From 7fca706e42cdb23d703d3cacf82e6617070a49e3 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:01:53 +0200 Subject: [PATCH 1/8] remote store gRPC spec update: introduce application level errors for recording registration --- .../proto/rerun/v0/common.proto | 12 ++++ .../proto/rerun/v0/remote_store.proto | 16 +++++ crates/store/re_remote_store_types/src/lib.rs | 12 ++++ .../src/v0/rerun.remote_store.v0.rs | 60 +++++++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto index 0f5d979cd81c..0ba85fe3eddc 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto @@ -161,3 +161,15 @@ enum SparseFillStrategy { NONE = 0; LATEST_AT_GLOBAL = 1; } + +// Error codes for application level errors +enum Code { + // unused + _NO_ERROR = 0; + + // object store access error + OBJECT_STORE_ERROR = 1; + + // metadata database access error + METADATA_DB_ERROR = 2; +} diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto index 4fe3b74c2e95..bcdc25be3ea1 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto @@ -27,6 +27,13 @@ message ObjectStorage { } message RegisterRecordingsResponse { + oneof response { + RegistrationSuccess success = 1; + RegistrationError error = 2; + } +} + +message RegistrationSuccess { // Note / TODO(zehiko): this implies we read the record (for example go through entire .rrd file // chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. // only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" @@ -34,6 +41,15 @@ message RegisterRecordingsResponse { repeated RecordingMetadata metadata = 2; } +message RegistrationError { + // error code + Code code = 1; + // url of the recording that failed to register + string url = 2; + // human readable details about the error + string message = 3; +} + // ---------------- GetRecordingMetadata ----------------- message GetRecordingMetadataRequest { diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs index 86126cf614ba..1e3db6a9d04d 100644 --- a/crates/store/re_remote_store_types/src/lib.rs +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -312,6 +312,18 @@ pub mod v0 { } } } + + // ------- Application level errors ------- + impl std::error::Error for RegistrationError {} + + impl std::fmt::Display for RegistrationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!( + "Failed to register recording: {}, error code: {}, error message: {}", + self.url, self.code, self.message + )) + } + } } #[cfg(test)] diff --git a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs index 9414f0fe4a41..32763da0c08b 100644 --- a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs @@ -209,6 +209,39 @@ impl SparseFillStrategy { } } } +/// Error codes for application level errors +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Code { + /// unused + NoError = 0, + /// object store access error + ObjectStoreError = 1, + /// metadata database access error + MetadataDbError = 2, +} +impl Code { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::NoError => "_NO_ERROR", + Self::ObjectStoreError => "OBJECT_STORE_ERROR", + Self::MetadataDbError => "METADATA_DB_ERROR", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "_NO_ERROR" => Some(Self::NoError), + "OBJECT_STORE_ERROR" => Some(Self::ObjectStoreError), + "METADATA_DB_ERROR" => Some(Self::MetadataDbError), + _ => None, + } + } +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegisterRecordingsRequest { #[prost(string, tag = "1")] @@ -228,6 +261,21 @@ pub struct ObjectStorage { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegisterRecordingsResponse { + #[prost(oneof = "register_recordings_response::Response", tags = "1, 2")] + pub response: ::core::option::Option, +} +/// Nested message and enum types in `RegisterRecordingsResponse`. +pub mod register_recordings_response { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Response { + #[prost(message, tag = "1")] + Success(super::RegistrationSuccess), + #[prost(message, tag = "2")] + Error(super::RegistrationError), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RegistrationSuccess { /// Note / TODO(zehiko): this implies we read the record (for example go through entire .rrd file /// chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. /// only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" @@ -236,6 +284,18 @@ pub struct RegisterRecordingsResponse { pub metadata: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct RegistrationError { + /// error code + #[prost(enumeration = "Code", tag = "1")] + pub code: i32, + /// url of the recording that failed to register + #[prost(string, tag = "2")] + pub url: ::prost::alloc::string::String, + /// human readable details about the error + #[prost(string, tag = "3")] + pub message: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct GetRecordingMetadataRequest { #[prost(message, optional, tag = "1")] pub recording_id: ::core::option::Option, From 22c5fca59ac563597b8d8026b24b3101b564d07f Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:49:06 +0200 Subject: [PATCH 2/8] recording metadata serialization --- .../proto/rerun/v0/remote_store.proto | 21 +++-- .../store/re_remote_store_types/src/codec.rs | 90 ++++++++++++++++++- .../src/v0/rerun.remote_store.v0.rs | 26 ++++-- 3 files changed, 120 insertions(+), 17 deletions(-) diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto index bcdc25be3ea1..ea50fc75c300 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto @@ -15,10 +15,22 @@ service StorageNode { // ---------------- RegisterRecording ------------------ message RegisterRecordingsRequest { + // human readable description of the recording string description = 1; + // information about recording's backing storage + // TODO(zehiko) add separate info about the "source" recording ObjectStorage obj_storage = 2; - // TODO(zehiko) should this be auto-discoverable? + // type of recording RecordingType typ = 3; + // (optional) any additional metadata that should be associated with the recording + // You can associate any arbtrirary number of columns with a specific recording + RecordingMetadata metadata = 4; +} + +// Recording metadata is single row arrow record batch +message RecordingMetadata { + EncoderVersion encoder_version = 1; + bytes payload = 2; } message ObjectStorage { @@ -57,13 +69,8 @@ message GetRecordingMetadataRequest { } message GetRecordingMetadataResponse { - RecordingMetadata metadata = 1; -} - -message RecordingMetadata { RecordingId id = 1; - Schema schema = 2; - repeated TimeMetadata time_metadata = 3; + RecordingMetadata metadata = 2; } message TimeMetadata { diff --git a/crates/store/re_remote_store_types/src/codec.rs b/crates/store/re_remote_store_types/src/codec.rs index 42acc31c9734..45561bb4241a 100644 --- a/crates/store/re_remote_store_types/src/codec.rs +++ b/crates/store/re_remote_store_types/src/codec.rs @@ -1,8 +1,11 @@ +use arrow2::array::Array as ArrowArray; +use arrow2::chunk::Chunk as ArrowChunk; +use arrow2::datatypes::Schema as ArrowSchema; use arrow2::error::Error as ArrowError; use arrow2::io::ipc::{read, write}; use re_dataframe::TransportChunk; -use crate::v0::EncoderVersion; +use crate::v0::{EncoderVersion, RecordingMetadata}; #[derive(Debug, thiserror::Error)] pub enum CodecError { @@ -23,6 +26,9 @@ pub enum CodecError { #[error("Unknown message header")] UnknownMessageHeader, + + #[error("Invalid argument: {0}")] + InvalidArgument(String), } #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)] @@ -154,11 +160,73 @@ pub fn decode(version: EncoderVersion, data: &[u8]) -> Result>, + ) -> Result { + if unit_batch.len() > 1 { + return Err(CodecError::InvalidArgument(format!( + "metadata record batch can only have a single row, batch with {} rows given", + unit_batch.len() + ))); + } + + match version { + EncoderVersion::V0 => { + let mut data: Vec = Vec::new(); + + let options = write::WriteOptions { compression: None }; + let mut sw = write::StreamWriter::new(&mut data, options); + + sw.start(schema, None) + .map_err(CodecError::ArrowSerialization)?; + sw.write(unit_batch, None) + .map_err(CodecError::ArrowSerialization)?; + sw.finish().map_err(CodecError::ArrowSerialization)?; + + Ok(Self { + encoder_version: version as i32, + payload: data, + }) + } + } + } + + /// Get arrow data from `RecordingMetadata` + pub fn data(&self) -> Result<(ArrowSchema, ArrowChunk>), CodecError> { + let mut reader = std::io::Cursor::new(self.payload.clone()); + + let metadata = + read::read_stream_metadata(&mut reader).map_err(CodecError::ArrowSerialization)?; + let mut stream = read::StreamReader::new(&mut reader, metadata, None); + + let schema = stream.schema().clone(); + // there should be at least one record batch in the stream + let stream_state = stream + .next() + .ok_or(CodecError::MissingRecordBatch)? + .map_err(CodecError::ArrowSerialization)?; + + match stream_state { + read::StreamState::Waiting => Err(CodecError::UnexpectedStreamState), + read::StreamState::Some(chunk) => Ok((schema, chunk)), + } + } +} + #[cfg(test)] mod tests { + + use arrow2::chunk::Chunk as ArrowChunk; + use arrow2::{array::Int32Array, datatypes::Field, datatypes::Schema as ArrowSchema}; use re_dataframe::external::re_chunk::{Chunk, RowId}; use re_log_types::{example_components::MyPoint, Timeline}; + use crate::v0::RecordingMetadata; use crate::{ codec::{decode, encode, CodecError, TransportMessageV0}, v0::EncoderVersion, @@ -250,4 +318,24 @@ mod tests { assert_eq!(expected_chunk, decoded_chunk); } + + #[test] + fn test_recording_metadata_serialization() { + let expected_schema = ArrowSchema::from(vec![Field::new( + "my_int", + arrow2::datatypes::DataType::Int32, + false, + )]); + let my_ints = Int32Array::from_slice(&[42]); + let expected_chunk = ArrowChunk::new(vec![Box::new(my_ints) as _]); + + let metadata = + RecordingMetadata::try_from(EncoderVersion::V0, &expected_schema, &expected_chunk) + .unwrap(); + + let (schema, chunk) = metadata.data().unwrap(); + + assert_eq!(expected_schema, schema); + assert_eq!(expected_chunk, chunk); + } } diff --git a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs index 32763da0c08b..f2cc86fc2787 100644 --- a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs @@ -244,13 +244,28 @@ impl Code { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegisterRecordingsRequest { + /// human readable description of the recording #[prost(string, tag = "1")] pub description: ::prost::alloc::string::String, + /// information about recording's backing storage + /// TODO(zehiko) add separate info about the "source" recording #[prost(message, optional, tag = "2")] pub obj_storage: ::core::option::Option, - /// TODO(zehiko) should this be auto-discoverable? + /// type of recording #[prost(enumeration = "RecordingType", tag = "3")] pub typ: i32, + /// (optional) any additional metadata that should be associated with the recording + /// You can associate any arbtrirary number of columns with a specific recording + #[prost(message, optional, tag = "4")] + pub metadata: ::core::option::Option, +} +/// Recording metadata is single row arrow record batch +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RecordingMetadata { + #[prost(enumeration = "EncoderVersion", tag = "1")] + pub encoder_version: i32, + #[prost(bytes = "vec", tag = "2")] + pub payload: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ObjectStorage { @@ -302,17 +317,10 @@ pub struct GetRecordingMetadataRequest { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetRecordingMetadataResponse { - #[prost(message, optional, tag = "1")] - pub metadata: ::core::option::Option, -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RecordingMetadata { #[prost(message, optional, tag = "1")] pub id: ::core::option::Option, #[prost(message, optional, tag = "2")] - pub schema: ::core::option::Option, - #[prost(message, repeated, tag = "3")] - pub time_metadata: ::prost::alloc::vec::Vec, + pub metadata: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct TimeMetadata { From eb2db7564bdf8f14889a43978662bb3094109cbf Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Fri, 25 Oct 2024 14:46:54 +0200 Subject: [PATCH 3/8] rebase --- .../proto/rerun/v0/remote_store.proto | 8 +------- crates/store/re_remote_store_types/src/codec.rs | 2 +- .../src/v0/rerun.remote_store.v0.rs | 16 +--------------- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto index ea50fc75c300..480ab7fcafc2 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto @@ -39,13 +39,6 @@ message ObjectStorage { } message RegisterRecordingsResponse { - oneof response { - RegistrationSuccess success = 1; - RegistrationError error = 2; - } -} - -message RegistrationSuccess { // Note / TODO(zehiko): this implies we read the record (for example go through entire .rrd file // chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. // only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" @@ -53,6 +46,7 @@ message RegistrationSuccess { repeated RecordingMetadata metadata = 2; } +// Server can include details about the error as part of gRPC error (Status) message RegistrationError { // error code Code code = 1; diff --git a/crates/store/re_remote_store_types/src/codec.rs b/crates/store/re_remote_store_types/src/codec.rs index 45561bb4241a..b8cf09fdb37e 100644 --- a/crates/store/re_remote_store_types/src/codec.rs +++ b/crates/store/re_remote_store_types/src/codec.rs @@ -160,7 +160,7 @@ pub fn decode(version: EncoderVersion, data: &[u8]) -> Result, -} -/// Nested message and enum types in `RegisterRecordingsResponse`. -pub mod register_recordings_response { - #[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Response { - #[prost(message, tag = "1")] - Success(super::RegistrationSuccess), - #[prost(message, tag = "2")] - Error(super::RegistrationError), - } -} -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RegistrationSuccess { /// Note / TODO(zehiko): this implies we read the record (for example go through entire .rrd file /// chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. /// only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" @@ -298,6 +283,7 @@ pub struct RegistrationSuccess { #[prost(message, repeated, tag = "2")] pub metadata: ::prost::alloc::vec::Vec, } +/// Server can include details about the error as part of gRPC error (Status) #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegistrationError { /// error code From 43ddd62f10cb9efd60db66ff8976bf205ef79fb0 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:36:14 +0200 Subject: [PATCH 4/8] rebase --- .../proto/rerun/v0/common.proto | 4 ++-- .../proto/rerun/v0/remote_store.proto | 2 +- .../src/v0/rerun.remote_store.v0.rs | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto index 0ba85fe3eddc..914e4c281210 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto @@ -163,9 +163,9 @@ enum SparseFillStrategy { } // Error codes for application level errors -enum Code { +enum ErrorCode { // unused - _NO_ERROR = 0; + _UNUSED = 0; // object store access error OBJECT_STORE_ERROR = 1; diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto index 480ab7fcafc2..48626eb3d19d 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto @@ -49,7 +49,7 @@ message RegisterRecordingsResponse { // Server can include details about the error as part of gRPC error (Status) message RegistrationError { // error code - Code code = 1; + ErrorCode code = 1; // url of the recording that failed to register string url = 2; // human readable details about the error diff --git a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs index d075c287530c..cdaf77447e4a 100644 --- a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs @@ -212,22 +212,22 @@ impl SparseFillStrategy { /// Error codes for application level errors #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] -pub enum Code { +pub enum ErrorCode { /// unused - NoError = 0, + Unused = 0, /// object store access error ObjectStoreError = 1, /// metadata database access error MetadataDbError = 2, } -impl Code { +impl ErrorCode { /// String value of the enum field names used in the ProtoBuf definition. /// /// The values are not transformed in any way and thus are considered stable /// (if the ProtoBuf definition does not change) and safe for programmatic use. pub fn as_str_name(&self) -> &'static str { match self { - Self::NoError => "_NO_ERROR", + Self::Unused => "_UNUSED", Self::ObjectStoreError => "OBJECT_STORE_ERROR", Self::MetadataDbError => "METADATA_DB_ERROR", } @@ -235,7 +235,7 @@ impl Code { /// Creates an enum from field names used in the ProtoBuf definition. pub fn from_str_name(value: &str) -> ::core::option::Option { match value { - "_NO_ERROR" => Some(Self::NoError), + "_UNUSED" => Some(Self::Unused), "OBJECT_STORE_ERROR" => Some(Self::ObjectStoreError), "METADATA_DB_ERROR" => Some(Self::MetadataDbError), _ => None, @@ -287,7 +287,7 @@ pub struct RegisterRecordingsResponse { #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegistrationError { /// error code - #[prost(enumeration = "Code", tag = "1")] + #[prost(enumeration = "ErrorCode", tag = "1")] pub code: i32, /// url of the recording that failed to register #[prost(string, tag = "2")] From ff863423babfdce88dfdce7f4d44c002d77a8c6a Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:47:26 +0200 Subject: [PATCH 5/8] rebase --- Cargo.lock | 2 + crates/build/re_build_info/src/build_info.rs | 9 + crates/build/re_build_info/src/lib.rs | 1 + crates/build/re_build_tools/src/lib.rs | 44 +- .../re_types_builder/src/codegen/rust/api.rs | 19 +- .../src/codegen/rust/reflection.rs | 36 +- .../definitions/rerun/components/blob.fbs | 2 +- .../rerun/components/image_buffer.fbs | 2 +- crates/store/re_types/src/components/blob.rs | 2 +- .../re_types/src/components/image_buffer.rs | 2 +- .../src/components/show_labels_ext.rs | 9 - .../store/re_types/src/datatypes/blob_ext.rs | 7 - crates/store/re_types_core/src/reflection.rs | 161 +++- crates/store/re_video/Cargo.toml | 2 + crates/store/re_video/build.rs | 2 + crates/store/re_video/src/lib.rs | 14 +- crates/top/rerun/src/commands/entrypoint.rs | 2 +- crates/utils/re_analytics/src/lib.rs | 2 + .../re_selection_panel/src/defaults_ui.rs | 19 +- .../re_selection_panel/src/visualizer_ui.rs | 11 +- crates/viewer/re_space_view/src/query.rs | 28 +- .../viewer/re_space_view/src/results_ext.rs | 19 +- .../viewer/re_space_view_spatial/src/ui_3d.rs | 8 +- crates/viewer/re_ui/src/command.rs | 9 +- crates/viewer/re_viewer/src/app.rs | 81 +- crates/viewer/re_viewer/src/reflection/mod.rs | 194 ++--- crates/viewer/re_viewer/src/ui/rerun_menu.rs | 8 + .../src/component_fallbacks.rs | 19 +- .../src/component_ui_registry.rs | 10 +- .../re_viewer_context/src/viewer_context.rs | 33 + .../src/view_properties.rs | 11 +- docs/content/concepts/app-model.md | 189 +++++ docs/content/concepts/apps-and-recordings.md | 52 +- docs/content/concepts/blueprint.md | 2 +- docs/content/howto/embed-rerun-viewer.md | 2 +- docs/content/howto/extend.md | 2 +- .../howto/logging/shared-recordings.md | 12 +- docs/content/howto/notebook.md | 2 +- docs/content/howto/using-native-loggers.md | 18 +- .../configure-viewer-through-code.md | 2 +- .../howto/visualization/reuse-blueprints.md | 44 + docs/content/reference/dataframes.md | 4 +- docs/content/reference/sdk/operating-modes.md | 2 + docs/snippets/CMakeLists.txt | 1 + .../all/concepts/app-model/native-async.cpp | 12 + .../all/concepts/app-model/native-async.py | 12 + .../all/concepts/app-model/native-async.rs | 10 + .../all/concepts/app-model/native-sync.cpp | 13 + .../all/concepts/app-model/native-sync.py | 13 + .../all/concepts/app-model/native-sync.rs | 10 + .../all/tutorials/custom-application-id.cpp | 1 + .../all/tutorials/custom-application-id.py | 1 + .../all/tutorials/custom-application-id.rs | 1 + .../all/tutorials/custom-recording-id.py | 2 - .../tutorials/visualization/load_blueprint.py | 12 + .../tutorials/visualization/save_blueprint.py | 23 + docs/snippets/snippets.toml | 5 + pixi.lock | 750 +++++++++--------- rerun_py/pyproject.toml | 2 + scripts/lint.py | 4 + 60 files changed, 1336 insertions(+), 635 deletions(-) create mode 100644 docs/content/concepts/app-model.md create mode 100644 docs/content/howto/visualization/reuse-blueprints.md create mode 100644 docs/snippets/all/concepts/app-model/native-async.cpp create mode 100755 docs/snippets/all/concepts/app-model/native-async.py create mode 100644 docs/snippets/all/concepts/app-model/native-async.rs create mode 100644 docs/snippets/all/concepts/app-model/native-sync.cpp create mode 100755 docs/snippets/all/concepts/app-model/native-sync.py create mode 100644 docs/snippets/all/concepts/app-model/native-sync.rs create mode 100644 docs/snippets/all/tutorials/custom-application-id.cpp create mode 100644 docs/snippets/all/tutorials/custom-application-id.py create mode 100644 docs/snippets/all/tutorials/custom-application-id.rs create mode 100644 docs/snippets/all/tutorials/visualization/load_blueprint.py create mode 100644 docs/snippets/all/tutorials/visualization/save_blueprint.py diff --git a/Cargo.lock b/Cargo.lock index d9081f07edde..7b39947f369e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6186,6 +6186,8 @@ dependencies = [ "indicatif", "itertools 0.13.0", "parking_lot", + "re_build_info", + "re_build_tools", "re_log", "re_mp4", "re_rav1d", diff --git a/crates/build/re_build_info/src/build_info.rs b/crates/build/re_build_info/src/build_info.rs index 55abb7290e60..e81cc03dab01 100644 --- a/crates/build/re_build_info/src/build_info.rs +++ b/crates/build/re_build_info/src/build_info.rs @@ -14,6 +14,9 @@ pub struct BuildInfo { /// `CARGO_PKG_NAME` pub crate_name: &'static str, + /// Space-separated names of all features enabled for this crate. + pub features: &'static str, + /// Crate version, parsed from `CARGO_PKG_VERSION`, ignoring any `+metadata` suffix. pub version: super::CrateVersion, @@ -74,6 +77,7 @@ impl std::fmt::Display for BuildInfo { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { crate_name, + features, version, rustc_version, llvm_version, @@ -89,6 +93,10 @@ impl std::fmt::Display for BuildInfo { write!(f, "{crate_name} {version}")?; + if !features.is_empty() { + write!(f, " ({features})")?; + } + if let Some(rustc_version) = rustc_version { write!(f, " [{rustc_version}")?; if let Some(llvm_version) = llvm_version { @@ -147,6 +155,7 @@ impl CrateVersion { fn crate_version_from_build_info_string() { let build_info = BuildInfo { crate_name: "re_build_info", + features: "default extra", version: CrateVersion { major: 0, minor: 10, diff --git a/crates/build/re_build_info/src/lib.rs b/crates/build/re_build_info/src/lib.rs index 42501cd64243..d7b4208e6a76 100644 --- a/crates/build/re_build_info/src/lib.rs +++ b/crates/build/re_build_info/src/lib.rs @@ -15,6 +15,7 @@ macro_rules! build_info { () => { $crate::BuildInfo { crate_name: env!("CARGO_PKG_NAME"), + features: env!("RE_BUILD_FEATURES"), version: $crate::CrateVersion::parse(env!("CARGO_PKG_VERSION")), rustc_version: env!("RE_BUILD_RUSTC_VERSION"), llvm_version: env!("RE_BUILD_LLVM_VERSION"), diff --git a/crates/build/re_build_tools/src/lib.rs b/crates/build/re_build_tools/src/lib.rs index 316e335f58aa..3bf2da9c7d08 100644 --- a/crates/build/re_build_tools/src/lib.rs +++ b/crates/build/re_build_tools/src/lib.rs @@ -194,6 +194,16 @@ pub fn export_build_info_vars_for_crate(crate_name: &str) { ); } } + + if environment == Environment::PublishingCrates { + // We can't query this during `cargo publish`, but we also don't need the info. + set_env("RE_BUILD_FEATURES", ""); + } else { + set_env( + "RE_BUILD_FEATURES", + &enabled_features_of(crate_name).unwrap().join(" "), + ); + } } /// ISO 8601 / RFC 3339 build time. @@ -269,7 +279,39 @@ fn rust_llvm_versions() -> anyhow::Result<(String, String)> { )) } -/// Returns info parsed from an invocation of the `cargo metadata` command +/// Returns info parsed from an invocation of the `cargo metadata` command. +/// +/// You may not run this during crate publishing. pub fn cargo_metadata() -> anyhow::Result { + // See https://github.com/rerun-io/rerun/pull/7885 + anyhow::ensure!( + Environment::detect() != Environment::PublishingCrates, + "Can't get metadata during crate publishing - it would create a Cargo.lock file" + ); + Ok(cargo_metadata::MetadataCommand::new().exec()?) } + +/// Returns a list of all the enabled features of the given package. +/// +/// You may not run this during crate publishing. +pub fn enabled_features_of(crate_name: &str) -> anyhow::Result> { + let metadata = cargo_metadata()?; + + let mut features = vec![]; + for package in &metadata.packages { + if package.name == crate_name { + for feature in package.features.keys() { + println!("Checking if feature is enabled: {feature:?}"); + let feature_in_screaming_snake_case = + feature.to_ascii_uppercase().replace('-', "_"); + if std::env::var(format!("CARGO_FEATURE_{feature_in_screaming_snake_case}")).is_ok() + { + features.push(feature.clone()); + } + } + } + } + + Ok(features) +} diff --git a/crates/build/re_types_builder/src/codegen/rust/api.rs b/crates/build/re_types_builder/src/codegen/rust/api.rs index 4f31be5ed752..5af0b8486865 100644 --- a/crates/build/re_types_builder/src/codegen/rust/api.rs +++ b/crates/build/re_types_builder/src/codegen/rust/api.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use anyhow::Context as _; use camino::{Utf8Path, Utf8PathBuf}; @@ -57,6 +57,7 @@ impl CodeGenerator for RustCodeGenerator { arrow_registry: &ArrowRegistry, ) -> BTreeMap { let mut files_to_write: BTreeMap = Default::default(); + let mut extension_contents_for_fqname: HashMap = Default::default(); for object_kind in ObjectKind::ALL { self.generate_folder( @@ -65,11 +66,17 @@ impl CodeGenerator for RustCodeGenerator { arrow_registry, object_kind, &mut files_to_write, + &mut extension_contents_for_fqname, ); } generate_blueprint_validation(reporter, objects, &mut files_to_write); - generate_reflection(reporter, objects, &mut files_to_write); + generate_reflection( + reporter, + objects, + &extension_contents_for_fqname, + &mut files_to_write, + ); files_to_write } @@ -83,6 +90,7 @@ impl RustCodeGenerator { arrow_registry: &ArrowRegistry, object_kind: ObjectKind, files_to_write: &mut BTreeMap, + extension_contents_for_fqname: &mut HashMap, ) { let crates_root_path = self.workspace_path.join("crates"); @@ -104,9 +112,14 @@ impl RustCodeGenerator { let filename = format!("{filename_stem}.rs"); let filepath = module_path.join(filename); - let mut code = generate_object_file(reporter, objects, arrow_registry, obj, &filepath); + if let Ok(extension_contents) = + std::fs::read_to_string(module_path.join(format!("{filename_stem}_ext.rs"))) + { + extension_contents_for_fqname.insert(obj.fqname.clone(), extension_contents); + } + if crate_name == "re_types_core" { code = code.replace("::re_types_core", "crate"); } diff --git a/crates/build/re_types_builder/src/codegen/rust/reflection.rs b/crates/build/re_types_builder/src/codegen/rust/reflection.rs index 2a6009be25fb..2a281250466d 100644 --- a/crates/build/re_types_builder/src/codegen/rust/reflection.rs +++ b/crates/build/re_types_builder/src/codegen/rust/reflection.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; use camino::Utf8PathBuf; use proc_macro2::TokenStream; @@ -6,7 +6,8 @@ use quote::{format_ident, quote}; use crate::{ codegen::{autogen_warning, Target}, - ObjectKind, Objects, Reporter, ATTR_RERUN_COMPONENT_REQUIRED, + ObjectKind, Objects, Reporter, ATTR_RERUN_COMPONENT_REQUIRED, ATTR_RUST_DERIVE, + ATTR_RUST_DERIVE_ONLY, }; use super::util::{append_tokens, doc_as_lines}; @@ -15,6 +16,7 @@ use super::util::{append_tokens, doc_as_lines}; pub fn generate_reflection( reporter: &Reporter, objects: &Objects, + extension_contents_for_fqname: &HashMap, files_to_write: &mut BTreeMap, ) { // Put into its own subfolder since codegen is set up in a way that it thinks that everything @@ -23,7 +25,12 @@ pub fn generate_reflection( let path = Utf8PathBuf::from("crates/viewer/re_viewer/src/reflection/mod.rs"); let mut imports = BTreeSet::new(); - let component_reflection = generate_component_reflection(reporter, objects, &mut imports); + let component_reflection = generate_component_reflection( + reporter, + objects, + extension_contents_for_fqname, + &mut imports, + ); let archetype_reflection = generate_archetype_reflection(reporter, objects); let mut code = format!("// {}\n\n", autogen_warning!()); @@ -77,6 +84,7 @@ pub fn generate_reflection( fn generate_component_reflection( reporter: &Reporter, objects: &Objects, + extension_contents_for_fqname: &HashMap, imports: &mut BTreeSet, ) -> TokenStream { let mut quoted_pairs = Vec::new(); @@ -111,11 +119,31 @@ fn generate_component_reflection( obj.is_experimental(), ) .join("\n"); + + // Emit custom placeholder if there's a default implementation + let auto_derive_default = obj.is_enum() // All enums have default values currently! + || obj + .try_get_attr::(ATTR_RUST_DERIVE_ONLY) + .or_else(|| obj.try_get_attr::(ATTR_RUST_DERIVE)) + .map_or(false, |derives| derives.contains("Default")); + let has_custom_default_impl = + extension_contents_for_fqname + .get(&obj.fqname) + .map_or(false, |contents| { + contents.contains(&format!("impl Default for {}", &obj.name)) + || contents.contains(&format!("impl Default for super::{}", &obj.name)) + }); + let custom_placeholder = if auto_derive_default || has_custom_default_impl { + quote! { Some(#type_name::default().to_arrow()?) } + } else { + quote! { None } + }; + let quoted_reflection = quote! { ComponentReflection { docstring_md: #docstring_md, - placeholder: Some(#type_name::default().to_arrow()?), + custom_placeholder: #custom_placeholder, } }; quoted_pairs.push(quote! { (#quoted_name, #quoted_reflection) }); diff --git a/crates/store/re_types/definitions/rerun/components/blob.fbs b/crates/store/re_types/definitions/rerun/components/blob.fbs index b6d6ed9ef91c..d391371b30c2 100644 --- a/crates/store/re_types/definitions/rerun/components/blob.fbs +++ b/crates/store/re_types/definitions/rerun/components/blob.fbs @@ -9,7 +9,7 @@ table Blob ( "attr.arrow.transparent", "attr.python.aliases": "bytes, npt.NDArray[np.uint8]", "attr.python.array_aliases": "bytes, npt.NDArray[np.uint8]", - "attr.rust.derive": "Default, PartialEq, Eq", + "attr.rust.derive": "PartialEq, Eq", "attr.rust.repr": "transparent" ) { data: rerun.datatypes.Blob (order: 100); diff --git a/crates/store/re_types/definitions/rerun/components/image_buffer.fbs b/crates/store/re_types/definitions/rerun/components/image_buffer.fbs index 10981a26e489..db63f79a09c7 100644 --- a/crates/store/re_types/definitions/rerun/components/image_buffer.fbs +++ b/crates/store/re_types/definitions/rerun/components/image_buffer.fbs @@ -9,7 +9,7 @@ table ImageBuffer ( "attr.arrow.transparent", "attr.python.aliases": "bytes, npt.NDArray[np.uint8]", "attr.python.array_aliases": "bytes, npt.NDArray[np.uint8]", - "attr.rust.derive": "Default, PartialEq, Eq", + "attr.rust.derive": "PartialEq, Eq", "attr.rust.repr": "transparent" ) { buffer: rerun.datatypes.Blob (order: 100); diff --git a/crates/store/re_types/src/components/blob.rs b/crates/store/re_types/src/components/blob.rs index 5eaa2871021b..2d5e717b8ab5 100644 --- a/crates/store/re_types/src/components/blob.rs +++ b/crates/store/re_types/src/components/blob.rs @@ -21,7 +21,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: A binary blob of data. /// /// Ref-counted internally and therefore cheap to clone. -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct Blob(pub crate::datatypes::Blob); diff --git a/crates/store/re_types/src/components/image_buffer.rs b/crates/store/re_types/src/components/image_buffer.rs index 969b2cd0825c..954a4cff5a52 100644 --- a/crates/store/re_types/src/components/image_buffer.rs +++ b/crates/store/re_types/src/components/image_buffer.rs @@ -21,7 +21,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: A buffer that is known to store image data. /// /// To interpret the contents of this buffer, see, [`components::ImageFormat`][crate::components::ImageFormat]. -#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct ImageBuffer(pub crate::datatypes::Blob); diff --git a/crates/store/re_types/src/components/show_labels_ext.rs b/crates/store/re_types/src/components/show_labels_ext.rs index 8914bba71ea0..67931c338f01 100644 --- a/crates/store/re_types/src/components/show_labels_ext.rs +++ b/crates/store/re_types/src/components/show_labels_ext.rs @@ -1,14 +1,5 @@ use super::ShowLabels; -impl Default for ShowLabels { - #[inline] - fn default() -> Self { - // We don't actually use this default -- visualizers choose a fallback value -- - // but it is necessary to satisfy `re_viewer::reflection::generate_component_reflection()`. - Self(true.into()) - } -} - impl From for bool { #[inline] fn from(value: ShowLabels) -> Self { diff --git a/crates/store/re_types/src/datatypes/blob_ext.rs b/crates/store/re_types/src/datatypes/blob_ext.rs index 1d48545d3622..55897c6f59b0 100644 --- a/crates/store/re_types/src/datatypes/blob_ext.rs +++ b/crates/store/re_types/src/datatypes/blob_ext.rs @@ -20,13 +20,6 @@ impl From> for Blob { } } -impl Default for Blob { - #[inline] - fn default() -> Self { - Self(Vec::new().into()) - } -} - impl std::ops::Deref for Blob { type Target = re_types_core::ArrowBuffer; diff --git a/crates/store/re_types_core/src/reflection.rs b/crates/store/re_types_core/src/reflection.rs index 8e817cacefdb..b183fc14ca64 100644 --- a/crates/store/re_types_core/src/reflection.rs +++ b/crates/store/re_types_core/src/reflection.rs @@ -51,6 +51,156 @@ impl Reflection { } } +/// Computes a placeholder for a given arrow datatype. +/// +/// With the exception of a few unsupported types, +/// a placeholder is an array of the given datatype with a single element. +/// This single element is (recursively if necessary) a sort of arbitrary zero value +/// which can be used as a starting point. +/// E.g. the default for a an integer array is an array containing a single zero. +/// +/// For unsupported types this yields an empty array instead. +/// +/// See also [`ComponentReflection::custom_placeholder`]. +pub fn generic_placeholder_for_datatype( + datatype: &arrow2::datatypes::DataType, +) -> Box { + use arrow2::{ + array, + datatypes::{DataType, IntervalUnit}, + types, + }; + + match datatype { + DataType::Null => Box::new(array::NullArray::new(datatype.clone(), 1)), + DataType::Boolean => Box::new(array::BooleanArray::from_slice([false])), + DataType::Int8 => Box::new(array::Int8Array::from_slice([0])), + DataType::Int16 => Box::new(array::Int16Array::from_slice([0])), + + DataType::Int32 + | DataType::Date32 + | DataType::Time32(_) + | DataType::Interval(IntervalUnit::YearMonth) => { + // TODO(andreas): Do we have to further distinguish these types? They do share the physical type. + Box::new(array::Int32Array::from_slice([0])) + } + DataType::Int64 + | DataType::Date64 + | DataType::Timestamp(_, _) + | DataType::Time64(_) + | DataType::Duration(_) => { + // TODO(andreas): Do we have to further distinguish these types? They do share the physical type. + Box::new(array::Int64Array::from_slice([0])) + } + + DataType::UInt8 => Box::new(array::UInt8Array::from_slice([0])), + DataType::UInt16 => Box::new(array::UInt16Array::from_slice([0])), + DataType::UInt32 => Box::new(array::UInt32Array::from_slice([0])), + DataType::UInt64 => Box::new(array::UInt64Array::from_slice([0])), + DataType::Float16 => Box::new(array::Float16Array::from_slice([types::f16::from_f32(0.0)])), + DataType::Float32 => Box::new(array::Float32Array::from_slice([0.0])), + DataType::Float64 => Box::new(array::Float64Array::from_slice([0.0])), + + DataType::Interval(IntervalUnit::DayTime) => { + Box::new(array::DaysMsArray::from_slice([types::days_ms::new(0, 0)])) + } + DataType::Interval(IntervalUnit::MonthDayNano) => { + Box::new(array::MonthsDaysNsArray::from_slice([ + types::months_days_ns::new(0, 0, 0), + ])) + } + + DataType::Binary => Box::new(array::BinaryArray::::from_slice([[]])), + DataType::FixedSizeBinary(size) => Box::new(array::FixedSizeBinaryArray::from_iter( + std::iter::once(Some(vec![0; *size])), + *size, + )), + DataType::LargeBinary => Box::new(array::BinaryArray::::from_slice([[]])), + DataType::Utf8 => Box::new(array::Utf8Array::::from_slice([""])), + DataType::LargeUtf8 => Box::new(array::Utf8Array::::from_slice([""])), + DataType::List(field) => { + let inner = generic_placeholder_for_datatype(field.data_type()); + let offsets = arrow2::offset::Offsets::try_from_lengths(std::iter::once(inner.len())) + .expect("failed to create offsets buffer"); + Box::new(array::ListArray::::new( + datatype.clone(), + offsets.into(), + inner, + None, + )) + } + + // TODO(andreas): Unsupported type. + // What we actually want here is an array containing a single array of size `size`. + // But it's a bit tricky to build, because it doesn't look like we can concatenate `size` many arrays. + DataType::FixedSizeList(_field, size) => { + Box::new(array::FixedSizeListArray::new_null(datatype.clone(), *size)) + } + + DataType::LargeList(field) => { + let inner = generic_placeholder_for_datatype(field.data_type()); + let offsets = arrow2::offset::Offsets::try_from_lengths(std::iter::once(inner.len())) + .expect("failed to create offsets buffer"); + Box::new(array::ListArray::::new( + datatype.clone(), + offsets.into(), + inner, + None, + )) + } + DataType::Struct(fields) => { + let inners = fields + .iter() + .map(|field| generic_placeholder_for_datatype(field.data_type())); + Box::new(array::StructArray::new( + datatype.clone(), + inners.collect(), + None, + )) + } + DataType::Union(fields, _types, _union_mode) => { + if let Some(first_field) = fields.first() { + let first_field = generic_placeholder_for_datatype(first_field.data_type()); + let first_field_len = first_field.len(); // Should be 1, but let's play this safe! + let other_fields = fields + .iter() + .skip(1) + .map(|field| array::new_empty_array(field.data_type().clone())); + let fields = std::iter::once(first_field).chain(other_fields); + + Box::new(array::UnionArray::new( + datatype.clone(), + std::iter::once(0).collect(), // Single element of type 0. + fields.collect(), + Some(std::iter::once(first_field_len as i32).collect()), + )) + } else { + // Pathological case: a union with no fields can't have a placeholder with a single element? + array::new_empty_array(datatype.clone()) + } + } + + // TODO(andreas): Unsupported types. Fairly complex to build and we don't use it so far. + DataType::Map(_field, _) => Box::new(array::MapArray::new_empty(datatype.clone())), + + // TODO(andreas): Unsupported type. Has only `try_new` meaning we'd have to handle all error cases. + // But also we don't use this today anyways. + DataType::Dictionary(_integer_type, _arc, _sorted) => { + array::new_empty_array(datatype.clone()) // Rust type varies per integer type, use utility instead. + } + + DataType::Decimal(_, _) => Box::new(array::Int128Array::from_slice([0])), + + DataType::Decimal256(_, _) => { + Box::new(array::Int256Array::from_slice([types::i256::from_words( + 0, 0, + )])) + } + + DataType::Extension(_, datatype, _) => generic_placeholder_for_datatype(datatype), + } +} + /// Runtime reflection about components. pub type ComponentReflectionMap = nohash_hasher::IntMap; @@ -60,12 +210,15 @@ pub struct ComponentReflection { /// Markdown docstring for the component. pub docstring_md: &'static str, - /// Placeholder value, used whenever no fallback was provided explicitly. + /// Custom placeholder value, used when not fallback was provided. /// - /// This is usually the default value of the component, serialized. + /// This is usually the default value of the component (if any), serialized. /// - /// This is useful as a base fallback value when displaying UI. - pub placeholder: Option>, + /// Placeholders are useful as a base fallback value when displaying UI, + /// especially when it's necessary to have a starting value for edit ui. + /// Typically, this is only used when `FallbackProvider`s are not available. + /// If there's no custom placeholder, a placeholder can be derived from the arrow datatype. + pub custom_placeholder: Option>, } /// Runtime reflection about archetypes. diff --git a/crates/store/re_video/Cargo.toml b/crates/store/re_video/Cargo.toml index 4d84f4380f16..e47edb47bbe5 100644 --- a/crates/store/re_video/Cargo.toml +++ b/crates/store/re_video/Cargo.toml @@ -37,6 +37,7 @@ nasm = [ [dependencies] +re_build_info.workspace = true re_log.workspace = true re_tracing.workspace = true @@ -66,6 +67,7 @@ criterion.workspace = true # For build.rs: [build-dependencies] +re_build_tools.workspace = true cfg_aliases.workspace = true diff --git a/crates/store/re_video/build.rs b/crates/store/re_video/build.rs index 773e9ed9afa4..261ccb770ba3 100644 --- a/crates/store/re_video/build.rs +++ b/crates/store/re_video/build.rs @@ -1,4 +1,6 @@ fn main() { + re_build_tools::export_build_info_vars_for_crate(env!("CARGO_PKG_NAME")); + // uncomment these when we update to Rust 1.80: https://blog.rust-lang.org/2024/05/06/check-cfg.html // println!("cargo::rustc-check-cfg=cfg(native)"); // println!("cargo::rustc-check-cfg=cfg(linux_arm64)"); diff --git a/crates/store/re_video/src/lib.rs b/crates/store/re_video/src/lib.rs index b007518fb2f4..d38a194da8c9 100644 --- a/crates/store/re_video/src/lib.rs +++ b/crates/store/re_video/src/lib.rs @@ -13,15 +13,7 @@ pub use self::{ time::{Time, Timescale}, }; -/// Which features was this crate compiled with? -pub fn features() -> Vec<&'static str> { - // TODO(emilk): is there a helper crate for this? - let mut features = vec![]; - if cfg!(feature = "av1") { - features.push("av1"); - } - if cfg!(feature = "nasm") { - features.push("nasm"); - } - features +/// Returns information about this crate +pub fn build_info() -> re_build_info::BuildInfo { + re_build_info::build_info!() } diff --git a/crates/top/rerun/src/commands/entrypoint.rs b/crates/top/rerun/src/commands/entrypoint.rs index a081b6f6419a..6c3b6389907e 100644 --- a/crates/top/rerun/src/commands/entrypoint.rs +++ b/crates/top/rerun/src/commands/entrypoint.rs @@ -553,7 +553,7 @@ where if args.version { println!("{build_info}"); - println!("Video features: {}", re_video::features().join(" ")); + println!("Video features: {}", re_video::build_info().features); return Ok(0); } diff --git a/crates/utils/re_analytics/src/lib.rs b/crates/utils/re_analytics/src/lib.rs index 99dd49fc573b..a0a10c8e7b0d 100644 --- a/crates/utils/re_analytics/src/lib.rs +++ b/crates/utils/re_analytics/src/lib.rs @@ -345,6 +345,7 @@ impl Properties for re_build_info::BuildInfo { let git_hash = self.git_hash_or_tag(); let Self { crate_name: _, + features, version, rustc_version, llvm_version, @@ -355,6 +356,7 @@ impl Properties for re_build_info::BuildInfo { datetime, } = self; + event.insert("features", features); event.insert("git_hash", git_hash); event.insert("rerun_version", version.to_string()); event.insert("rust_version", rustc_version); diff --git a/crates/viewer/re_selection_panel/src/defaults_ui.rs b/crates/viewer/re_selection_panel/src/defaults_ui.rs index 5663c7131b3a..02695a9bd529 100644 --- a/crates/viewer/re_selection_panel/src/defaults_ui.rs +++ b/crates/viewer/re_selection_panel/src/defaults_ui.rs @@ -290,22 +290,13 @@ fn add_popup_ui( // - Finally, fall back on the default value from the component registry. // TODO(jleibs): Is this the right place for fallbacks to come from? - let Some(initial_data) = ctx - .visualizer_collection - .get_by_identifier(viz) - .ok() - .and_then(|sys| { - sys.fallback_provider() - .fallback_for(&query_context, component_name) - .ok() - }) - else { - re_log::warn!( - "Could not identify an initial value for: {}", - component_name - ); + let Ok(visualizer) = ctx.visualizer_collection.get_by_identifier(viz) else { + re_log::warn!("Could not find visualizer for: {}", viz); return; }; + let initial_data = visualizer + .fallback_provider() + .fallback_for(&query_context, component_name); match Chunk::builder(defaults_path.clone()) .with_row( diff --git a/crates/viewer/re_selection_panel/src/visualizer_ui.rs b/crates/viewer/re_selection_panel/src/visualizer_ui.rs index 29671a65a176..89292d90f028 100644 --- a/crates/viewer/re_selection_panel/src/visualizer_ui.rs +++ b/crates/viewer/re_selection_panel/src/visualizer_ui.rs @@ -205,16 +205,9 @@ fn visualizer_components( let result_default = query_result.defaults.get(&component_name); let raw_default = non_empty_component_batch_raw(result_default, &component_name); - let raw_fallback = match visualizer + let raw_fallback = visualizer .fallback_provider() - .fallback_for(&query_ctx, component_name) - { - Ok(fallback) => fallback, - Err(err) => { - re_log::warn_once!("Failed to get fallback for component {component_name}: {err}"); - continue; // TODO(andreas): Don't give up on the entire component because of this. Show an error instead. - } - }; + .fallback_for(&query_ctx, component_name); // Determine where the final value comes from. // Putting this into an enum makes it easier to reason about the next steps. diff --git a/crates/viewer/re_space_view/src/query.rs b/crates/viewer/re_space_view/src/query.rs index b4909a518008..54b8c1f6624c 100644 --- a/crates/viewer/re_space_view/src/query.rs +++ b/crates/viewer/re_space_view/src/query.rs @@ -1,12 +1,16 @@ use nohash_hasher::IntSet; -use crate::results_ext::{HybridLatestAtResults, HybridRangeResults}; -use crate::HybridResults; -use re_chunk_store::{LatestAtQuery, RangeQuery, RowId}; +use crate::{ + results_ext::{HybridLatestAtResults, HybridRangeResults}, + HybridResults, +}; +use re_chunk_store::{external::re_chunk::ArrowArray, LatestAtQuery, RangeQuery, RowId}; use re_log_types::{TimeInt, Timeline}; use re_query::LatestAtResults; use re_types_core::{Archetype, ComponentName}; -use re_viewer_context::{DataResult, QueryRange, ViewContext, ViewQuery, ViewerContext}; +use re_viewer_context::{ + DataResult, QueryContext, QueryRange, ViewContext, ViewQuery, ViewerContext, +}; // --- @@ -244,9 +248,10 @@ pub trait DataResultQuery { fn best_fallback_for<'a>( &self, - ctx: &'a ViewContext<'a>, + query_ctx: &'a QueryContext<'a>, + visualizer_collection: &'a re_viewer_context::VisualizerCollection, component: re_types_core::ComponentName, - ) -> Option<&'a dyn re_viewer_context::ComponentFallbackProvider>; + ) -> Box; } impl DataResultQuery for DataResult { @@ -283,20 +288,21 @@ impl DataResultQuery for DataResult { fn best_fallback_for<'a>( &self, - ctx: &'a ViewContext<'a>, + query_ctx: &'a QueryContext<'a>, + visualizer_collection: &'a re_viewer_context::VisualizerCollection, component: re_types_core::ComponentName, - ) -> Option<&'a dyn re_viewer_context::ComponentFallbackProvider> { + ) -> Box { // TODO(jleibs): This should be cached somewhere for vis in &self.visualizers { - let Ok(vis) = ctx.visualizer_collection.get_by_identifier(*vis) else { + let Ok(vis) = visualizer_collection.get_by_identifier(*vis) else { continue; }; if vis.visualizer_query_info().queried.contains(&component) { - return Some(vis.fallback_provider()); + return vis.fallback_provider().fallback_for(query_ctx, component); } } - None + query_ctx.viewer_ctx.placeholder_for(component) } } diff --git a/crates/viewer/re_space_view/src/results_ext.rs b/crates/viewer/re_space_view/src/results_ext.rs index 5be4920c8402..ac9c8e195b5d 100644 --- a/crates/viewer/re_space_view/src/results_ext.rs +++ b/crates/viewer/re_space_view/src/results_ext.rs @@ -50,11 +50,7 @@ impl<'a> HybridLatestAtResults<'a> { .or_else(|| self.defaults.get(&component_name)) } - pub fn try_fallback_raw(&self, component_name: ComponentName) -> Option> { - let fallback_provider = self - .data_result - .best_fallback_for(self.ctx, component_name)?; - + pub fn fallback_raw(&self, component_name: ComponentName) -> Box { let query_context = QueryContext { viewer_ctx: self.ctx.viewer_ctx, target_entity_path: &self.data_result.entity_path, @@ -64,9 +60,11 @@ impl<'a> HybridLatestAtResults<'a> { view_ctx: Some(self.ctx), }; - fallback_provider - .fallback_for(&query_context, component_name) - .ok() + self.data_result.best_fallback_for( + &query_context, + &self.ctx.visualizer_collection, + component_name, + ) } /// Utility for retrieving the first instance of a component, ignoring defaults. @@ -119,8 +117,9 @@ impl<'a> HybridLatestAtResults<'a> { self.get_instance(index) .or_else(|| { // No override, no store, no default -> try fallback instead - self.try_fallback_raw(C::name()) - .and_then(|raw| C::from_arrow(raw.as_ref()).ok()) + let raw_fallback = self.fallback_raw(C::name()); + C::from_arrow(raw_fallback.as_ref()) + .ok() .and_then(|r| r.first().cloned()) }) .unwrap_or_default() diff --git a/crates/viewer/re_space_view_spatial/src/ui_3d.rs b/crates/viewer/re_space_view_spatial/src/ui_3d.rs index bb2741c28b4f..bcf45adeb3e3 100644 --- a/crates/viewer/re_space_view_spatial/src/ui_3d.rs +++ b/crates/viewer/re_space_view_spatial/src/ui_3d.rs @@ -888,8 +888,14 @@ fn add_picking_ray( let mut line_batch = line_builder.batch("picking ray"); let origin = ray.point_along(0.0); + // No harm in making this ray _very_ long. (Infinite messes with things though!) - let fallback_ray_end = ray.point_along(scene_bbox.size().length() * 10.0); + // + // There are some degenerated cases where just taking the scene bounding box isn't enough: + // For instance, we don't add pinholes & depth images to the bounding box since + // the default size of a pinhole visualization itself is determined by the bounding box. + let fallback_ray_end = + ray.point_along((scene_bbox.size().length() * 10.0).at_least(thick_ray_length * 10.0)); let main_ray_end = ray.point_along(thick_ray_length); line_batch diff --git a/crates/viewer/re_ui/src/command.rs b/crates/viewer/re_ui/src/command.rs index f997ef524307..611ce3c1c691 100644 --- a/crates/viewer/re_ui/src/command.rs +++ b/crates/viewer/re_ui/src/command.rs @@ -14,6 +14,7 @@ pub trait UICommandSender { pub enum UICommand { // Listed in the order they show up in the command palette by default! Open, + Import, SaveRecording, SaveRecordingSelection, SaveBlueprint, @@ -111,7 +112,8 @@ impl UICommand { 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, …)"), + Self::Open => ("Open…", "Open any supported files (.rrd, images, meshes, …) in a new recording"), + Self::Import => ("Import…", "Import any supported files (.rrd, images, meshes, …) in the current recording"), Self::CloseCurrentRecording => ( "Close current recording", @@ -271,6 +273,10 @@ impl UICommand { KeyboardShortcut::new(Modifiers::COMMAND, key) } + fn cmd_shift(key: Key) -> KeyboardShortcut { + KeyboardShortcut::new(Modifiers::COMMAND.plus(Modifiers::SHIFT), key) + } + fn cmd_alt(key: Key) -> KeyboardShortcut { KeyboardShortcut::new(Modifiers::COMMAND.plus(Modifiers::ALT), key) } @@ -284,6 +290,7 @@ impl UICommand { Self::SaveRecordingSelection => Some(cmd_alt(Key::S)), Self::SaveBlueprint => None, Self::Open => Some(cmd(Key::O)), + Self::Import => Some(cmd_shift(Key::O)), Self::CloseCurrentRecording => None, Self::CloseAllRecordings => None, diff --git a/crates/viewer/re_viewer/src/app.rs b/crates/viewer/re_viewer/src/app.rs index 571f26c1dcc8..8d04ebe075dc 100644 --- a/crates/viewer/re_viewer/src/app.rs +++ b/crates/viewer/re_viewer/src/app.rs @@ -146,6 +146,13 @@ const MIN_ZOOM_FACTOR: f32 = 0.2; #[cfg(not(target_arch = "wasm32"))] const MAX_ZOOM_FACTOR: f32 = 5.0; +#[cfg(target_arch = "wasm32")] +struct PendingFilePromise { + recommended_application_id: Option, + recommended_recording_id: Option, + promise: poll_promise::Promise>, +} + /// The Rerun Viewer as an [`eframe`] application. pub struct App { build_info: re_build_info::BuildInfo, @@ -169,7 +176,7 @@ pub struct App { rx: ReceiveSet, #[cfg(target_arch = "wasm32")] - open_files_promise: Option>>, + open_files_promise: Option, /// What is serialized pub(crate) state: AppState, @@ -564,6 +571,18 @@ impl App { store_context: Option<&StoreContext<'_>>, cmd: UICommand, ) { + let active_application_id = store_context + .and_then(|ctx| { + ctx.hub + .active_app() + // Don't redirect data to the welcome screen. + .filter(|&app_id| app_id != &StoreHub::welcome_screen_app_id()) + }) + .cloned(); + let active_recording_id = store_context + .and_then(|ctx| ctx.hub.active_recording_id()) + .cloned(); + match cmd { UICommand::SaveRecording => { if let Err(err) = save_recording(self, store_context, None) { @@ -602,12 +621,57 @@ impl App { #[cfg(target_arch = "wasm32")] UICommand::Open => { let egui_ctx = egui_ctx.clone(); - self.open_files_promise = Some(poll_promise::Promise::spawn_local(async move { + + // Open: we want to try and load into a new dedicated recording. + let recommended_application_id = None; + let recommended_recording_id = None; + let promise = poll_promise::Promise::spawn_local(async move { let file = async_open_rrd_dialog().await; egui_ctx.request_repaint(); // Wake ui thread file - })); + }); + + self.open_files_promise = Some(PendingFilePromise { + recommended_application_id, + recommended_recording_id, + promise, + }); } + + #[cfg(not(target_arch = "wasm32"))] + UICommand::Import => { + for file_path in open_file_dialog_native() { + self.command_sender + .send_system(SystemCommand::LoadDataSource(DataSource::FilePath( + FileSource::FileDialog { + recommended_application_id: active_application_id.clone(), + recommended_recording_id: active_recording_id.clone(), + }, + file_path, + ))); + } + } + #[cfg(target_arch = "wasm32")] + UICommand::Import => { + let egui_ctx = egui_ctx.clone(); + + // Import: we want to try and load into the current recording. + let recommended_application_id = active_application_id; + let recommended_recording_id = active_recording_id; + + let promise = poll_promise::Promise::spawn_local(async move { + let file = async_open_rrd_dialog().await; + egui_ctx.request_repaint(); // Wake ui thread + file + }); + + self.open_files_promise = Some(PendingFilePromise { + recommended_application_id, + recommended_recording_id, + promise, + }); + } + UICommand::CloseCurrentRecording => { let cur_rec = store_context.map(|ctx| ctx.recording.store_id()); if let Some(cur_rec) = cur_rec { @@ -1586,14 +1650,19 @@ impl eframe::App for App { } #[cfg(target_arch = "wasm32")] - if let Some(promise) = &self.open_files_promise { + if let Some(PendingFilePromise { + recommended_application_id, + recommended_recording_id, + promise, + }) = &self.open_files_promise + { if let Some(files) = promise.ready() { for file in files { self.command_sender .send_system(SystemCommand::LoadDataSource(DataSource::FileContents( FileSource::FileDialog { - recommended_application_id: None, - recommended_recording_id: None, + recommended_application_id: recommended_application_id.clone(), + recommended_recording_id: recommended_recording_id.clone(), }, file.clone(), ))); diff --git a/crates/viewer/re_viewer/src/reflection/mod.rs b/crates/viewer/re_viewer/src/reflection/mod.rs index 245825156a81..73ce1ec69a5d 100644 --- a/crates/viewer/re_viewer/src/reflection/mod.rs +++ b/crates/viewer/re_viewer/src/reflection/mod.rs @@ -38,665 +38,669 @@ fn generate_component_reflection() -> Result::name(), ComponentReflection { docstring_md: "The active tab in a tabbed container.", - placeholder: Some(ActiveTab::default().to_arrow()?), + custom_placeholder: Some(ActiveTab::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether empty cells in a dataframe should be filled with a latest-at query.", - placeholder: Some(ApplyLatestAt::default().to_arrow()?), + custom_placeholder: Some(ApplyLatestAt::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether the viewport layout is determined automatically.", - placeholder: Some(AutoLayout::default().to_arrow()?), + custom_placeholder: Some(AutoLayout::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether or not space views should be created automatically.", - placeholder: Some(AutoSpaceViews::default().to_arrow()?), + custom_placeholder: Some(AutoSpaceViews::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The type of the background in a view.", - placeholder: Some(BackgroundKind::default().to_arrow()?), + custom_placeholder: Some(BackgroundKind::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The layout share of a column in the container.", - placeholder: Some(ColumnShare::default().to_arrow()?), + custom_placeholder: Some(ColumnShare::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Describe a component column to be selected in the dataframe view.", - placeholder: Some(ComponentColumnSelector::default().to_arrow()?), + custom_placeholder: Some(ComponentColumnSelector::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The kind of a blueprint container (tabs, grid, …).", - placeholder: Some(ContainerKind::default().to_arrow()?), + custom_placeholder: Some(ContainerKind::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "One of four 2D corners, typically used to align objects.", - placeholder: Some(Corner2D::default().to_arrow()?), + custom_placeholder: Some(Corner2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Configuration for a filter-by-range feature of the dataframe view.", - placeholder: Some(FilterByRange::default().to_arrow()?), + custom_placeholder: Some(FilterByRange::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Configuration for the filter is not null feature of the dataframe view.", - placeholder: Some(FilterIsNotNull::default().to_arrow()?), + custom_placeholder: Some(FilterIsNotNull::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "How many columns a grid container should have.", - placeholder: Some(GridColumns::default().to_arrow()?), + custom_placeholder: Some(GridColumns::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "All the contents in the container.", - placeholder: Some(IncludedContent::default().to_arrow()?), + custom_placeholder: Some(IncludedContent::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The unique id of a space view, used to refer to views in containers.", - placeholder: Some(IncludedSpaceView::default().to_arrow()?), + custom_placeholder: Some(IncludedSpaceView::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether the entity can be interacted with.\n\nNon interactive components are still visible, but mouse interactions in the view are disabled.", - placeholder: Some(Interactive::default().to_arrow()?), + custom_placeholder: Some(Interactive::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Indicate whether the range should be locked when zooming in on the data.\n\nDefault is `false`, i.e. zoom will change the visualized range.", - placeholder: Some(LockRangeDuringZoom::default().to_arrow()?), + custom_placeholder: Some(LockRangeDuringZoom::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Tri-state for panel controls.", - placeholder: Some(PanelState::default().to_arrow()?), + custom_placeholder: Some(PanelState::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "An individual query expression used to filter a set of [`datatypes.EntityPath`](https://rerun.io/docs/reference/types/datatypes/entity_path)s.\n\nEach expression is either an inclusion or an exclusion expression.\nInclusions start with an optional `+` and exclusions must start with a `-`.\n\nMultiple expressions are combined together as part of `SpaceViewContents`.\n\nThe `/**` suffix matches the whole subtree, i.e. self and any child, recursively\n(`/world/**` matches both `/world` and `/world/car/driver`).\nOther uses of `*` are not (yet) supported.", - placeholder: Some(QueryExpression::default().to_arrow()?), + custom_placeholder: Some(QueryExpression::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The container that sits at the root of a viewport.", - placeholder: Some(RootContainer::default().to_arrow()?), + custom_placeholder: Some(RootContainer::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The layout share of a row in the container.", - placeholder: Some(RowShare::default().to_arrow()?), + custom_placeholder: Some(RowShare::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Describe a component column to be selected in the dataframe view.", - placeholder: Some(SelectedColumns::default().to_arrow()?), + custom_placeholder: Some(SelectedColumns::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The class identifier of view, e.g. `\"2D\"`, `\"TextLog\"`, ….", - placeholder: Some(SpaceViewClass::default().to_arrow()?), + custom_placeholder: Some(SpaceViewClass::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether a space view is maximized.", - placeholder: Some(SpaceViewMaximized::default().to_arrow()?), + custom_placeholder: Some(SpaceViewMaximized::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The origin of a `SpaceView`.", - placeholder: Some(SpaceViewOrigin::default().to_arrow()?), + custom_placeholder: Some(SpaceViewOrigin::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Show a slider for the index of some dimension of a slider.", - placeholder: Some(TensorDimensionIndexSlider::default().to_arrow()?), + custom_placeholder: Some( + TensorDimensionIndexSlider::default().to_arrow()?, + ), }, ), ( ::name(), ComponentReflection { docstring_md: "A timeline identified by its name.", - placeholder: Some(TimelineName::default().to_arrow()?), + custom_placeholder: Some(TimelineName::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Determines whether an image or texture should be scaled to fit the viewport.", - placeholder: Some(ViewFit::default().to_arrow()?), + custom_placeholder: Some(ViewFit::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Hash of a viewer recommendation.\n\nThe formation of this hash is considered an internal implementation detail of the viewer.", - placeholder: Some(ViewerRecommendationHash::default().to_arrow()?), + custom_placeholder: Some(ViewerRecommendationHash::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether the container, view, entity or instance is currently visible.", - placeholder: Some(Visible::default().to_arrow()?), + custom_placeholder: Some(Visible::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The range of values on a given timeline that will be included in a view's query.\n\nRefer to `VisibleTimeRanges` archetype for more information.", - placeholder: Some(VisibleTimeRange::default().to_arrow()?), + custom_placeholder: Some(VisibleTimeRange::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Visual bounds in 2D space used for `Spatial2DView`.", - placeholder: Some(VisualBounds2D::default().to_arrow()?), + custom_placeholder: Some(VisualBounds2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Override the visualizers for an entity.\n\nThis component is a stop-gap mechanism based on the current implementation details\nof the visualizer system. It is not intended to be a long-term solution, but provides\nenough utility to be useful in the short term.\n\nThe long-term solution is likely to be based off: \n\nThis can only be used as part of blueprints. It will have no effect if used\nin a regular entity.", - placeholder: Some(VisualizerOverrides::default().to_arrow()?), + custom_placeholder: Some(VisualizerOverrides::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Policy for aggregation of multiple scalar plot values.\n\nThis is used for lines in plots when the X axis distance of individual points goes below a single pixel,\ni.e. a single pixel covers more than one tick worth of data. It can greatly improve performance\n(and readability) in such situations as it prevents overdraw.", - placeholder: Some(AggregationPolicy::default().to_arrow()?), + custom_placeholder: Some(AggregationPolicy::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A color multiplier, usually applied to a whole entity, e.g. a mesh.", - placeholder: Some(AlbedoFactor::default().to_arrow()?), + custom_placeholder: Some(AlbedoFactor::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The annotation context provides additional information on how to display entities.\n\nEntities can use [`datatypes.ClassId`](https://rerun.io/docs/reference/types/datatypes/class_id)s and [`datatypes.KeypointId`](https://rerun.io/docs/reference/types/datatypes/keypoint_id)s to provide annotations, and\nthe labels and colors will be looked up in the appropriate\nannotation context. We use the *first* annotation context we find in the\npath-hierarchy when searching up through the ancestors of a given entity\npath.", - placeholder: Some(AnnotationContext::default().to_arrow()?), + custom_placeholder: Some(AnnotationContext::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The length of an axis in local units of the space.", - placeholder: Some(AxisLength::default().to_arrow()?), + custom_placeholder: Some(AxisLength::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A binary blob of data.", - placeholder: Some(Blob::default().to_arrow()?), + custom_placeholder: None, }, ), ( ::name(), ComponentReflection { docstring_md: "A 16-bit ID representing a type of semantic class.", - placeholder: Some(ClassId::default().to_arrow()?), + custom_placeholder: Some(ClassId::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Configures how a clear operation should behave - recursive or not.", - placeholder: Some(ClearIsRecursive::default().to_arrow()?), + custom_placeholder: Some(ClearIsRecursive::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha.\n\nThe color is stored as a 32-bit integer, where the most significant\nbyte is `R` and the least significant byte is `A`.", - placeholder: Some(Color::default().to_arrow()?), + custom_placeholder: Some(Color::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Colormap for mapping scalar values within a given range to a color.\n\nThis provides a number of popular pre-defined colormaps.\nIn the future, the Rerun Viewer will allow users to define their own colormaps,\nbut currently the Viewer is limited to the types defined here.", - placeholder: Some(Colormap::default().to_arrow()?), + custom_placeholder: Some(Colormap::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The world->depth map scaling factor.\n\nThis measures how many depth map units are in a world unit.\nFor instance, if a depth map uses millimeters and the world uses meters,\nthis value would be `1000`.\n\nNote that the only effect on 2D views is the physical depth values shown when hovering the image.\nIn 3D views on the other hand, this affects where the points of the point cloud are placed.", - placeholder: Some(DepthMeter::default().to_arrow()?), + custom_placeholder: Some(DepthMeter::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Spatially disconnect this entity from its parent.\n\nSpecifies that the entity path at which this is logged is spatially disconnected from its parent,\nmaking it impossible to transform the entity path into its parent's space and vice versa.\nIt *only* applies to space views that work with spatial transformations, i.e. 2D & 3D space views.\nThis is useful for specifying that a subgraph is independent of the rest of the scene.", - placeholder: Some(DisconnectedSpace::default().to_arrow()?), + custom_placeholder: Some(DisconnectedSpace::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Draw order of 2D elements. Higher values are drawn on top of lower values.\n\nAn entity can have only a single draw order component.\nWithin an entity draw order is governed by the order of the components.\n\nDraw order for entities with the same draw order is generally undefined.", - placeholder: Some(DrawOrder::default().to_arrow()?), + custom_placeholder: Some(DrawOrder::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A path to an entity, usually to reference some data that is part of the target entity.", - placeholder: Some(EntityPath::default().to_arrow()?), + custom_placeholder: Some(EntityPath::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "How a geometric shape is drawn and colored.", - placeholder: Some(FillMode::default().to_arrow()?), + custom_placeholder: Some(FillMode::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "How much a primitive fills out the available space.\n\nUsed for instance to scale the points of the point cloud created from [`archetypes.DepthImage`](https://rerun.io/docs/reference/types/archetypes/depth_image) projection in 3D views.\nValid range is from 0 to max float although typically values above 1.0 are not useful.\n\nDefaults to 1.0.", - placeholder: Some(FillRatio::default().to_arrow()?), + custom_placeholder: Some(FillRatio::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A gamma correction value to be used with a scalar value or color.\n\nUsed to adjust the gamma of a color or scalar value between 0 and 1 before rendering.\n`new_value = old_value ^ gamma`\n\nValid range is from 0 (excluding) to max float.\nDefaults to 1.0 unless otherwise specified.", - placeholder: Some(GammaCorrection::default().to_arrow()?), + custom_placeholder: Some(GammaCorrection::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Half-size (radius) of a 2D box.\n\nMeasured in its local coordinate system.\n\nThe box extends both in negative and positive direction along each axis.\nNegative sizes indicate that the box is flipped along the respective axis, but this has no effect on how it is displayed.", - placeholder: Some(HalfSize2D::default().to_arrow()?), + custom_placeholder: Some(HalfSize2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Half-size (radius) of a 3D box.\n\nMeasured in its local coordinate system.\n\nThe box extends both in negative and positive direction along each axis.\nNegative sizes indicate that the box is flipped along the respective axis, but this has no effect on how it is displayed.", - placeholder: Some(HalfSize3D::default().to_arrow()?), + custom_placeholder: Some(HalfSize3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A buffer that is known to store image data.\n\nTo interpret the contents of this buffer, see, [`components.ImageFormat`](https://rerun.io/docs/reference/types/components/image_format).", - placeholder: Some(ImageBuffer::default().to_arrow()?), + custom_placeholder: None, }, ), ( ::name(), ComponentReflection { docstring_md: "The metadata describing the contents of a [`components.ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer).", - placeholder: Some(ImageFormat::default().to_arrow()?), + custom_placeholder: Some(ImageFormat::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The distance from the camera origin to the image plane when the projection is shown in a 3D viewer.\n\nThis is only used for visualization purposes, and does not affect the projection itself.", - placeholder: Some(ImagePlaneDistance::default().to_arrow()?), + custom_placeholder: Some(ImagePlaneDistance::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 16-bit ID representing a type of semantic keypoint within a class.", - placeholder: Some(KeypointId::default().to_arrow()?), + custom_placeholder: Some(KeypointId::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A line strip in 2D space.\n\nA line strip is a list of points connected by line segments. It can be used to draw\napproximations of smooth curves.\n\nThe points will be connected in order, like so:\n```text\n 2------3 5\n / \\ /\n0----1 \\ /\n 4\n```", - placeholder: Some(LineStrip2D::default().to_arrow()?), + custom_placeholder: Some(LineStrip2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A line strip in 3D space.\n\nA line strip is a list of points connected by line segments. It can be used to draw\napproximations of smooth curves.\n\nThe points will be connected in order, like so:\n```text\n 2------3 5\n / \\ /\n0----1 \\ /\n 4\n```", - placeholder: Some(LineStrip3D::default().to_arrow()?), + custom_placeholder: Some(LineStrip3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Filter used when magnifying an image/texture such that a single pixel/texel is displayed as multiple pixels on screen.", - placeholder: Some(MagnificationFilter::default().to_arrow()?), + custom_placeholder: Some(MagnificationFilter::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The visual appearance of a point in e.g. a 2D plot.", - placeholder: Some(MarkerShape::default().to_arrow()?), + custom_placeholder: Some(MarkerShape::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Radius of a marker of a point in e.g. a 2D plot, measured in UI points.", - placeholder: Some(MarkerSize::default().to_arrow()?), + custom_placeholder: Some(MarkerSize::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A standardized media type (RFC2046, formerly known as MIME types), encoded as a string.\n\nThe complete reference of officially registered media types is maintained by the IANA and can be\nconsulted at .", - placeholder: Some(MediaType::default().to_arrow()?), + custom_placeholder: Some(MediaType::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A display name, typically for an entity or a item like a plot series.", - placeholder: Some(Name::default().to_arrow()?), + custom_placeholder: Some(Name::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Degree of transparency ranging from 0.0 (fully transparent) to 1.0 (fully opaque).\n\nThe final opacity value may be a result of multiplication with alpha values as specified by other color sources.\nUnless otherwise specified, the default value is 1.", - placeholder: Some(Opacity::default().to_arrow()?), + custom_placeholder: Some(Opacity::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Camera projection, from image coordinates to view coordinates.\n\nChild from parent.\nImage coordinates from camera view coordinates.\n\nExample:\n```text\n1496.1 0.0 980.5\n 0.0 1496.1 744.5\n 0.0 0.0 1.0\n```", - placeholder: Some(PinholeProjection::default().to_arrow()?), + custom_placeholder: Some(PinholeProjection::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "3D rotation represented by a rotation around a given axis that doesn't propagate in the transform hierarchy.", - placeholder: Some(PoseRotationAxisAngle::default().to_arrow()?), + custom_placeholder: Some(PoseRotationAxisAngle::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 3D rotation expressed as a quaternion that doesn't propagate in the transform hierarchy.\n\nNote: although the x,y,z,w components of the quaternion will be passed through to the\ndatastore as provided, when used in the Viewer, quaternions will always be normalized.", - placeholder: Some(PoseRotationQuat::default().to_arrow()?), + custom_placeholder: Some(PoseRotationQuat::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 3D scale factor that doesn't propagate in the transform hierarchy.\n\nA scale of 1.0 means no scaling.\nA scale of 2.0 means doubling the size.\nEach component scales along the corresponding axis.", - placeholder: Some(PoseScale3D::default().to_arrow()?), + custom_placeholder: Some(PoseScale3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 3x3 transformation matrix Matrix that doesn't propagate in the transform hierarchy.\n\n3x3 matrixes are able to represent any affine transformation in 3D space,\ni.e. rotation, scaling, shearing, reflection etc.\n\nMatrices in Rerun are stored as flat list of coefficients in column-major order:\n```text\n column 0 column 1 column 2\n -------------------------------------------------\nrow 0 | flat_columns[0] flat_columns[3] flat_columns[6]\nrow 1 | flat_columns[1] flat_columns[4] flat_columns[7]\nrow 2 | flat_columns[2] flat_columns[5] flat_columns[8]\n```", - placeholder: Some(PoseTransformMat3x3::default().to_arrow()?), + custom_placeholder: Some(PoseTransformMat3x3::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A translation vector in 3D space that doesn't propagate in the transform hierarchy.", - placeholder: Some(PoseTranslation3D::default().to_arrow()?), + custom_placeholder: Some(PoseTranslation3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A position in 2D space.", - placeholder: Some(Position2D::default().to_arrow()?), + custom_placeholder: Some(Position2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A position in 3D space.", - placeholder: Some(Position3D::default().to_arrow()?), + custom_placeholder: Some(Position3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The radius of something, e.g. a point.\n\nInternally, positive values indicate scene units, whereas negative values\nare interpreted as UI points.\n\nUI points are independent of zooming in Views, but are sensitive to the application UI scaling.\nat 100% UI scaling, UI points are equal to pixels\nThe Viewer's UI scaling defaults to the OS scaling which typically is 100% for full HD screens and 200% for 4k screens.", - placeholder: Some(Radius::default().to_arrow()?), + custom_placeholder: Some(Radius::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 1D range, specifying a lower and upper bound.", - placeholder: Some(Range1D::default().to_arrow()?), + custom_placeholder: Some(Range1D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Pixel resolution width & height, e.g. of a camera sensor.\n\nTypically in integer units, but for some use cases floating point may be used.", - placeholder: Some(Resolution::default().to_arrow()?), + custom_placeholder: Some(Resolution::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "3D rotation represented by a rotation around a given axis.", - placeholder: Some(RotationAxisAngle::default().to_arrow()?), + custom_placeholder: Some(RotationAxisAngle::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 3D rotation expressed as a quaternion.\n\nNote: although the x,y,z,w components of the quaternion will be passed through to the\ndatastore as provided, when used in the Viewer, quaternions will always be normalized.", - placeholder: Some(RotationQuat::default().to_arrow()?), + custom_placeholder: Some(RotationQuat::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A scalar value, encoded as a 64-bit floating point.\n\nUsed for time series plots.", - placeholder: Some(Scalar::default().to_arrow()?), + custom_placeholder: Some(Scalar::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 3D scale factor.\n\nA scale of 1.0 means no scaling.\nA scale of 2.0 means doubling the size.\nEach component scales along the corresponding axis.", - placeholder: Some(Scale3D::default().to_arrow()?), + custom_placeholder: Some(Scale3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Whether the entity's [`components.Text`](https://rerun.io/docs/reference/types/components/text) label is shown.\n\nThe main purpose of this component existing separately from the labels themselves\nis to be overridden when desired, to allow hiding and showing from the viewer and\nblueprints.", - placeholder: Some(ShowLabels::default().to_arrow()?), + custom_placeholder: None, }, ), ( ::name(), ComponentReflection { docstring_md: "The width of a stroke specified in UI points.", - placeholder: Some(StrokeWidth::default().to_arrow()?), + custom_placeholder: Some(StrokeWidth::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "An N-dimensional array of numbers.\n\nThe number of dimensions and their respective lengths is specified by the `shape` field.\nThe dimensions are ordered from outermost to innermost. For example, in the common case of\na 2D RGB Image, the shape would be `[height, width, channel]`.\n\nThese dimensions are combined with an index to look up values from the `buffer` field,\nwhich stores a contiguous array of typed values.", - placeholder: Some(TensorData::default().to_arrow()?), + custom_placeholder: Some(TensorData::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Specifies a concrete index on a tensor dimension.", - placeholder: Some(TensorDimensionIndexSelection::default().to_arrow()?), + custom_placeholder: Some( + TensorDimensionIndexSelection::default().to_arrow()?, + ), }, ), ( ::name(), ComponentReflection { docstring_md: "Specifies which dimension to use for height.", - placeholder: Some(TensorHeightDimension::default().to_arrow()?), + custom_placeholder: Some(TensorHeightDimension::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Specifies which dimension to use for width.", - placeholder: Some(TensorWidthDimension::default().to_arrow()?), + custom_placeholder: Some(TensorWidthDimension::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 2D texture UV coordinate.\n\nTexture coordinates specify a position on a 2D texture.\nA range from 0-1 covers the entire texture in the respective dimension.\nUnless configured otherwise, the texture repeats outside of this range.\nRerun uses top-left as the origin for UV coordinates.\n\n 0 U 1\n0 + --------- →\n | .\nV | .\n | .\n1 ↓ . . . . . .\n\nThis is the same convention as in Vulkan/Metal/DX12/WebGPU, but (!) unlike OpenGL,\nwhich places the origin at the bottom-left.", - placeholder: Some(Texcoord2D::default().to_arrow()?), + custom_placeholder: Some(Texcoord2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A string of text, e.g. for labels and text documents.", - placeholder: Some(Text::default().to_arrow()?), + custom_placeholder: Some(Text::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The severity level of a text log message.\n\nRecommended to be one of:\n* `\"CRITICAL\"`\n* `\"ERROR\"`\n* `\"WARN\"`\n* `\"INFO\"`\n* `\"DEBUG\"`\n* `\"TRACE\"`", - placeholder: Some(TextLogLevel::default().to_arrow()?), + custom_placeholder: Some(TextLogLevel::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A 3x3 transformation matrix Matrix.\n\n3x3 matrixes are able to represent any affine transformation in 3D space,\ni.e. rotation, scaling, shearing, reflection etc.\n\nMatrices in Rerun are stored as flat list of coefficients in column-major order:\n```text\n column 0 column 1 column 2\n -------------------------------------------------\nrow 0 | flat_columns[0] flat_columns[3] flat_columns[6]\nrow 1 | flat_columns[1] flat_columns[4] flat_columns[7]\nrow 2 | flat_columns[2] flat_columns[5] flat_columns[8]\n```", - placeholder: Some(TransformMat3x3::default().to_arrow()?), + custom_placeholder: Some(TransformMat3x3::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Specifies relation a spatial transform describes.", - placeholder: Some(TransformRelation::default().to_arrow()?), + custom_placeholder: Some(TransformRelation::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A translation vector in 3D space.", - placeholder: Some(Translation3D::default().to_arrow()?), + custom_placeholder: Some(Translation3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "The three indices of a triangle in a triangle mesh.", - placeholder: Some(TriangleIndices::default().to_arrow()?), + custom_placeholder: Some(TriangleIndices::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Range of expected or valid values, specifying a lower and upper bound.", - placeholder: Some(ValueRange::default().to_arrow()?), + custom_placeholder: Some(ValueRange::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A vector in 2D space.", - placeholder: Some(Vector2D::default().to_arrow()?), + custom_placeholder: Some(Vector2D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "A vector in 3D space.", - placeholder: Some(Vector3D::default().to_arrow()?), + custom_placeholder: Some(Vector3D::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "Timestamp inside a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video).", - placeholder: Some(VideoTimestamp::default().to_arrow()?), + custom_placeholder: Some(VideoTimestamp::default().to_arrow()?), }, ), ( ::name(), ComponentReflection { docstring_md: "How we interpret the coordinate system of an entity/space.\n\nFor instance: What is \"up\"? What does the Z axis mean?\n\nThe three coordinates are always ordered as [x, y, z].\n\nFor example [Right, Down, Forward] means that the X axis points to the right, the Y axis points\ndown, and the Z axis points forward.\n\n⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032).\n\nThe following constants are used to represent the different directions:\n * Up = 1\n * Down = 2\n * Right = 3\n * Left = 4\n * Forward = 5\n * Back = 6", - placeholder: Some(ViewCoordinates::default().to_arrow()?), + custom_placeholder: Some(ViewCoordinates::default().to_arrow()?), }, ), ]; diff --git a/crates/viewer/re_viewer/src/ui/rerun_menu.rs b/crates/viewer/re_viewer/src/ui/rerun_menu.rs index 5d75274b4a49..9992499f2285 100644 --- a/crates/viewer/re_viewer/src/ui/rerun_menu.rs +++ b/crates/viewer/re_viewer/src/ui/rerun_menu.rs @@ -37,6 +37,7 @@ impl App { ui.add_space(SPACING); UICommand::Open.menu_button_ui(ui, &self.command_sender); + UICommand::Import.menu_button_ui(ui, &self.command_sender); self.save_buttons_ui(ui, _store_context); @@ -114,6 +115,7 @@ impl App { fn about_rerun_ui(&self, frame: &eframe::Frame, ui: &mut egui::Ui) { let re_build_info::BuildInfo { crate_name, + features, version, rustc_version, llvm_version, @@ -138,6 +140,12 @@ impl App { {target_triple}" ); + // It is really the features of `rerun-cli` (the `rerun` binary) that are interesting. + // For the web-viewer we get `crate_name: "re_viewer"` here, which is much less interesting. + if crate_name == "rerun-cli" && !features.is_empty() { + label += &format!("\n{crate_name} features: {features}"); + } + if !rustc_version.is_empty() { label += &format!("\nrustc {rustc_version}"); if !llvm_version.is_empty() { diff --git a/crates/viewer/re_viewer_context/src/component_fallbacks.rs b/crates/viewer/re_viewer_context/src/component_fallbacks.rs index 183cb9240cea..adc8211dbeda 100644 --- a/crates/viewer/re_viewer_context/src/component_fallbacks.rs +++ b/crates/viewer/re_viewer_context/src/component_fallbacks.rs @@ -30,14 +30,6 @@ impl From for ComponentFallbackProviderResult { /// Error type for a fallback request. #[derive(thiserror::Error, Debug)] pub enum ComponentFallbackError { - /// The fallback provider is not able to handle the given component _and_ there was no placeholder value. - /// - /// This should never happen, since all components should have a placeholder value - /// registered in [`crate::ViewerContext::reflection`]. - /// Meaning, that this is an unknown component or something went wrong with the placeholder registration. - #[error("Missing placeholder for component. Was the component's default registered with the viewer?")] - MissingPlaceholderValue, - /// Not directly returned by the fallback provider, but useful when serializing a fallback value. #[error("Fallback value turned up to be empty when we expected a value.")] UnexpectedEmptyFallback, @@ -65,10 +57,10 @@ pub trait ComponentFallbackProvider { &self, ctx: &QueryContext<'_>, component: ComponentName, - ) -> Result, ComponentFallbackError> { + ) -> Box { match self.try_provide_fallback(ctx, component) { ComponentFallbackProviderResult::Value(value) => { - return Ok(value); + return value; } ComponentFallbackProviderResult::SerializationError(err) => { // We still want to provide the base fallback value so we can move on, @@ -80,12 +72,7 @@ pub trait ComponentFallbackProvider { ComponentFallbackProviderResult::ComponentNotHandled => {} } - ctx.viewer_ctx - .reflection - .components - .get(&component) - .and_then(|info| info.placeholder.clone()) - .ok_or(ComponentFallbackError::MissingPlaceholderValue) + ctx.viewer_ctx.placeholder_for(component) } } diff --git a/crates/viewer/re_viewer_context/src/component_ui_registry.rs b/crates/viewer/re_viewer_context/src/component_ui_registry.rs index f94b96969378..59db1807f4f0 100644 --- a/crates/viewer/re_viewer_context/src/component_ui_registry.rs +++ b/crates/viewer/re_viewer_context/src/component_ui_registry.rs @@ -591,15 +591,7 @@ impl ComponentUiRegistry { { component_raw } else { - match fallback_provider.fallback_for(ctx, component_name) { - Ok(value) => value, - Err(err) => { - let error_text = format!("No fallback value available for {component_name}."); - re_log::error_once!("{error_text} ({err})"); - ui.error_label(&error_text); - return; - } - } + fallback_provider.fallback_for(ctx, component_name) }; self.edit_ui_raw( diff --git a/crates/viewer/re_viewer_context/src/viewer_context.rs b/crates/viewer/re_viewer_context/src/viewer_context.rs index a5c1eaac439e..4ab832b84348 100644 --- a/crates/viewer/re_viewer_context/src/viewer_context.rs +++ b/crates/viewer/re_viewer_context/src/viewer_context.rs @@ -160,6 +160,39 @@ impl<'a> ViewerContext<'a> { } } } + + /// Returns a placeholder value for a given component, solely identified by its name. + /// + /// A placeholder is an array of the component type with a single element which takes on some default value. + /// It can be set as part of the reflection information, see [`re_types_core::reflection::ComponentReflection::custom_placeholder`]. + /// Note that automatically generated placeholders ignore any extension types. + /// + /// This requires the component name to be known by either datastore or blueprint store and + /// will return a placeholder for a nulltype otherwise, logging an error. + /// The rationale is that to get into this situation, we need to know of a component name for which + /// we don't have a datatype, meaning that we can't make any statement about what data this component should represent. + // TODO(andreas): Are there cases where this is expected and how to handle this? + pub fn placeholder_for( + &self, + component: re_chunk::ComponentName, + ) -> Box { + self.reflection.components.get(&component).and_then(|info| info.custom_placeholder.as_ref()).cloned() + + .unwrap_or_else(|| + { + // TODO(andreas): Is this operation common enough to cache the result? If so, here or in the reflection data? + // The nice thing about this would be that we could always give out references (but updating said cache wouldn't be easy in that case). + let datatype = self + .recording_store() + .lookup_datatype(&component) + .or_else(|| self.blueprint_store().lookup_datatype(&component)) + .unwrap_or_else(|| { + re_log::error_once!("Could not find datatype for component {component}. Using null array as placeholder."); + &re_chunk::external::arrow2::datatypes::DataType::Null + }); + re_types::reflection::generic_placeholder_for_datatype(datatype) + }) + } } // ---------------------------------------------------------------------------- diff --git a/crates/viewer/re_viewport_blueprint/src/view_properties.rs b/crates/viewer/re_viewport_blueprint/src/view_properties.rs index 2894c50b6adb..b601fc6416b0 100644 --- a/crates/viewer/re_viewport_blueprint/src/view_properties.rs +++ b/crates/viewer/re_viewport_blueprint/src/view_properties.rs @@ -103,10 +103,11 @@ impl ViewProperty { view_state: &dyn re_viewer_context::SpaceViewState, ) -> Result, ViewPropertyQueryError> { let component_name = C::name(); - Ok(C::from_arrow( - self.component_or_fallback_raw(ctx, component_name, fallback_provider, view_state)? + C::from_arrow( + self.component_or_fallback_raw(ctx, component_name, fallback_provider, view_state) .as_ref(), - )?) + ) + .map_err(|err| err.into()) } /// Get a single component or None, not using any fallbacks. @@ -157,10 +158,10 @@ impl ViewProperty { component_name: ComponentName, fallback_provider: &dyn ComponentFallbackProvider, view_state: &dyn re_viewer_context::SpaceViewState, - ) -> Result, ComponentFallbackError> { + ) -> Box { if let Some(value) = self.component_raw(component_name) { if value.len() > 0 { - return Ok(value); + return value; } } fallback_provider.fallback_for(&self.query_context(ctx, view_state), component_name) diff --git a/docs/content/concepts/app-model.md b/docs/content/concepts/app-model.md new file mode 100644 index 000000000000..51c88c071dbe --- /dev/null +++ b/docs/content/concepts/app-model.md @@ -0,0 +1,189 @@ +--- +title: Application model +order: 0 +--- + +The Rerun distribution comes with numerous moving pieces: +* The **SDKs** (Python, Rust & C++), for logging data and querying it back. These are libraries running directly in the end user's process. +* The **Native Viewer**: the Rerun GUI application for native platforms (Linux, macOS, Windows). +* The **TCP server**, which receives data from the **SDKs** and forwards it to the **Native Viewer** and/or **WebSocket Server**. The communication is unidirectional: clients push data into the TCP connection, never the other way around. +* The **Web Viewer**, which packs the **Native Viewer** into a WASM application that can run on the Web and its derivatives (notebooks, etc). +* The **Web/HTTP Server**, for serving the web page that hosts the **Web Viewer**. +* The **WebSocket server**, for serving data to the **Web Viewer**. The communication is unidirectional: the server pushes data to the **Web Viewer**, never the other way around. +* The **CLI**, which allows you to control all the pieces above as well as manipulate RRD files. + +The **Native Viewer** always includes: + * A **Chunk Store**: an in-memory database that stores the logged data. + * A **Renderer**: a 3D engine that renders the contents of the **Chunk Store**. + + +## What runs where? + +This is a lot to take in at first, but as we'll see these different pieces are generally deployed in just a few unique configurations for most common cases. + +The first thing to understand is what process do each of these things run in. + +The **CLI**, **Native Viewer**, **TCP server**, **Web/HTTP Server** and **WebSocket Server** are all part of the same binary: `rerun`. +Some of them can be enabled or disabled on demand using the appropriate flags but, no matter what, all these pieces are part of the same binary and execute in the same process. +Keep in mind that even the **Native Viewer** can be disabled (headless mode). + +The **SDKs** are vanilla software libraries and therefore always executes in the same context as the end-user's code. + +Finally, the **Web Viewer** is a WASM application and therefore has its own dedicated `.wasm` artifact, and always runs in isolation in the end-user's web browser. + +The best way to make sense of it all it to look at some of the most common scenarios when: +* Logging and visualizing data on native. +* Logging data on native and visualizing it on the web. + + +## Logging and visualizing data on native + +There are two common sub-scenarios when working natively: +* Data is being logged and visualized at the same time (synchronous workflow). +* Data is being logged first to some persistent storage, and visualized at a later time (asynchronous workflow). + + +### Synchronous workflow + +This is the most common kind of Rerun deployment, and also the simplest: one or more **SDKs**, embedded into the user's process, are logging data directly to a **TCP Server**, which in turns feeds the **Native Viewer**. +Both the **Native Viewer** and the **TCP Server** are running in the same `rerun` process. + +Logging script: + +snippet: concepts/app-model/native-sync + +Deployment: + +```sh +# Start the Rerun Native Viewer in the background. +# +# This will also start the TCP server on its default port (9876, use `--port` +# to pick another one). +# +# We could also have just used `spawn()` instead of `connect()` in the logging +# script above, and # we wouldn't have had to start the Native Viewer manually. +# `spawn()` does exactly this: it fork-execs a Native Viewer in the background +# using the first `rerun` # binary available # on your $PATH. +$ rerun & + +# Start logging data. It will be pushed to the Native Viewer through the TCP link. +$ ./logging_script +``` + + +Dataflow: + + + + + + + + + +Reference: +* [SDK operating modes: `connect`](../reference/sdk/operating-modes.md#connect) +* [🐍 Python `connect`](https://ref.rerun.io/docs/python/0.19.0/common/initialization_functions/#rerun.connect) +* [🦀 Rust `connect`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.connect) +* [🌊 C++ `connect`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#aef3377ffaa2441b906d2bac94dd8fc64) + +### Asynchronous workflow + +The asynchronous native workflow is similarly simple: one or more **SDKs**, embedded into the user's process, are logging data directly to one or more files. +The user will then manually start the **Native Viewer** at some later point, in order to visualize these files. + +Note: the `rerun` process still embeds both a **Native Viewer** and a **TCP Server**. For each **Native Viewer**, there is **always** an accompanying **TCP Server**, no exception. + +Logging script: + +snippet: concepts/app-model/native-async + +Deployment: +```sh +# Log the data into one or more files. +$ ./logging_script + +# Start the Rerun Native Viewer and feed it the RRD file directly. +# +# This will also start the TCP server on its default port (9876, use `--port` +# to pick another one). Although it is not used yet, some client might want +# to connect in the future. +$ rerun /tmp/my_recording.rrd +``` + +Dataflow: + + + + + + + + + + +Reference: +* [SDK operating modes: `save`](../reference/sdk/operating-modes.md#save) +* [🐍 Python `save`](https://ref.rerun.io/docs/python/0.19.0/common/initialization_functions/#rerun.save) +* [🦀 Rust `save`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.save) +* [🌊 C++ `save`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a555a7940a076c93d951de5b139d14918) + +## Logging data on native and visualizing it on the web. + +TODO(cmc): incoming. + + +## FAQ + +### How can I use multiple **Native Viewers** at the same (i.e. multiple windows)? + +Every **Native Viewer** comes with a corresponding **TCP Server** -- always. You cannot start a **Native Viewer** without starting a **TCP server**. + +The only way to have more than one Rerun window is to have more than one **TCP server**, by means of the `--port` flag. + +E.g.: +```sh +# starts a new viewer, listening for TCP connections on :9876 +rerun & + +# does nothing, there's already a viewer session running at that address +rerun & + +# does nothing, there's already a viewer session running at that address +rerun --port 9876 & + +# logs the image file to the existing viewer running on :9876 +rerun image.jpg + +# logs the image file to the existing viewer running on :9876 +rerun --port 9876 image.jpg + +# starts a new viewer, listening for TCP connections on :6789, and logs the image data to it +rerun --port 6789 image.jpg + +# does nothing, there's already a viewer session running at that address +rerun --port 6789 & + +# logs the image file to the existing viewer running on :6789 +rerun --port 6789 image.jpg & +``` + + +### What happens when I use `rr.spawn()` from my SDK of choice? + +TODO(cmc): incoming. + + +### What happens when I use `rr.serve()` from my SDK of choice? + +TODO(cmc): incoming. + + +### What happens when I use `rerun --serve`? + +TODO(cmc): incoming. + + +### Can the **Native Viewer** pull data from a **WebSocket Server**, like the **Web Viewer** does? + +TODO(cmc): incoming. diff --git a/docs/content/concepts/apps-and-recordings.md b/docs/content/concepts/apps-and-recordings.md index 4cc5115f0aca..790d88285af9 100644 --- a/docs/content/concepts/apps-and-recordings.md +++ b/docs/content/concepts/apps-and-recordings.md @@ -1,20 +1,48 @@ --- -title: Application IDs and Recording IDs -order: 500 +title: Recordings +order: 0 --- -## Application ID -When you initialize Rerun with [`rr.init`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) you need to set an Application ID. +Recordings are the core abstraction for organizing data in Rerun. -Your Rerun Viewer will store the Blueprint based on this Application ID. -This means that you can run your app and set up the Viewer to your liking, -and then when you run the app again the Rerun Viewer will remember how you set up your Space Views etc. +A Recording is a semantic collection of data with an associated _Recording ID_ (which is just another name for a UID). That's it. -## Recording ID -Each time you start logging using Rerun, a random _Recording ID_ is generated. -For instance, each `.rrd` file will have a unique Recording ID. +Recordings are a _logical abstraction_, not a physical one: a recording is not confined to a specific file, or folder, or database, or whichever physical storage you might think of. +Similarly, there is no such thing as "closing" a recording: as long as there exists or will exist a system somewhere that is capable of producing _chunks_ of data, and tagging these chunks with the appropriate _Recording ID_, then that recording is effectively still growing. Whether that happens today, tomorrow, or in some distant future. + +This design naturally allows for both the production and the storage of recordings to be horizontally distributed: +* Production can be handled by multiple producers that all log data to the same _Recording ID_, independently. +* Storage can be sharded over multiple independent files (or any other storage medium). + +You can learn more about sharding in the [dedicated documentation page](../howto/logging/shared-recordings.md). + +In practice, most Rerun recordings are encoded in binary files with the `.rrd` extension by default. This is our basic storage solution for recordings, which is specifically designed for streaming use cases (i.e. `.rrd` files do not offer random-access to the data within). +Note that [blueprints](../howto/configure-viewer-through-code.md) are recordings too, and by convention are stored in binary `.rbl` files. + + +## Application IDs + +Rerun recordings have an extra piece of metadata associated with them in addition to their _Recording ID_: an _Application ID_. _Application IDs_ are arbitrary user-defined strings. + +When you initialize the Rerun logging SDK, you need to set an _Application ID_. + +snippet: tutorials/custom-application-id + +The Rerun viewer will store your blueprint based on this _Application ID_. + +This means that you can run your app and set up the viewer to your liking, and then when you run the app again the Rerun viewer will remember how you set up your Space Views etc. +Different recordings (i.e. different _Recording IDs_) will share the same blueprint as long as they share the same _Application ID_. + +Check out the API to learn more about SDK initialization: +* [🐍 Python](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) +* [🦀 Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.new) +* [🌊 C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#abda6202900fa439fe5c27f7aa0d1105a) + + +## Recording IDs in practice + +Each time you start logging using Rerun, a random _Recording ID_ is generated. For instance, each `.rrd` file will have a unique _Recording ID_. This means you can have multiple recordings with different Recording IDs sharing the same application ID. -If you want to log from multiple processes and want all the log data to show up -together in the viewer, you need to make sure all processes use the same Recording ID. +If you want to log from multiple processes and want all the log data to show up together in the viewer, you need to make sure all processes use the same Recording ID. diff --git a/docs/content/concepts/blueprint.md b/docs/content/concepts/blueprint.md index 6233a3ace4db..3034d82d1134 100644 --- a/docs/content/concepts/blueprint.md +++ b/docs/content/concepts/blueprint.md @@ -1,5 +1,5 @@ --- -title: Blueprint +title: Blueprints order: 600 --- diff --git a/docs/content/howto/embed-rerun-viewer.md b/docs/content/howto/embed-rerun-viewer.md index bc20b88bdf87..b9172f0bda97 100644 --- a/docs/content/howto/embed-rerun-viewer.md +++ b/docs/content/howto/embed-rerun-viewer.md @@ -1,5 +1,5 @@ --- title: Embed a Rerun Viewer hidden: true -redirect: howto/embed-web +redirect: howto/integrations/embed-web --- diff --git a/docs/content/howto/extend.md b/docs/content/howto/extend.md index 2085a08aba9b..6660f38cee34 100644 --- a/docs/content/howto/extend.md +++ b/docs/content/howto/extend.md @@ -1,6 +1,6 @@ --- title: Extend Rerun -order: 1000 +hidden: true --- There are currently two major ways of extending Rerun. You can use Rerun with [your own custom data](logging/custom-data.md), or [extend the Rerun Viewer](visualization/extend-ui.md) (currently Rust only). diff --git a/docs/content/howto/logging/shared-recordings.md b/docs/content/howto/logging/shared-recordings.md index 38f51eee5983..bd7695ad3b41 100644 --- a/docs/content/howto/logging/shared-recordings.md +++ b/docs/content/howto/logging/shared-recordings.md @@ -31,8 +31,14 @@ Here's a simple example of such a workflow: rerun /tmp/recording*.rrd # they share the same Recording ID! ``` -For more information, check out our [dedicated example](https://github.com/rerun-io/rerun/tree/main/examples/python/shared_recording). +For more information, check out our dedicated examples: +* [🐍 Python](https://github.com/rerun-io/rerun/blob/latest/examples/python/shared_recording/shared_recording.py) +* [🦀 Rust](https://github.com/rerun-io/rerun/blob/latest/examples/rust/shared_recording/src/main.rs) +* [🌊 C++](https://github.com/rerun-io/rerun/blob/latest/examples/cpp/shared_recording/main.cpp) -### Caveats -We do not yet provide a way to merge [multiple recording files](https://github.com/rerun-io/rerun/issues/4057) into a single one directly from the CLI, although you can load all of them in the Rerun Viewer first and then use the save feature ([which has its own issues](https://github.com/rerun-io/rerun/issues/3091)). +### Merging recordings with the Rerun CLI + +It is possible to merge multiple recording files into a single one using the [Rerun CLI](../../reference/cli.md#rerun-rrd-merge), e.g. `rerun rrd merge -o merged_recordings.rrd my_first_recording.rrd my_second_recording.rrd`. + +The Rerun CLI offers several options to manipulate recordings in different ways, check out [the CLI reference](../../reference/cli.md) for more information. diff --git a/docs/content/howto/notebook.md b/docs/content/howto/notebook.md index 118fb9a2e5ac..3adc04cf6e2d 100644 --- a/docs/content/howto/notebook.md +++ b/docs/content/howto/notebook.md @@ -1,5 +1,5 @@ --- title: Embed Rerun in notebooks hidden: true -redirect: howto/integrations/embed-notebook +redirect: howto/integrations/embed-notebooks --- diff --git a/docs/content/howto/using-native-loggers.md b/docs/content/howto/using-native-loggers.md index bf75732fa33f..bf3e74206204 100644 --- a/docs/content/howto/using-native-loggers.md +++ b/docs/content/howto/using-native-loggers.md @@ -1,19 +1,5 @@ --- title: Integrate Rerun with native loggers -order: 700 -description: How to use the Rerun SDK as a native logger for the host language +hidden: true +redirect: howto/integrations/integrate-host-loggers --- - -The Rerun SDK implements the native logging interfaces of its supported host languages, allowing you to transparently stream text logs logged with the native APIs into the Rerun Viewer. - -The details of how to achieve that vary language by language, see the snippets below. - -snippet: archetypes/text_log_integration - - - - - - - - diff --git a/docs/content/howto/visualization/configure-viewer-through-code.md b/docs/content/howto/visualization/configure-viewer-through-code.md index 5ff10d00de1c..75126bae68d8 100644 --- a/docs/content/howto/visualization/configure-viewer-through-code.md +++ b/docs/content/howto/visualization/configure-viewer-through-code.md @@ -1,5 +1,5 @@ --- -title: Configure the Viewer through code +title: Configure the Viewer through code (Blueprints) order: 100 --- diff --git a/docs/content/howto/visualization/reuse-blueprints.md b/docs/content/howto/visualization/reuse-blueprints.md new file mode 100644 index 000000000000..ee4c6f8fcb67 --- /dev/null +++ b/docs/content/howto/visualization/reuse-blueprints.md @@ -0,0 +1,44 @@ +--- +title: Re-use blueprints across sessions and SDKs +order: 150 +--- + +While the [blueprint APIs](configure-viewer-through-code) are currently only available through [🐍 Python](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/), blueprints can be saved to file and then re-logged as needed from any language our SDKs support. + +This enables you to re-use your saved blueprints both from any language we support as well as across different recordings that share a similar-enough structure, and makes it possible to share those blueprints with other users. + +For this you'll need to 1) create a blueprint file and B) _import_ that file when needed. + + +## Creating a blueprint file + +Blueprint files (`.rbl`, by convention) can currently be created in two ways. + +One is to use the Rerun viewer to interactively build the blueprint you want (e.g. by moving panels around, changing view settings, etc), and then using `Menu > Save blueprint` (or the equivalent palette command) to save the blueprint as a file. + +The other is to use the [🐍 Python blueprint API](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) to programmatically build the blueprint, and then use the [`Blueprint.save`](https://ref.rerun.io/docs/python/0.19.0/common/blueprint_apis/#rerun.blueprint.Blueprint.save) method to save it as a file: + +snippet: tutorials/visualization/save_blueprint + + +## (Re)Using a blueprint file + +There are two ways to re-use a blueprint file. + +The interactive way is to import the blueprint file directly into the Rerun viewer, using either `Menu > Import…` (or the equivalent palette command) or simply by drag-and-dropping the blueprint file into your recording. + +The programmatic way works by calling `log_file_from_path`: +* [🐍 Python `log_file_from_path`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log_file_from_path) +* [🦀 Rust `log_file_from_path`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path) +* [🌊 C++ `log_file_from_path`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a20798d7ea74cce5c8174e5cacd0a2c47) + +This method allows you to log any file that contains data that Rerun understands (in this case, blueprint data) as part of your current recording: + +snippet: tutorials/visualization/load_blueprint + + +## Limitation: dynamic blueprints + +Sometimes, you might need your blueprint to dynamically react to the data you receive at runtime (e.g. you want to create one view per anomaly detected, and there is no way of knowing how many anomalies you're going to detect until the program actually runs). + +The only way to deal with these situations today is to use the [🐍 Python](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) API. diff --git a/docs/content/reference/dataframes.md b/docs/content/reference/dataframes.md index a9349a8cd994..ede4aaf5a2b0 100644 --- a/docs/content/reference/dataframes.md +++ b/docs/content/reference/dataframes.md @@ -48,7 +48,7 @@ snippet: reference/dataframe_view_query #### Aside: re-using blueprint files from other SDKs -While the blueprint APIs are currently only available in Python, blueprints can be saved and re-logged as needed from any language our SDKs support. +While the blueprint APIs are currently only available through Python, blueprints can be saved and re-logged as needed from any language our SDKs support. First, save the blueprint to a file (`.rbl` by convention) using either the viewer (`Menu > Save blueprint`) or the python API: @@ -64,6 +64,8 @@ Check out the blueprint API and `log_file_from_path` references to learn more: * [🦀 Rust `log_file_from_path`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path) * [🌊 C++ `log_file_from_path`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a20798d7ea74cce5c8174e5cacd0a2c47) +You can learn more in our [dedicated page about blueprint re-use](../howto/visualization/reuse-blueprints). + ### Setting up dataframe view manually in the UI diff --git a/docs/content/reference/sdk/operating-modes.md b/docs/content/reference/sdk/operating-modes.md index 2606a9f13027..cf6c729067ee 100644 --- a/docs/content/reference/sdk/operating-modes.md +++ b/docs/content/reference/sdk/operating-modes.md @@ -8,6 +8,8 @@ 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. +Before reading this document, you might want to familiarize yourself with the [Rerun application model](../../concepts/app-model.md). + ## Operating modes The Rerun SDK provides 4 modes of operation: `spawn`, `connect`, `serve` & `save`. diff --git a/docs/snippets/CMakeLists.txt b/docs/snippets/CMakeLists.txt index 3f304fe1c1a7..ee52cdd57556 100644 --- a/docs/snippets/CMakeLists.txt +++ b/docs/snippets/CMakeLists.txt @@ -5,6 +5,7 @@ file(GLOB_RECURSE sources_list true ${CMAKE_CURRENT_SOURCE_DIR}/all/*.cpp) # Not complete examples: list(FILTER sources_list EXCLUDE REGEX .*/concepts/static/*) +list(FILTER sources_list EXCLUDE REGEX .*/tutorials/custom-application-id.*) list(FILTER sources_list EXCLUDE REGEX .*/tutorials/custom-recording-id.*) list(FILTER sources_list EXCLUDE REGEX .*/tutorials/log_line.*) list(FILTER sources_list EXCLUDE REGEX .*/tutorials/log-file.*) diff --git a/docs/snippets/all/concepts/app-model/native-async.cpp b/docs/snippets/all/concepts/app-model/native-async.cpp new file mode 100644 index 000000000000..5e035ed2ea59 --- /dev/null +++ b/docs/snippets/all/concepts/app-model/native-async.cpp @@ -0,0 +1,12 @@ +#include + +int main() { + // Open a local file handle to stream the data into. + const auto rec = rerun::RecordingStream("rerun_example_native_sync"); + rec.save("/tmp/my_recording.rrd").exit_on_failure(); + + // Log data as usual, thereby writing it into the file. + while (true) { + rec.log("log", rerun::TextLog("Logging things...")); + } +} diff --git a/docs/snippets/all/concepts/app-model/native-async.py b/docs/snippets/all/concepts/app-model/native-async.py new file mode 100755 index 000000000000..ed7cc903682b --- /dev/null +++ b/docs/snippets/all/concepts/app-model/native-async.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 + +import rerun as rr + +rr.init("rerun_example_native_sync") + +# Open a local file handle to stream the data into. +rr.save("/tmp/my_recording.rrd") + +# Log data as usual, thereby writing it into the file. +while True: + rr.log("/", rr.TextLog("Logging things...")) diff --git a/docs/snippets/all/concepts/app-model/native-async.rs b/docs/snippets/all/concepts/app-model/native-async.rs new file mode 100644 index 000000000000..e58ca5e8a7d8 --- /dev/null +++ b/docs/snippets/all/concepts/app-model/native-async.rs @@ -0,0 +1,10 @@ +fn main() -> Result<(), Box> { + // Open a local file handle to stream the data into. + let rec = rerun::RecordingStreamBuilder::new("rerun_example_native_sync") + .save("/tmp/my_recording.rrd")?; + + // Log data as usual, thereby writing it into the file. + loop { + rec.log("/", &rerun::TextLog::new("Logging things..."))?; + } +} diff --git a/docs/snippets/all/concepts/app-model/native-sync.cpp b/docs/snippets/all/concepts/app-model/native-sync.cpp new file mode 100644 index 000000000000..c36bcc0faa77 --- /dev/null +++ b/docs/snippets/all/concepts/app-model/native-sync.cpp @@ -0,0 +1,13 @@ +#include + +int main() { + // Connect to the Rerun TCP server using the default address and + // port: localhost:9876 + const auto rec = rerun::RecordingStream("rerun_example_native_sync"); + rec.connect().exit_on_failure(); + + // Log data as usual, thereby pushing it into the TCP socket. + while (true) { + rec.log("log", rerun::TextLog("Logging things...")); + } +} diff --git a/docs/snippets/all/concepts/app-model/native-sync.py b/docs/snippets/all/concepts/app-model/native-sync.py new file mode 100755 index 000000000000..6847e4e3fb71 --- /dev/null +++ b/docs/snippets/all/concepts/app-model/native-sync.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import rerun as rr + +rr.init("rerun_example_native_sync") + +# Connect to the Rerun TCP server using the default address and +# port: localhost:9876 +rr.connect() + +# Log data as usual, thereby pushing it into the TCP socket. +while True: + rr.log("/", rr.TextLog("Logging things...")) diff --git a/docs/snippets/all/concepts/app-model/native-sync.rs b/docs/snippets/all/concepts/app-model/native-sync.rs new file mode 100644 index 000000000000..2db8313dd9df --- /dev/null +++ b/docs/snippets/all/concepts/app-model/native-sync.rs @@ -0,0 +1,10 @@ +fn main() -> Result<(), Box> { + // Connect to the Rerun TCP server using the default address and + // port: localhost:9876 + let rec = rerun::RecordingStreamBuilder::new("rerun_example_native_sync").connect()?; + + // Log data as usual, thereby pushing it into the TCP socket. + loop { + rec.log("/", &rerun::TextLog::new("Logging things..."))?; + } +} diff --git a/docs/snippets/all/tutorials/custom-application-id.cpp b/docs/snippets/all/tutorials/custom-application-id.cpp new file mode 100644 index 000000000000..f7af79c224ec --- /dev/null +++ b/docs/snippets/all/tutorials/custom-application-id.cpp @@ -0,0 +1 @@ +const auto rec = rerun::RecordingStream("my_custom_application_id"); diff --git a/docs/snippets/all/tutorials/custom-application-id.py b/docs/snippets/all/tutorials/custom-application-id.py new file mode 100644 index 000000000000..9a73730ca547 --- /dev/null +++ b/docs/snippets/all/tutorials/custom-application-id.py @@ -0,0 +1 @@ +rr.init("my_custom_application_id") diff --git a/docs/snippets/all/tutorials/custom-application-id.rs b/docs/snippets/all/tutorials/custom-application-id.rs new file mode 100644 index 000000000000..9a22f6479cac --- /dev/null +++ b/docs/snippets/all/tutorials/custom-application-id.rs @@ -0,0 +1 @@ +rerun::RecordingStreamBuilder::new("rerun_example_shared_recording") diff --git a/docs/snippets/all/tutorials/custom-recording-id.py b/docs/snippets/all/tutorials/custom-recording-id.py index 209cfd524b80..93a68f04cf95 100644 --- a/docs/snippets/all/tutorials/custom-recording-id.py +++ b/docs/snippets/all/tutorials/custom-recording-id.py @@ -1,3 +1 @@ -import rerun as rr - rr.init("rerun_example_shared_recording", recording_id="my_shared_recording") diff --git a/docs/snippets/all/tutorials/visualization/load_blueprint.py b/docs/snippets/all/tutorials/visualization/load_blueprint.py new file mode 100644 index 000000000000..8b8df583a816 --- /dev/null +++ b/docs/snippets/all/tutorials/visualization/load_blueprint.py @@ -0,0 +1,12 @@ +"""Demonstrates how to programmatically re-use a blueprint stored in a file.""" + +import sys + +import rerun as rr + +path_to_rbl = sys.argv[1] + +rr.init("rerun_example_reuse_blueprint_file", spawn=True) +rr.log_file_from_path(path_to_rbl) + +# … log some data as usual … diff --git a/docs/snippets/all/tutorials/visualization/save_blueprint.py b/docs/snippets/all/tutorials/visualization/save_blueprint.py new file mode 100644 index 000000000000..6c6896915f92 --- /dev/null +++ b/docs/snippets/all/tutorials/visualization/save_blueprint.py @@ -0,0 +1,23 @@ +"""Craft an example blueprint with the python API and save it to a file for future use.""" + +import sys + +import rerun.blueprint as rrb + +path_to_rbl = sys.argv[1] + +rrb.Blueprint( + rrb.Horizontal( + rrb.Grid( + rrb.BarChartView(name="Bar Chart", origin="/bar_chart"), + rrb.TimeSeriesView( + name="Curves", + origin="/curves", + ), + ), + rrb.TextDocumentView(name="Description", origin="/description"), + column_shares=[3, 1], + ), + rrb.SelectionPanel(state="collapsed"), + rrb.TimePanel(state="collapsed"), +).save("your_blueprint_name", path_to_rbl) diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index a58f5eb3031c..4620e4dafb70 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -91,6 +91,11 @@ views = [ "cpp", "rust", ] +"tutorials/custom-application-id" = [ # Not a complete examples + "cpp", + "rust", + "py", +] "tutorials/custom-recording-id" = [ # Not a complete examples "cpp", "rust", diff --git a/pixi.lock b/pixi.lock index 9a2efa0e0616..2506d9ee7279 100644 --- a/pixi.lock +++ b/pixi.lock @@ -12997,8 +12997,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/b3/02/f7f7bb6b6af6031edb11037639c697b912e1dea2db94d436e681aea2f495/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d + url: https://files.pythonhosted.org/packages/5a/e4/bf8034d25edaa495da3c8a3405627d2e35758e44ff6eaa7948092646fdcc/argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl + sha256: e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -13010,8 +13010,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/5a/e4/bf8034d25edaa495da3c8a3405627d2e35758e44ff6eaa7948092646fdcc/argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl - sha256: e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 + url: https://files.pythonhosted.org/packages/37/2c/e34e47c7dee97ba6f01a6203e0383e15b60fb85d78ac9a15cd066f6fe28b/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl + sha256: b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -13023,8 +13023,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/ec/f7/378254e6dd7ae6f31fe40c8649eea7d4832a42243acaf0f1fff9083b2bed/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae + url: https://files.pythonhosted.org/packages/b3/02/f7f7bb6b6af6031edb11037639c697b912e1dea2db94d436e681aea2f495/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -13036,8 +13036,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/37/2c/e34e47c7dee97ba6f01a6203e0383e15b60fb85d78ac9a15cd066f6fe28b/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl - sha256: b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f + url: https://files.pythonhosted.org/packages/ec/f7/378254e6dd7ae6f31fe40c8649eea7d4832a42243acaf0f1fff9083b2bed/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -14687,8 +14687,8 @@ packages: - kind: pypi name: black version: 24.10.0 - url: https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl - sha256: 3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d + url: https://files.pythonhosted.org/packages/c2/cc/7496bb63a9b06a954d3d0ac9fe7a73f3bf1cd92d7a58877c27f4ad1e9d41/black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14706,8 +14706,8 @@ packages: - kind: pypi name: black version: 24.10.0 - url: https://files.pythonhosted.org/packages/c2/cc/7496bb63a9b06a954d3d0ac9fe7a73f3bf1cd92d7a58877c27f4ad1e9d41/black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad + url: https://files.pythonhosted.org/packages/a3/95/17d4a09a5be5f8c65aa4a361444d95edc45def0de887810f508d3f65db7a/black-24.10.0-cp311-cp311-win_amd64.whl + sha256: 394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14725,8 +14725,8 @@ packages: - kind: pypi name: black version: 24.10.0 - url: https://files.pythonhosted.org/packages/c9/9b/2db8045b45844665c720dcfe292fdaf2e49825810c0103e1191515fc101a/black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl - sha256: 4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392 + url: https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl + sha256: 3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14744,8 +14744,8 @@ packages: - kind: pypi name: black version: 24.10.0 - url: https://files.pythonhosted.org/packages/a3/95/17d4a09a5be5f8c65aa4a361444d95edc45def0de887810f508d3f65db7a/black-24.10.0-cp311-cp311-win_amd64.whl - sha256: 394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175 + url: https://files.pythonhosted.org/packages/c9/9b/2db8045b45844665c720dcfe292fdaf2e49825810c0103e1191515fc101a/black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl + sha256: 4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -15347,32 +15347,32 @@ packages: - kind: pypi name: cffi version: 1.17.1 - url: https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl - sha256: caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 + url: https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.17.1 - url: https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf + url: https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl + sha256: caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.17.1 - url: https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 + url: https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.17.1 - url: https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d + url: https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 requires_dist: - pycparser requires_python: '>=3.8' @@ -15382,6 +15382,12 @@ packages: url: https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl sha256: bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.4.0 + url: https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc + requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.4.0 @@ -15400,12 +15406,6 @@ packages: url: https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl sha256: c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944 requires_python: '>=3.7.0' -- kind: pypi - name: charset-normalizer - version: 3.4.0 - url: https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc - requires_python: '>=3.7.0' - kind: conda name: clang version: 16.0.6 @@ -16339,8 +16339,8 @@ packages: - kind: pypi name: contourpy version: 1.3.0 - url: https://files.pythonhosted.org/packages/e1/5d/3056c167fa4486900dfbd7e26a2fdc2338dc58eee36d490a0ed3ddda5ded/contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66 + url: https://files.pythonhosted.org/packages/b3/1f/9375917786cb39270b0ee6634536c0e22abf225825602688990d8f5c6c19/contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad requires_dist: - numpy>=1.23 - furo ; extra == 'docs' @@ -16364,8 +16364,8 @@ packages: - kind: pypi name: contourpy version: 1.3.0 - url: https://files.pythonhosted.org/packages/b3/1f/9375917786cb39270b0ee6634536c0e22abf225825602688990d8f5c6c19/contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad + url: https://files.pythonhosted.org/packages/8d/2f/804f02ff30a7fae21f98198828d0857439ec4c91a96e20cf2d6c49372966/contourpy-1.3.0-cp311-cp311-win_amd64.whl + sha256: 6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67 requires_dist: - numpy>=1.23 - furo ; extra == 'docs' @@ -16389,8 +16389,8 @@ packages: - kind: pypi name: contourpy version: 1.3.0 - url: https://files.pythonhosted.org/packages/03/33/003065374f38894cdf1040cef474ad0546368eea7e3a51d48b8a423961f8/contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d + url: https://files.pythonhosted.org/packages/e1/5d/3056c167fa4486900dfbd7e26a2fdc2338dc58eee36d490a0ed3ddda5ded/contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66 requires_dist: - numpy>=1.23 - furo ; extra == 'docs' @@ -16414,8 +16414,8 @@ packages: - kind: pypi name: contourpy version: 1.3.0 - url: https://files.pythonhosted.org/packages/8d/2f/804f02ff30a7fae21f98198828d0857439ec4c91a96e20cf2d6c49372966/contourpy-1.3.0-cp311-cp311-win_amd64.whl - sha256: 6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67 + url: https://files.pythonhosted.org/packages/03/33/003065374f38894cdf1040cef474ad0546368eea7e3a51d48b8a423961f8/contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d requires_dist: - numpy>=1.23 - furo ; extra == 'docs' @@ -16508,8 +16508,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/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' @@ -16536,8 +16536,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' @@ -16564,8 +16564,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/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' @@ -16592,8 +16592,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/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' @@ -16830,14 +16830,14 @@ packages: - kind: pypi name: debugpy version: 1.8.7 - url: https://files.pythonhosted.org/packages/46/6f/2bb0bba20b8b74b7c341379dd99275cf6aa7722c1948fa99728716aad1b9/debugpy-1.8.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: cba1d078cf2e1e0b8402e6bda528bf8fda7ccd158c3dba6c012b7897747c41a0 + url: https://files.pythonhosted.org/packages/7d/e1/e9ac2d546143a4defbaa2e609e173c912fb989cdfb5385c9771770a6bf5c/debugpy-1.8.7-cp311-cp311-win_amd64.whl + sha256: 6e1c4ffb0c79f66e89dfd97944f335880f0d50ad29525dc792785384923e2211 requires_python: '>=3.8' - kind: pypi name: debugpy version: 1.8.7 - url: https://files.pythonhosted.org/packages/7d/e1/e9ac2d546143a4defbaa2e609e173c912fb989cdfb5385c9771770a6bf5c/debugpy-1.8.7-cp311-cp311-win_amd64.whl - sha256: 6e1c4ffb0c79f66e89dfd97944f335880f0d50ad29525dc792785384923e2211 + url: https://files.pythonhosted.org/packages/46/6f/2bb0bba20b8b74b7c341379dd99275cf6aa7722c1948fa99728716aad1b9/debugpy-1.8.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: cba1d078cf2e1e0b8402e6bda528bf8fda7ccd158c3dba6c012b7897747c41a0 requires_python: '>=3.8' - kind: pypi name: decorator @@ -17907,8 +17907,8 @@ packages: - kind: pypi name: fonttools version: 4.54.1 - url: https://files.pythonhosted.org/packages/45/4b/8a32f56a13e78256192f77d6b65583c43538c7955f5420887bb574b91ddf/fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7 + url: https://files.pythonhosted.org/packages/aa/2c/8b5d82fe2d9c7f260fb73121418f5e07d4e38c329ea3886a5b0e55586113/fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl + sha256: 5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -17944,8 +17944,8 @@ packages: - kind: pypi name: fonttools version: 4.54.1 - url: https://files.pythonhosted.org/packages/aa/2c/8b5d82fe2d9c7f260fb73121418f5e07d4e38c329ea3886a5b0e55586113/fonttools-4.54.1-cp311-cp311-macosx_10_9_universal2.whl - sha256: 5419771b64248484299fa77689d4f3aeed643ea6630b2ea750eeab219588ba20 + url: https://files.pythonhosted.org/packages/63/f1/3a081cd047d83b5966cb0d7ef3fea929ee6eddeb94d8fbfdb2a19bd60cc7/fonttools-4.54.1-cp311-cp311-win_amd64.whl + sha256: 07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -17981,8 +17981,8 @@ packages: - kind: pypi name: fonttools version: 4.54.1 - url: https://files.pythonhosted.org/packages/96/13/748b7f7239893ff0796de11074b0ad8aa4c3da2d9f4d79a128b0b16147f3/fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07 + url: https://files.pythonhosted.org/packages/45/4b/8a32f56a13e78256192f77d6b65583c43538c7955f5420887bb574b91ddf/fonttools-4.54.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 76ae5091547e74e7efecc3cbf8e75200bc92daaeb88e5433c5e3e95ea8ce5aa7 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18018,8 +18018,8 @@ packages: - kind: pypi name: fonttools version: 4.54.1 - url: https://files.pythonhosted.org/packages/63/f1/3a081cd047d83b5966cb0d7ef3fea929ee6eddeb94d8fbfdb2a19bd60cc7/fonttools-4.54.1-cp311-cp311-win_amd64.whl - sha256: 07e005dc454eee1cc60105d6a29593459a06321c21897f769a281ff2d08939f6 + url: https://files.pythonhosted.org/packages/96/13/748b7f7239893ff0796de11074b0ad8aa4c3da2d9f4d79a128b0b16147f3/fonttools-4.54.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 82834962b3d7c5ca98cb56001c33cf20eb110ecf442725dc5fdf36d16ed1ab07 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18249,26 +18249,26 @@ packages: - kind: pypi name: freetype-py version: 2.5.1 - url: https://files.pythonhosted.org/packages/a2/93/280ad06dc944e40789b0a641492321a2792db82edda485369cbc59d14366/freetype_py-2.5.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 5d2f6b3d68496797da23204b3b9c4e77e67559c80390fc0dc8b3f454ae1cd819 + url: https://files.pythonhosted.org/packages/38/a8/258dd138ebe60c79cd8cfaa6d021599208a33f0175a5e29b01f60c9ab2c7/freetype_py-2.5.1-py3-none-macosx_10_9_universal2.whl + sha256: d01ded2557694f06aa0413f3400c0c0b2b5ebcaabeef7aaf3d756be44f51e90b requires_python: '>=3.7' - kind: pypi name: freetype-py version: 2.5.1 - url: https://files.pythonhosted.org/packages/38/a8/258dd138ebe60c79cd8cfaa6d021599208a33f0175a5e29b01f60c9ab2c7/freetype_py-2.5.1-py3-none-macosx_10_9_universal2.whl - sha256: d01ded2557694f06aa0413f3400c0c0b2b5ebcaabeef7aaf3d756be44f51e90b + url: https://files.pythonhosted.org/packages/93/6e/bd7fbfacca077bc6f34f1a1109800a2c41ab50f4704d3a0507ba41009915/freetype_py-2.5.1-py3-none-win_amd64.whl + sha256: 0b7f8e0342779f65ca13ef8bc103938366fecade23e6bb37cb671c2b8ad7f124 requires_python: '>=3.7' - kind: pypi name: freetype-py version: 2.5.1 - url: https://files.pythonhosted.org/packages/b6/36/853cad240ec63e21a37a512ee19c896b655ce1772d803a3dd80fccfe63fe/freetype_py-2.5.1-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl - sha256: 289b443547e03a4f85302e3ac91376838e0d11636050166662a4f75e3087ed0b + url: https://files.pythonhosted.org/packages/a2/93/280ad06dc944e40789b0a641492321a2792db82edda485369cbc59d14366/freetype_py-2.5.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 5d2f6b3d68496797da23204b3b9c4e77e67559c80390fc0dc8b3f454ae1cd819 requires_python: '>=3.7' - kind: pypi name: freetype-py version: 2.5.1 - url: https://files.pythonhosted.org/packages/93/6e/bd7fbfacca077bc6f34f1a1109800a2c41ab50f4704d3a0507ba41009915/freetype_py-2.5.1-py3-none-win_amd64.whl - sha256: 0b7f8e0342779f65ca13ef8bc103938366fecade23e6bb37cb671c2b8ad7f124 + url: https://files.pythonhosted.org/packages/b6/36/853cad240ec63e21a37a512ee19c896b655ce1772d803a3dd80fccfe63fe/freetype_py-2.5.1-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl + sha256: 289b443547e03a4f85302e3ac91376838e0d11636050166662a4f75e3087ed0b requires_python: '>=3.7' - kind: conda name: fribidi @@ -19004,8 +19004,8 @@ packages: - kind: pypi name: google-crc32c version: 1.6.0 - url: https://files.pythonhosted.org/packages/00/9c/f5f5af3ddaa7a639d915f8f58b09bbb8d1db90ecd0459b62cd430eb9a4b6/google_crc32c-1.6.0-cp311-cp311-win_amd64.whl - sha256: bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3 + url: https://files.pythonhosted.org/packages/67/1e/4870896fc81ec77b1b5ebae7fdd680d5a4d40e19a4b6d724032f996ca77a/google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f requires_dist: - importlib-resources>=1.3 ; python_version < '3.9' and os_name == 'nt' - pytest ; extra == 'testing' @@ -19013,8 +19013,8 @@ packages: - kind: pypi name: google-crc32c version: 1.6.0 - url: https://files.pythonhosted.org/packages/67/72/c3298da1a3773102359c5a78f20dae8925f5ea876e37354415f68594a6fb/google_crc32c-1.6.0.tar.gz - sha256: 6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc + url: https://files.pythonhosted.org/packages/00/9c/f5f5af3ddaa7a639d915f8f58b09bbb8d1db90ecd0459b62cd430eb9a4b6/google_crc32c-1.6.0-cp311-cp311-win_amd64.whl + sha256: bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3 requires_dist: - importlib-resources>=1.3 ; python_version < '3.9' and os_name == 'nt' - pytest ; extra == 'testing' @@ -19022,8 +19022,8 @@ packages: - kind: pypi name: google-crc32c version: 1.6.0 - url: https://files.pythonhosted.org/packages/67/1e/4870896fc81ec77b1b5ebae7fdd680d5a4d40e19a4b6d724032f996ca77a/google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f + url: https://files.pythonhosted.org/packages/67/72/c3298da1a3773102359c5a78f20dae8925f5ea876e37354415f68594a6fb/google_crc32c-1.6.0.tar.gz + sha256: 6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc requires_dist: - importlib-resources>=1.3 ; python_version < '3.9' and os_name == 'nt' - pytest ; extra == 'testing' @@ -20385,8 +20385,8 @@ packages: - kind: pypi name: jaxlib version: 0.4.34 - url: https://files.pythonhosted.org/packages/c7/d0/6bc81c0b1d507f403e6085ce76a429e6d7f94749d742199252e299dd1424/jaxlib-0.4.34-cp311-cp311-manylinux2014_x86_64.whl - sha256: 3bcfa639ca3cfaf86c8ceebd5fc0d47300fd98a078014a1d0cc03133e1523d5f + url: https://files.pythonhosted.org/packages/9d/5d/7e71019af5f6fdebe6c10eab97d01f44b931d94609330da9e142cb155f8c/jaxlib-0.4.34-cp311-cp311-win_amd64.whl + sha256: 133070d4fec5525ffea4dc72956398c1cf647a04dcb37f8a935ee82af78d9965 requires_dist: - scipy>=1.10 - numpy>=1.24 @@ -20396,8 +20396,8 @@ packages: - kind: pypi name: jaxlib version: 0.4.34 - url: https://files.pythonhosted.org/packages/9d/5d/7e71019af5f6fdebe6c10eab97d01f44b931d94609330da9e142cb155f8c/jaxlib-0.4.34-cp311-cp311-win_amd64.whl - sha256: 133070d4fec5525ffea4dc72956398c1cf647a04dcb37f8a935ee82af78d9965 + url: https://files.pythonhosted.org/packages/c7/d0/6bc81c0b1d507f403e6085ce76a429e6d7f94749d742199252e299dd1424/jaxlib-0.4.34-cp311-cp311-manylinux2014_x86_64.whl + sha256: 3bcfa639ca3cfaf86c8ceebd5fc0d47300fd98a078014a1d0cc03133e1523d5f requires_dist: - scipy>=1.10 - numpy>=1.24 @@ -20973,26 +20973,26 @@ packages: - kind: pypi name: kiwisolver version: 1.4.7 - url: https://files.pythonhosted.org/packages/b8/01/946852b13057a162a8c32c4c8d2e9ed79f0bb5d86569a40c0b5fb103e373/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02 + url: https://files.pythonhosted.org/packages/e5/20/8c75caed8f2462d63c7fd65e16c832b8f76cda331ac9e615e914ee80bac9/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95 requires_python: '>=3.8' - kind: pypi name: kiwisolver version: 1.4.7 - url: https://files.pythonhosted.org/packages/e5/20/8c75caed8f2462d63c7fd65e16c832b8f76cda331ac9e615e914ee80bac9/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95 + url: https://files.pythonhosted.org/packages/a1/65/d43e9a20aabcf2e798ad1aff6c143ae3a42cf506754bcb6a7ed8259c8425/kiwisolver-1.4.7-cp311-cp311-win_amd64.whl + sha256: 929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b requires_python: '>=3.8' - kind: pypi name: kiwisolver version: 1.4.7 - url: https://files.pythonhosted.org/packages/a7/4b/2db7af3ed3af7c35f388d5f53c28e155cd402a55432d800c543dc6deb731/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18 + url: https://files.pythonhosted.org/packages/b8/01/946852b13057a162a8c32c4c8d2e9ed79f0bb5d86569a40c0b5fb103e373/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02 requires_python: '>=3.8' - kind: pypi name: kiwisolver version: 1.4.7 - url: https://files.pythonhosted.org/packages/a1/65/d43e9a20aabcf2e798ad1aff6c143ae3a42cf506754bcb6a7ed8259c8425/kiwisolver-1.4.7-cp311-cp311-win_amd64.whl - sha256: 929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b + url: https://files.pythonhosted.org/packages/a7/4b/2db7af3ed3af7c35f388d5f53c28e155cd402a55432d800c543dc6deb731/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18 requires_python: '>=3.8' - kind: pypi name: kiwisolver @@ -29009,26 +29009,26 @@ packages: - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2 + url: https://files.pythonhosted.org/packages/95/8c/de3276d773ab6ce3ad676df5fab5aac19696b2956319d65d7dd88fb10f19/llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/95/8c/de3276d773ab6ce3ad676df5fab5aac19696b2956319d65d7dd88fb10f19/llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98 + url: https://files.pythonhosted.org/packages/20/ab/ed5ed3688c6ba4f0b8d789da19fd8e30a9cf7fc5852effe311bc5aefe73e/llvmlite-0.43.0-cp311-cp311-win_amd64.whl + sha256: d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/6b/99/5d00a7d671b1ba1751fc9f19d3b36f3300774c6eebe2bcdb5f6191763eb4/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749 + url: https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/20/ab/ed5ed3688c6ba4f0b8d789da19fd8e30a9cf7fc5852effe311bc5aefe73e/llvmlite-0.43.0-cp311-cp311-win_amd64.whl - sha256: d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91 + url: https://files.pythonhosted.org/packages/6b/99/5d00a7d671b1ba1751fc9f19d3b36f3300774c6eebe2bcdb5f6191763eb4/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749 requires_python: '>=3.9' - kind: pypi name: llvmlite @@ -29047,8 +29047,8 @@ packages: - kind: pypi name: lxml version: 5.3.0 - url: https://files.pythonhosted.org/packages/ee/73/623ecea6ca3c530dd0a4ed0d00d9702e0e85cd5624e2d5b93b005fe00abd/lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: 69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16 + url: https://files.pythonhosted.org/packages/ac/8a/ae6325e994e2052de92f894363b038351c50ee38749d30cc6b6d96aaf90f/lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -29059,8 +29059,8 @@ packages: - kind: pypi name: lxml version: 5.3.0 - url: https://files.pythonhosted.org/packages/ac/8a/ae6325e994e2052de92f894363b038351c50ee38749d30cc6b6d96aaf90f/lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18 + url: https://files.pythonhosted.org/packages/c3/b5/91c2249bfac02ee514ab135e9304b89d55967be7e53e94a879b74eec7a5c/lxml-5.3.0-cp311-cp311-win_amd64.whl + sha256: 9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -29071,8 +29071,8 @@ packages: - kind: pypi name: lxml version: 5.3.0 - url: https://files.pythonhosted.org/packages/42/07/b29571a58a3a80681722ea8ed0ba569211d9bb8531ad49b5cacf6d409185/lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654 + url: https://files.pythonhosted.org/packages/ee/73/623ecea6ca3c530dd0a4ed0d00d9702e0e85cd5624e2d5b93b005fe00abd/lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: 69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -29083,8 +29083,8 @@ packages: - kind: pypi name: lxml version: 5.3.0 - url: https://files.pythonhosted.org/packages/c3/b5/91c2249bfac02ee514ab135e9304b89d55967be7e53e94a879b74eec7a5c/lxml-5.3.0-cp311-cp311-win_amd64.whl - sha256: 9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1 + url: https://files.pythonhosted.org/packages/42/07/b29571a58a3a80681722ea8ed0ba569211d9bb8531ad49b5cacf6d409185/lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -29314,6 +29314,12 @@ packages: - pytest-cov ; extra == 'testing' - pytest-regressions ; extra == 'testing' requires_python: '>=3.8' +- kind: pypi + name: markupsafe + version: 3.0.1 + url: https://files.pythonhosted.org/packages/ae/1d/7d5ec8bcfd9c2db235d720fa51d818b7e2abc45250ce5f53dd6cb60409ca/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b + requires_python: '>=3.9' - kind: pypi name: markupsafe version: 3.0.1 @@ -29323,8 +29329,8 @@ packages: - kind: pypi name: markupsafe version: 3.0.1 - url: https://files.pythonhosted.org/packages/ae/1d/7d5ec8bcfd9c2db235d720fa51d818b7e2abc45250ce5f53dd6cb60409ca/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b + url: https://files.pythonhosted.org/packages/ce/af/2f5d88a7fc7226bd34c6e15f6061246ad8cff979da9f19d11bdd0addd8e2/MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl + sha256: 26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad requires_python: '>=3.9' - kind: pypi name: markupsafe @@ -29338,12 +29344,6 @@ packages: url: https://files.pythonhosted.org/packages/58/26/78f161d602fb03804118905e5faacafc0ec592bbad71aaee62537529813a/MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl sha256: 973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7 requires_python: '>=3.9' -- kind: pypi - name: markupsafe - version: 3.0.1 - url: https://files.pythonhosted.org/packages/ce/af/2f5d88a7fc7226bd34c6e15f6061246ad8cff979da9f19d11bdd0addd8e2/MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl - sha256: 26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad - requires_python: '>=3.9' - kind: conda name: markupsafe version: 3.0.1 @@ -29474,8 +29474,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f + url: https://files.pythonhosted.org/packages/77/c2/f9d7fe80a8fcce9bb128d1381c6fe41a8d286d7e18395e273002e8e0fa34/matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl + sha256: d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -29496,8 +29496,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/77/c2/f9d7fe80a8fcce9bb128d1381c6fe41a8d286d7e18395e273002e8e0fa34/matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl - sha256: d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772 + url: https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl + sha256: ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -29518,8 +29518,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447 + url: https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -29540,8 +29540,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl - sha256: ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7 + url: https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -29729,32 +29729,32 @@ packages: - kind: pypi name: mediapipe version: 0.10.11 - url: https://files.pythonhosted.org/packages/c9/e4/3e645a8f87577553194a2a15383a60d61b8381cf864e903e43e4c6eb58e0/mediapipe-0.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: ea751e043909ba7bbe27e7afdbcdafd79723d50ef4165afcaae431ab428eea13 + url: https://files.pythonhosted.org/packages/67/4c/569cbb27c6b1e09c7c088ca1e7ce88573dfb9769cfc79ebeacdab0f6903d/mediapipe-0.10.11-cp311-cp311-win_amd64.whl + sha256: 36231eaf23cd795a923a8b015d36bd6e410a8e997c36dd9432db0157b822b181 requires_dist: - absl-py - attrs>=19.1.0 - flatbuffers>=2.0 - jax - - jaxlib - matplotlib - numpy - - torch - opencv-contrib-python - protobuf<4,>=3.11 - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 - url: https://files.pythonhosted.org/packages/67/4c/569cbb27c6b1e09c7c088ca1e7ce88573dfb9769cfc79ebeacdab0f6903d/mediapipe-0.10.11-cp311-cp311-win_amd64.whl - sha256: 36231eaf23cd795a923a8b015d36bd6e410a8e997c36dd9432db0157b822b181 + url: https://files.pythonhosted.org/packages/c9/e4/3e645a8f87577553194a2a15383a60d61b8381cf864e903e43e4c6eb58e0/mediapipe-0.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: ea751e043909ba7bbe27e7afdbcdafd79723d50ef4165afcaae431ab428eea13 requires_dist: - absl-py - attrs>=19.1.0 - flatbuffers>=2.0 - jax + - jaxlib - matplotlib - numpy + - torch - opencv-contrib-python - protobuf<4,>=3.11 - sounddevice>=0.4.4 @@ -30014,8 +30014,8 @@ packages: - kind: pypi name: ml-dtypes version: 0.5.0 - url: https://files.pythonhosted.org/packages/89/65/ffdbf3489b0ba2213674ea347fad3a11747be64d2d23d888f9e5abe80a18/ml_dtypes-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 2e7534392682c3098bc7341648c650864207169c654aed83143d7a19c67ae06f + url: https://files.pythonhosted.org/packages/bf/31/058b9bcf9a81abd51623985add78711a915e4b0f6045baa5f9a0b41eb039/ml_dtypes-0.5.0-cp311-cp311-win_amd64.whl + sha256: dc74fd9995513d33eac63d64e436240f5494ec74d522a9f0920194942fc3d2d7 requires_dist: - numpy>=1.21 - numpy>=1.21.2 ; python_version >= '3.10' @@ -30031,8 +30031,8 @@ packages: - kind: pypi name: ml-dtypes version: 0.5.0 - url: https://files.pythonhosted.org/packages/bf/31/058b9bcf9a81abd51623985add78711a915e4b0f6045baa5f9a0b41eb039/ml_dtypes-0.5.0-cp311-cp311-win_amd64.whl - sha256: dc74fd9995513d33eac63d64e436240f5494ec74d522a9f0920194942fc3d2d7 + url: https://files.pythonhosted.org/packages/89/65/ffdbf3489b0ba2213674ea347fad3a11747be64d2d23d888f9e5abe80a18/ml_dtypes-0.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 2e7534392682c3098bc7341648c650864207169c654aed83143d7a19c67ae06f requires_dist: - numpy>=1.21 - numpy>=1.21.2 ; python_version >= '3.10' @@ -30080,40 +30080,40 @@ packages: - kind: pypi name: multidict version: 6.1.0 - url: https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb + url: https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 requires_dist: - typing-extensions>=4.1.0 ; python_version < '3.11' requires_python: '>=3.8' - kind: pypi name: multidict version: 6.1.0 - url: https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 + url: https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb requires_dist: - typing-extensions>=4.1.0 ; python_version < '3.11' requires_python: '>=3.8' - kind: pypi name: multidict version: 6.1.0 - url: https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl - sha256: 82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 + url: https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 requires_dist: - typing-extensions>=4.1.0 ; python_version < '3.11' requires_python: '>=3.8' - kind: pypi name: multidict version: 6.1.0 - url: https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b + url: https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl + sha256: 82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 requires_dist: - typing-extensions>=4.1.0 ; python_version < '3.11' requires_python: '>=3.8' - kind: pypi name: multidict version: 6.1.0 - url: https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 + url: https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b requires_dist: - typing-extensions>=4.1.0 ; python_version < '3.11' requires_python: '>=3.8' @@ -31018,8 +31018,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl - sha256: 5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703 + url: https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -31027,8 +31027,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8 + url: https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl + sha256: cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -31036,8 +31036,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - sha256: 4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8 + url: https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl + sha256: 5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -31045,8 +31045,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl - sha256: cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2 + url: https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + sha256: 4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -31445,8 +31445,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/f8/76/f76fe74b864f3cfa737173ca12e8890aad8369e980006fb8a0b6cd14c6c7/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 040575b69e4f3aa761676bace4e3d1b8485fbfaf77ef77b266ab6bda5a3b5e9b + url: https://files.pythonhosted.org/packages/09/94/d077c4c976c2d7a88812fd55396e92edae0e0c708689dbd8c8f508920e47/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl + sha256: dea80d4db73b8acccf9e16b5744bf3654f47b22745074263f0a6c10de26c5ef5 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' @@ -31462,8 +31462,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/09/94/d077c4c976c2d7a88812fd55396e92edae0e0c708689dbd8c8f508920e47/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl - sha256: dea80d4db73b8acccf9e16b5744bf3654f47b22745074263f0a6c10de26c5ef5 + url: https://files.pythonhosted.org/packages/a7/9e/7110d2c5d543ab03b9581dbb1f8e2429863e44e0c9b4960b766f230c1279/opencv_contrib_python-4.10.0.84-cp37-abi3-win_amd64.whl + sha256: 47ec3160dae75f70e099b286d1a2e086d20dac8b06e759f60eaf867e6bdecba7 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' @@ -31479,8 +31479,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/b0/e0/8f5d065ebb2e5941d289c5f653f944318f9e418bc5167bc6a346ab5e0f6a/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a261223db41f6e512d76deaf21c8fcfb4fbbcbc2de62ca7f74a05f2c9ee489ef + url: https://files.pythonhosted.org/packages/f8/76/f76fe74b864f3cfa737173ca12e8890aad8369e980006fb8a0b6cd14c6c7/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 040575b69e4f3aa761676bace4e3d1b8485fbfaf77ef77b266ab6bda5a3b5e9b 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' @@ -31496,8 +31496,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/a7/9e/7110d2c5d543ab03b9581dbb1f8e2429863e44e0c9b4960b766f230c1279/opencv_contrib_python-4.10.0.84-cp37-abi3-win_amd64.whl - sha256: 47ec3160dae75f70e099b286d1a2e086d20dac8b06e759f60eaf867e6bdecba7 + url: https://files.pythonhosted.org/packages/b0/e0/8f5d065ebb2e5941d289c5f653f944318f9e418bc5167bc6a346ab5e0f6a/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a261223db41f6e512d76deaf21c8fcfb4fbbcbc2de62ca7f74a05f2c9ee489ef 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' @@ -31976,8 +31976,8 @@ packages: - kind: pypi name: pandas version: 2.2.3 - url: https://files.pythonhosted.org/packages/45/fb/c4beeb084718598ba19aa9f5abbc8aed8b42f90930da861fcb1acdb54c3a/pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl - sha256: cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698 + url: https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -32068,8 +32068,8 @@ packages: - kind: pypi name: pandas version: 2.2.3 - url: https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039 + url: https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl + sha256: 3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -32160,8 +32160,8 @@ packages: - kind: pypi name: pandas version: 2.2.3 - url: https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc + url: https://files.pythonhosted.org/packages/45/fb/c4beeb084718598ba19aa9f5abbc8aed8b42f90930da861fcb1acdb54c3a/pandas-2.2.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl + sha256: cd8d0c3be0515c12fed0bdbae072551c8b54b7192c7b1fda0ba56059a0179698 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -32252,8 +32252,8 @@ packages: - kind: pypi name: pandas version: 2.2.3 - url: https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl - sha256: 3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5 + url: https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -32605,8 +32605,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/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' @@ -32629,8 +32629,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' @@ -32653,8 +32653,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/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -32677,8 +32677,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/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' @@ -32701,8 +32701,8 @@ packages: - kind: pypi name: pillow version: 11.0.0 - url: https://files.pythonhosted.org/packages/25/b3/2b54a1d541accebe6bd8b1358b34ceb2c509f51cb7dcda8687362490da5b/pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a + url: https://files.pythonhosted.org/packages/39/63/b3fc299528d7df1f678b0666002b37affe6b8751225c3d9c12cf530e73ed/pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -32728,8 +32728,8 @@ packages: - kind: pypi name: pillow version: 11.0.0 - url: https://files.pythonhosted.org/packages/39/63/b3fc299528d7df1f678b0666002b37affe6b8751225c3d9c12cf530e73ed/pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa + url: https://files.pythonhosted.org/packages/25/b3/2b54a1d541accebe6bd8b1358b34ceb2c509f51cb7dcda8687362490da5b/pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -32755,8 +32755,8 @@ packages: - kind: pypi name: pillow version: 11.0.0 - url: https://files.pythonhosted.org/packages/dc/83/1470c220a4ff06cd75fc609068f6605e567ea51df70557555c2ab6516b2c/pillow-11.0.0-cp311-cp311-win_amd64.whl - sha256: 52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291 + url: https://files.pythonhosted.org/packages/f0/eb/f7e21b113dd48a9c97d364e0915b3988c6a0b6207652f5a92372871b7aa4/pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -32782,8 +32782,8 @@ packages: - kind: pypi name: pillow version: 11.0.0 - url: https://files.pythonhosted.org/packages/fc/e4/130c5fab4a54d3991129800dd2801feeb4b118d7630148cd67f0e6269d4c/pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: 5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b + url: https://files.pythonhosted.org/packages/dc/83/1470c220a4ff06cd75fc609068f6605e567ea51df70557555c2ab6516b2c/pillow-11.0.0-cp311-cp311-win_amd64.whl + sha256: 52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -32809,8 +32809,8 @@ packages: - kind: pypi name: pillow version: 11.0.0 - url: https://files.pythonhosted.org/packages/f0/eb/f7e21b113dd48a9c97d364e0915b3988c6a0b6207652f5a92372871b7aa4/pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc + url: https://files.pythonhosted.org/packages/fc/e4/130c5fab4a54d3991129800dd2801feeb4b118d7630148cd67f0e6269d4c/pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: 5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -33191,26 +33191,26 @@ packages: - kind: pypi name: protobuf version: 5.28.2 - url: https://files.pythonhosted.org/packages/7d/46/3fdf7462160135aee6a530f1ec66665b5b4132fa2e1002ab971bc6ec2589/protobuf-5.28.2-cp310-abi3-win_amd64.whl - sha256: 2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132 + url: https://files.pythonhosted.org/packages/23/08/a1ce0415a115c2b703bfa798f06f0e43ca91dbe29d6180bf86a9287b15e2/protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl + sha256: 5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f requires_python: '>=3.8' - kind: pypi name: protobuf version: 5.28.2 - url: https://files.pythonhosted.org/packages/37/45/d2a760580f8f2ed2825ba44cb370e0a4011ddef85e728f46ea3dd565a8a5/protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl - sha256: a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7 + url: https://files.pythonhosted.org/packages/7d/46/3fdf7462160135aee6a530f1ec66665b5b4132fa2e1002ab971bc6ec2589/protobuf-5.28.2-cp310-abi3-win_amd64.whl + sha256: 2c69461a7fcc8e24be697624c09a839976d82ae75062b11a0972e41fd2cd9132 requires_python: '>=3.8' - kind: pypi name: protobuf version: 5.28.2 - url: https://files.pythonhosted.org/packages/23/08/a1ce0415a115c2b703bfa798f06f0e43ca91dbe29d6180bf86a9287b15e2/protobuf-5.28.2-cp38-abi3-manylinux2014_x86_64.whl - sha256: 5e8a95246d581eef20471b5d5ba010d55f66740942b95ba9b872d918c459452f + url: https://files.pythonhosted.org/packages/37/45/d2a760580f8f2ed2825ba44cb370e0a4011ddef85e728f46ea3dd565a8a5/protobuf-5.28.2-cp38-abi3-macosx_10_9_universal2.whl + sha256: a8b9403fc70764b08d2f593ce44f1d2920c5077bf7d311fefec999f8c40f78b7 requires_python: '>=3.8' - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl - sha256: ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0 + url: https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -33221,8 +33221,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd + url: https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl + sha256: ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -33233,8 +33233,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl - sha256: 33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 + url: https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl + sha256: c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -33245,8 +33245,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 + url: https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl + sha256: 33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -33257,8 +33257,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl - sha256: c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 + url: https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -33369,8 +33369,8 @@ packages: - kind: pypi name: psygnal version: 0.11.1 - url: https://files.pythonhosted.org/packages/68/76/d5c5bf5a932ec2dcdc4a23565815a1cc5fd96b03b26ff3f647cdff5ea62c/psygnal-0.11.1-py3-none-any.whl - sha256: 04255fe28828060a80320f8fda937c47bc0c21ca14f55a13eb7c494b165ea395 + url: https://files.pythonhosted.org/packages/25/92/6dcab17c3bb91fa3f250ebdbb66de55332436da836c4c547c26e3942877e/psygnal-0.11.1-cp311-cp311-macosx_10_16_x86_64.whl + sha256: 8f77317cbd11fbed5bfdd40ea41b4e551ee0cf37881cdbc325b67322af577485 requires_dist: - ipython ; extra == 'dev' - mypy ; extra == 'dev' @@ -33406,8 +33406,8 @@ packages: - kind: pypi name: psygnal version: 0.11.1 - url: https://files.pythonhosted.org/packages/25/92/6dcab17c3bb91fa3f250ebdbb66de55332436da836c4c547c26e3942877e/psygnal-0.11.1-cp311-cp311-macosx_10_16_x86_64.whl - sha256: 8f77317cbd11fbed5bfdd40ea41b4e551ee0cf37881cdbc325b67322af577485 + url: https://files.pythonhosted.org/packages/68/76/d5c5bf5a932ec2dcdc4a23565815a1cc5fd96b03b26ff3f647cdff5ea62c/psygnal-0.11.1-py3-none-any.whl + sha256: 04255fe28828060a80320f8fda937c47bc0c21ca14f55a13eb7c494b165ea395 requires_dist: - ipython ; extra == 'dev' - mypy ; extra == 'dev' @@ -33738,8 +33738,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl - sha256: a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03 + url: https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl + sha256: 1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -33777,8 +33777,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl - sha256: 1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977 + url: https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl + sha256: a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -33986,8 +33986,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/d5/9c/09cd808743338db170915deb35fa020b792d583238afe55f27c011f91c3c/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6a07f57f991e379959c0f4a1b9ea35d875876433b7f45c6d8fe6b718e58834bc + url: https://files.pythonhosted.org/packages/6b/56/9eedccfd1cfdaf6553d527bed0b2b5572550567a5786a8beb098027a3e5e/pycocotools-2.0.8-cp311-cp311-macosx_10_9_universal2.whl + sha256: 92bf788e6936fc52b57ccaaa78ecdaeac81872eebbfc45b6fe16ae18b85709bd requires_dist: - matplotlib>=2.1.0 - numpy @@ -33995,8 +33995,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/6b/56/9eedccfd1cfdaf6553d527bed0b2b5572550567a5786a8beb098027a3e5e/pycocotools-2.0.8-cp311-cp311-macosx_10_9_universal2.whl - sha256: 92bf788e6936fc52b57ccaaa78ecdaeac81872eebbfc45b6fe16ae18b85709bd + url: https://files.pythonhosted.org/packages/2e/f5/dfa78dc72e47dfe1ada7b37fedcb338454750470358a6dfcfdfda35fa337/pycocotools-2.0.8-cp311-cp311-win_amd64.whl + sha256: e680e27e58b840c105fa09a3bb1d91706038c5c8d7b7bf09c2e5ecbd1b05ad7f requires_dist: - matplotlib>=2.1.0 - numpy @@ -34004,8 +34004,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/8b/d4/7279d072c0255d07c541326f6058effb1b08190f49695bf2c22aae666878/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5968a1e5421719af9eb7ccee4c540bfb18b1fc95d30d9a48571d0aaeb159a1ae + url: https://files.pythonhosted.org/packages/d5/9c/09cd808743338db170915deb35fa020b792d583238afe55f27c011f91c3c/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6a07f57f991e379959c0f4a1b9ea35d875876433b7f45c6d8fe6b718e58834bc requires_dist: - matplotlib>=2.1.0 - numpy @@ -34013,8 +34013,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/2e/f5/dfa78dc72e47dfe1ada7b37fedcb338454750470358a6dfcfdfda35fa337/pycocotools-2.0.8-cp311-cp311-win_amd64.whl - sha256: e680e27e58b840c105fa09a3bb1d91706038c5c8d7b7bf09c2e5ecbd1b05ad7f + url: https://files.pythonhosted.org/packages/8b/d4/7279d072c0255d07c541326f6058effb1b08190f49695bf2c22aae666878/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5968a1e5421719af9eb7ccee4c540bfb18b1fc95d30d9a48571d0aaeb159a1ae requires_dist: - matplotlib>=2.1.0 - numpy @@ -34121,8 +34121,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' @@ -34133,8 +34133,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' @@ -34145,8 +34145,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' @@ -34552,32 +34552,32 @@ packages: - kind: pypi name: pyyaml version: 6.0.2 - url: https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 + url: https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 requires_python: '>=3.8' - kind: pypi name: pyyaml version: 6.0.2 - url: https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee + url: https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl + sha256: e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 requires_python: '>=3.8' - kind: pypi name: pyyaml version: 6.0.2 - url: https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 + url: https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c requires_python: '>=3.8' - kind: pypi name: pyyaml version: 6.0.2 - url: https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl - sha256: e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 + url: https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee requires_python: '>=3.8' - kind: pypi name: pyyaml version: 6.0.2 - url: https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c + url: https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 requires_python: '>=3.8' - kind: pypi name: pyyaml-env-tag @@ -34590,32 +34590,32 @@ packages: - kind: pypi name: pyzmq version: 26.2.0 - url: https://files.pythonhosted.org/packages/e1/bf/c67fd638c2f9fbbab8090a3ee779370b97c82b84cc12d0c498b285d7b2c0/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef + url: https://files.pythonhosted.org/packages/12/20/de7442172f77f7c96299a0ac70e7d4fb78cd51eca67aa2cf552b66c14196/pyzmq-26.2.0-cp311-cp311-macosx_10_15_universal2.whl + sha256: 8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218 requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.2.0 - url: https://files.pythonhosted.org/packages/12/20/de7442172f77f7c96299a0ac70e7d4fb78cd51eca67aa2cf552b66c14196/pyzmq-26.2.0-cp311-cp311-macosx_10_15_universal2.whl - sha256: 8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218 + url: https://files.pythonhosted.org/packages/3b/1b/0a540edd75a41df14ec416a9a500b9fec66e554aac920d4c58fbd5756776/pyzmq-26.2.0-cp311-cp311-win_amd64.whl + sha256: 5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5 requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.2.0 - url: https://files.pythonhosted.org/packages/ab/68/6fb6ae5551846ad5beca295b7bca32bf0a7ce19f135cb30e55fa2314e6b6/pyzmq-26.2.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e + url: https://files.pythonhosted.org/packages/e1/bf/c67fd638c2f9fbbab8090a3ee779370b97c82b84cc12d0c498b285d7b2c0/pyzmq-26.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.2.0 - url: https://files.pythonhosted.org/packages/3b/1b/0a540edd75a41df14ec416a9a500b9fec66e554aac920d4c58fbd5756776/pyzmq-26.2.0-cp311-cp311-win_amd64.whl - sha256: 5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5 + url: https://files.pythonhosted.org/packages/ab/68/6fb6ae5551846ad5beca295b7bca32bf0a7ce19f135cb30e55fa2314e6b6/pyzmq-26.2.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' @@ -34926,32 +34926,32 @@ packages: - kind: pypi name: regex version: 2024.9.11 - url: https://files.pythonhosted.org/packages/32/d9/bfdd153179867c275719e381e1e8e84a97bd186740456a0dcb3e7125c205/regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268 + url: https://files.pythonhosted.org/packages/e9/5c/8b385afbfacb853730682c57be56225f9fe275c5bf02ac1fc88edbff316d/regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50 requires_python: '>=3.8' - kind: pypi name: regex version: 2024.9.11 - url: https://files.pythonhosted.org/packages/33/c4/60f3370735135e3a8d673ddcdb2507a8560d0e759e1398d366e43d000253/regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl - sha256: 64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad + url: https://files.pythonhosted.org/packages/c7/ab/1ad2511cf6a208fde57fafe49829cab8ca018128ab0d0b48973d8218634a/regex-2024.9.11-cp311-cp311-win_amd64.whl + sha256: 313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf requires_python: '>=3.8' - kind: pypi name: regex version: 2024.9.11 - url: https://files.pythonhosted.org/packages/e9/5c/8b385afbfacb853730682c57be56225f9fe275c5bf02ac1fc88edbff316d/regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50 + url: https://files.pythonhosted.org/packages/b1/51/91a5ebdff17f9ec4973cb0aa9d37635efec1c6868654bbc25d1543aca4ec/regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679 requires_python: '>=3.8' - kind: pypi name: regex version: 2024.9.11 - url: https://files.pythonhosted.org/packages/c7/ab/1ad2511cf6a208fde57fafe49829cab8ca018128ab0d0b48973d8218634a/regex-2024.9.11-cp311-cp311-win_amd64.whl - sha256: 313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf + url: https://files.pythonhosted.org/packages/33/c4/60f3370735135e3a8d673ddcdb2507a8560d0e759e1398d366e43d000253/regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl + sha256: 64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad requires_python: '>=3.8' - kind: pypi name: regex version: 2024.9.11 - url: https://files.pythonhosted.org/packages/b1/51/91a5ebdff17f9ec4973cb0aa9d37635efec1c6868654bbc25d1543aca4ec/regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679 + url: https://files.pythonhosted.org/packages/32/d9/bfdd153179867c275719e381e1e8e84a97bd186740456a0dcb3e7125c205/regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268 requires_python: '>=3.8' - kind: pypi name: requests @@ -35006,8 +35006,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/30/5f/ce02381b9d7e1e14f60c421c76dce12b7d823690181784780b30266017b1/rerun_sdk-0.17.0-cp38-abi3-macosx_10_12_x86_64.whl - sha256: abd34f746eada83b8bb0bc50007183151981d7ccf18306f3d42165819a3f6fcb + url: https://files.pythonhosted.org/packages/d9/74/6c1ff0c8dbe6da09ceb5ea838a72382fa3131ef6bb9377a30003299743fa/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_x86_64.whl + sha256: 9d41f1f475270b1e0d50ddb8cb62e0d828988f0c371ac8457af25c8be5aa1dc0 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -35020,8 +35020,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/87/0a/b5fe1ffea700eeaa8d28817a92ad3cb4a7d56dc4af45de76ea412cfc5cd5/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_aarch64.whl - sha256: ad55807abafb01e527846742e087819aac8e103f1ec15aadc563a4038bb44e1d + url: https://files.pythonhosted.org/packages/b7/c5/d47ba7b774bc563aa3c07ba500dd304ea24b31fe438e10ea9ad5e10ffe17/rerun_sdk-0.17.0-cp38-abi3-macosx_11_0_arm64.whl + sha256: 8b0a8a6feab3f8e679801d158216a71d88a81480021587719330f50d083c4d26 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -35034,8 +35034,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/b7/c5/d47ba7b774bc563aa3c07ba500dd304ea24b31fe438e10ea9ad5e10ffe17/rerun_sdk-0.17.0-cp38-abi3-macosx_11_0_arm64.whl - sha256: 8b0a8a6feab3f8e679801d158216a71d88a81480021587719330f50d083c4d26 + url: https://files.pythonhosted.org/packages/30/5f/ce02381b9d7e1e14f60c421c76dce12b7d823690181784780b30266017b1/rerun_sdk-0.17.0-cp38-abi3-macosx_10_12_x86_64.whl + sha256: abd34f746eada83b8bb0bc50007183151981d7ccf18306f3d42165819a3f6fcb requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -35048,8 +35048,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/d9/74/6c1ff0c8dbe6da09ceb5ea838a72382fa3131ef6bb9377a30003299743fa/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_x86_64.whl - sha256: 9d41f1f475270b1e0d50ddb8cb62e0d828988f0c371ac8457af25c8be5aa1dc0 + url: https://files.pythonhosted.org/packages/87/0a/b5fe1ffea700eeaa8d28817a92ad3cb4a7d56dc4af45de76ea412cfc5cd5/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_aarch64.whl + sha256: ad55807abafb01e527846742e087819aac8e103f1ec15aadc563a4038bb44e1d requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -35063,7 +35063,7 @@ packages: name: rerun-sdk version: 0.20.0a1+dev path: rerun_py - sha256: eb5f7980a383fbf90ac89432b7a8b244b996ba65520ee25a53f541ecf243236b + sha256: 987ab780f77273923cbadafacc493abc008101bc123927c458b6d01e4af3b1b6 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -35175,32 +35175,32 @@ packages: - kind: pypi name: rpds-py version: 0.20.0 - url: https://files.pythonhosted.org/packages/ab/2a/191374c52d7be0b056cc2a04d718d2244c152f915d4a8d2db2aacc526189/rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl - sha256: ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489 + url: https://files.pythonhosted.org/packages/a7/e8/85835077b782555d6b3416874b702ea6ebd7db1f145283c9252968670dd5/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209 requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.20.0 - url: https://files.pythonhosted.org/packages/0e/6a/2c9fdcc6d235ac0d61ec4fd9981184689c3e682abd05e3caa49bccb9c298/rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318 + url: https://files.pythonhosted.org/packages/cc/ec/77d0674f9af4872919f3738018558dd9d37ad3f7ad792d062eadd4af7cba/rpds_py-0.20.0-cp311-none-win_amd64.whl + sha256: c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.20.0 - url: https://files.pythonhosted.org/packages/a7/e8/85835077b782555d6b3416874b702ea6ebd7db1f145283c9252968670dd5/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209 + url: https://files.pythonhosted.org/packages/d2/b2/725487d29633f64ef8f9cbf4729111a0b61702c8f8e94db1653930f52cce/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.20.0 - url: https://files.pythonhosted.org/packages/cc/ec/77d0674f9af4872919f3738018558dd9d37ad3f7ad792d062eadd4af7cba/rpds_py-0.20.0-cp311-none-win_amd64.whl - sha256: c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c + url: https://files.pythonhosted.org/packages/0e/6a/2c9fdcc6d235ac0d61ec4fd9981184689c3e682abd05e3caa49bccb9c298/rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318 requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.20.0 - url: https://files.pythonhosted.org/packages/d2/b2/725487d29633f64ef8f9cbf4729111a0b61702c8f8e94db1653930f52cce/rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db + url: https://files.pythonhosted.org/packages/ab/2a/191374c52d7be0b056cc2a04d718d2244c152f915d4a8d2db2aacc526189/rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl + sha256: ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489 requires_python: '>=3.8' - kind: pypi name: rrt-star @@ -35355,8 +35355,8 @@ packages: - kind: pypi name: safetensors version: 0.4.5 - url: https://files.pythonhosted.org/packages/39/83/c4a7ce01d626e46ea2b45887f2e59b16441408031e2ce2f9fe01860c6946/safetensors-0.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 09dedf7c2fda934ee68143202acff6e9e8eb0ddeeb4cfc24182bef999efa9f42 + url: https://files.pythonhosted.org/packages/9a/a5/25bcf75e373412daf1fd88045ab3aa8140a0d804ef0e70712c4f2c5b94d8/safetensors-0.4.5-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 21f848d7aebd5954f92538552d6d75f7c1b4500f51664078b5b49720d180e47c requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -35395,8 +35395,8 @@ packages: - kind: pypi name: safetensors version: 0.4.5 - url: https://files.pythonhosted.org/packages/9a/a5/25bcf75e373412daf1fd88045ab3aa8140a0d804ef0e70712c4f2c5b94d8/safetensors-0.4.5-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 21f848d7aebd5954f92538552d6d75f7c1b4500f51664078b5b49720d180e47c + url: https://files.pythonhosted.org/packages/6d/41/948c96c8a7e9fef57c2e051f1871c108a6dbbc6d285598bdb1d89b98617c/safetensors-0.4.5-cp311-none-win_amd64.whl + sha256: cbd39cae1ad3e3ef6f63a6f07296b080c951f24cec60188378e43d3713000c04 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -35435,8 +35435,8 @@ packages: - kind: pypi name: safetensors version: 0.4.5 - url: https://files.pythonhosted.org/packages/e6/ee/69e498a892f208bd1da4104d4b9be887f8611bf4942144718b6738482250/safetensors-0.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a6c19feda32b931cae0acd42748a670bdf56bee6476a046af20181ad3fee4090 + url: https://files.pythonhosted.org/packages/39/83/c4a7ce01d626e46ea2b45887f2e59b16441408031e2ce2f9fe01860c6946/safetensors-0.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 09dedf7c2fda934ee68143202acff6e9e8eb0ddeeb4cfc24182bef999efa9f42 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -35475,8 +35475,8 @@ packages: - kind: pypi name: safetensors version: 0.4.5 - url: https://files.pythonhosted.org/packages/6d/41/948c96c8a7e9fef57c2e051f1871c108a6dbbc6d285598bdb1d89b98617c/safetensors-0.4.5-cp311-none-win_amd64.whl - sha256: cbd39cae1ad3e3ef6f63a6f07296b080c951f24cec60188378e43d3713000c04 + url: https://files.pythonhosted.org/packages/e6/ee/69e498a892f208bd1da4104d4b9be887f8611bf4942144718b6738482250/safetensors-0.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a6c19feda32b931cae0acd42748a670bdf56bee6476a046af20181ad3fee4090 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -35555,8 +35555,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2 + url: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -35622,8 +35622,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831 + url: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl + sha256: dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -35689,8 +35689,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c + url: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -35756,8 +35756,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl - sha256: dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c + url: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -35890,8 +35890,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.2 - url: https://files.pythonhosted.org/packages/4c/75/62e49f8a62bf3c60b0e64d0fce540578ee4f0e752765beb2e1dc7c6d6098/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f763897fe92d0e903aa4847b0aec0e68cadfff77e8a0687cabd946c89d17e675 + url: https://files.pythonhosted.org/packages/ff/91/609961972f694cb9520c4c3d201e377a26583e1eb83bc5a334c893729214/scikit_learn-1.5.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 03b6158efa3faaf1feea3faa884c840ebd61b6484167c711548fce208ea09445 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -35952,8 +35952,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.2 - url: https://files.pythonhosted.org/packages/ff/91/609961972f694cb9520c4c3d201e377a26583e1eb83bc5a334c893729214/scikit_learn-1.5.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 03b6158efa3faaf1feea3faa884c840ebd61b6484167c711548fce208ea09445 + url: https://files.pythonhosted.org/packages/17/1c/ccdd103cfcc9435a18819856fbbe0c20b8fa60bfc3343580de4be13f0668/scikit_learn-1.5.2-cp311-cp311-win_amd64.whl + sha256: 6c16d84a0d45e4894832b3c4d0bf73050939e21b99b01b6fd59cbb0cf39163b6 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -36014,8 +36014,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.2 - url: https://files.pythonhosted.org/packages/49/21/3723de321531c9745e40f1badafd821e029d346155b6c79704e0b7197552/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: f8b0ccd4a902836493e026c03256e8b206656f91fbcc4fde28c57a5b752561f1 + url: https://files.pythonhosted.org/packages/4c/75/62e49f8a62bf3c60b0e64d0fce540578ee4f0e752765beb2e1dc7c6d6098/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f763897fe92d0e903aa4847b0aec0e68cadfff77e8a0687cabd946c89d17e675 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -36076,8 +36076,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.2 - url: https://files.pythonhosted.org/packages/17/1c/ccdd103cfcc9435a18819856fbbe0c20b8fa60bfc3343580de4be13f0668/scikit_learn-1.5.2-cp311-cp311-win_amd64.whl - sha256: 6c16d84a0d45e4894832b3c4d0bf73050939e21b99b01b6fd59cbb0cf39163b6 + url: https://files.pythonhosted.org/packages/49/21/3723de321531c9745e40f1badafd821e029d346155b6c79704e0b7197552/scikit_learn-1.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: f8b0ccd4a902836493e026c03256e8b206656f91fbcc4fde28c57a5b752561f1 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -36200,8 +36200,8 @@ packages: - kind: pypi name: scipy version: 1.14.1 - url: https://files.pythonhosted.org/packages/c2/4b/b44bee3c2ddc316b0159b3d87a3d467ef8d7edfd525e6f7364a62cd87d90/scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37 + url: https://files.pythonhosted.org/packages/b2/ab/070ccfabe870d9f105b04aee1e2860520460ef7ca0213172abfe871463b9/scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl + sha256: 2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -36242,8 +36242,8 @@ packages: - kind: pypi name: scipy version: 1.14.1 - url: https://files.pythonhosted.org/packages/b2/ab/070ccfabe870d9f105b04aee1e2860520460ef7ca0213172abfe871463b9/scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl - sha256: 2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675 + url: https://files.pythonhosted.org/packages/ea/c2/5ecadc5fcccefaece775feadcd795060adf5c3b29a883bff0e678cfe89af/scipy-1.14.1-cp311-cp311-win_amd64.whl + sha256: 716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -36284,8 +36284,8 @@ packages: - kind: pypi name: scipy version: 1.14.1 - url: https://files.pythonhosted.org/packages/93/6b/701776d4bd6bdd9b629c387b5140f006185bd8ddea16788a44434376b98f/scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2 + url: https://files.pythonhosted.org/packages/c2/4b/b44bee3c2ddc316b0159b3d87a3d467ef8d7edfd525e6f7364a62cd87d90/scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -36326,8 +36326,8 @@ packages: - kind: pypi name: scipy version: 1.14.1 - url: https://files.pythonhosted.org/packages/ea/c2/5ecadc5fcccefaece775feadcd795060adf5c3b29a883bff0e678cfe89af/scipy-1.14.1-cp311-cp311-win_amd64.whl - sha256: 716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94 + url: https://files.pythonhosted.org/packages/93/6b/701776d4bd6bdd9b629c387b5140f006185bd8ddea16788a44434376b98f/scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -36554,8 +36554,8 @@ packages: - kind: pypi name: shapely version: 2.0.6 - url: https://files.pythonhosted.org/packages/6e/5a/d019f69449329dcd517355444fdb9ddd58bec5e080b8bdba007e8e4c546d/shapely-2.0.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f32c23d2f43d54029f986479f7c1f6e09c6b3a19353a3833c2ffb226fb63a855 + url: https://files.pythonhosted.org/packages/37/15/269d8e1f7f658a37e61f7028683c546f520e4e7cedba1e32c77ff9d3a3c7/shapely-2.0.6-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5aeb0f51a9db176da9a30cb2f4329b6fbd1e26d359012bb0ac3d3c7781667a9e requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -36569,8 +36569,8 @@ packages: - kind: pypi name: shapely version: 2.0.6 - url: https://files.pythonhosted.org/packages/37/15/269d8e1f7f658a37e61f7028683c546f520e4e7cedba1e32c77ff9d3a3c7/shapely-2.0.6-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5aeb0f51a9db176da9a30cb2f4329b6fbd1e26d359012bb0ac3d3c7781667a9e + url: https://files.pythonhosted.org/packages/b1/5a/6a67d929c467a1973b6bb9f0b00159cc343b02bf9a8d26db1abd2f87aa23/shapely-2.0.6-cp311-cp311-win_amd64.whl + sha256: c02eb6bf4cfb9fe6568502e85bb2647921ee49171bcd2d4116c7b3109724ef9b requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -36584,8 +36584,8 @@ packages: - kind: pypi name: shapely version: 2.0.6 - url: https://files.pythonhosted.org/packages/25/aa/53f145e5a610a49af9ac49f2f1be1ec8659ebd5c393d66ac94e57c83b00e/shapely-2.0.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b3dc9fb0eb56498912025f5eb352b5126f04801ed0e8bdbd867d21bdbfd7cbd0 + url: https://files.pythonhosted.org/packages/6e/5a/d019f69449329dcd517355444fdb9ddd58bec5e080b8bdba007e8e4c546d/shapely-2.0.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f32c23d2f43d54029f986479f7c1f6e09c6b3a19353a3833c2ffb226fb63a855 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -36599,8 +36599,8 @@ packages: - kind: pypi name: shapely version: 2.0.6 - url: https://files.pythonhosted.org/packages/b1/5a/6a67d929c467a1973b6bb9f0b00159cc343b02bf9a8d26db1abd2f87aa23/shapely-2.0.6-cp311-cp311-win_amd64.whl - sha256: c02eb6bf4cfb9fe6568502e85bb2647921ee49171bcd2d4116c7b3109724ef9b + url: https://files.pythonhosted.org/packages/25/aa/53f145e5a610a49af9ac49f2f1be1ec8659ebd5c393d66ac94e57c83b00e/shapely-2.0.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b3dc9fb0eb56498912025f5eb352b5126f04801ed0e8bdbd867d21bdbfd7cbd0 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -36686,26 +36686,26 @@ packages: - kind: pypi name: simplejson version: 3.19.3 - url: https://files.pythonhosted.org/packages/ab/4d/15718f20cb0e3875b8af9597d6bb3bfbcf1383834b82b6385ee9ac0b72a9/simplejson-3.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 5d9e8f836688a8fabe6a6b41b334aa550a6823f7b4ac3d3712fc0ad8655be9a8 + url: https://files.pythonhosted.org/packages/ac/ae/a06523928af3a6783e2638cd4f6035c3e32de1c1063d563d9060c8d2f1ad/simplejson-3.19.3-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 934a50a614fb831614db5dbfba35127ee277624dda4d15895c957d2f5d48610c requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson version: 3.19.3 - url: https://files.pythonhosted.org/packages/ac/ae/a06523928af3a6783e2638cd4f6035c3e32de1c1063d563d9060c8d2f1ad/simplejson-3.19.3-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 934a50a614fb831614db5dbfba35127ee277624dda4d15895c957d2f5d48610c + url: https://files.pythonhosted.org/packages/65/be/d8ab9717f471be3c114f16abd8be21d9a6a0a09b9b49177d93d64d3717d9/simplejson-3.19.3-cp311-cp311-win_amd64.whl + sha256: c9bedebdc5fdad48af8783022bae307746d54006b783007d1d3c38e10872a2c6 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson version: 3.19.3 - url: https://files.pythonhosted.org/packages/b7/d4/850948bcbcfe0b4a6c69dfde10e245d3a1ea45252f16a1e2308a3b06b1da/simplejson-3.19.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: c4f614581b61a26fbbba232a1391f6cee82bc26f2abbb6a0b44a9bba25c56a1c + url: https://files.pythonhosted.org/packages/ab/4d/15718f20cb0e3875b8af9597d6bb3bfbcf1383834b82b6385ee9ac0b72a9/simplejson-3.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 5d9e8f836688a8fabe6a6b41b334aa550a6823f7b4ac3d3712fc0ad8655be9a8 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson version: 3.19.3 - url: https://files.pythonhosted.org/packages/65/be/d8ab9717f471be3c114f16abd8be21d9a6a0a09b9b49177d93d64d3717d9/simplejson-3.19.3-cp311-cp311-win_amd64.whl - sha256: c9bedebdc5fdad48af8783022bae307746d54006b783007d1d3c38e10872a2c6 + url: https://files.pythonhosted.org/packages/b7/d4/850948bcbcfe0b4a6c69dfde10e245d3a1ea45252f16a1e2308a3b06b1da/simplejson-3.19.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: c4f614581b61a26fbbba232a1391f6cee82bc26f2abbb6a0b44a9bba25c56a1c requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson @@ -36835,8 +36835,8 @@ packages: - kind: pypi name: sounddevice version: 0.5.1 - url: https://files.pythonhosted.org/packages/06/d1/464b5fca3decdd0cfec8c47f7b4161a0b12972453201c1bf03811f367c5e/sounddevice-0.5.1-py3-none-any.whl - sha256: e2017f182888c3f3c280d9fbac92e5dbddac024a7e3442f6e6116bd79dab8a9c + url: https://files.pythonhosted.org/packages/af/9b/15217b04f3b36d30de55fef542389d722de63f1ad81f9c72d8afc98cb6ab/sounddevice-0.5.1-py3-none-win_amd64.whl + sha256: 4313b63f2076552b23ac3e0abd3bcfc0c1c6a696fc356759a13bd113c9df90f1 requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -36844,8 +36844,8 @@ packages: - kind: pypi name: sounddevice version: 0.5.1 - url: https://files.pythonhosted.org/packages/af/9b/15217b04f3b36d30de55fef542389d722de63f1ad81f9c72d8afc98cb6ab/sounddevice-0.5.1-py3-none-win_amd64.whl - sha256: 4313b63f2076552b23ac3e0abd3bcfc0c1c6a696fc356759a13bd113c9df90f1 + url: https://files.pythonhosted.org/packages/06/d1/464b5fca3decdd0cfec8c47f7b4161a0b12972453201c1bf03811f367c5e/sounddevice-0.5.1-py3-none-any.whl + sha256: e2017f182888c3f3c280d9fbac92e5dbddac024a7e3442f6e6116bd79dab8a9c requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -37414,8 +37414,8 @@ packages: - kind: pypi name: tokenizers version: 0.20.1 - url: https://files.pythonhosted.org/packages/2d/ca/f3a294ed89f2a1b900fba072ef4cb5331d4f156e2d5ea2d34f60160ef5bd/tokenizers-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 929c8f3afa16a5130a81ab5079c589226273ec618949cce79b46d96e59a84f61 + url: https://files.pythonhosted.org/packages/61/9a/be5f00cd37ad4fab0e5d1dbf31404a66ac2c1c33973beda9fc8e248a37ab/tokenizers-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 4a717dcb08f2dabbf27ae4b6b20cbbb2ad7ed78ce05a829fae100ff4b3c7ff15 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -37432,8 +37432,8 @@ packages: - kind: pypi name: tokenizers version: 0.20.1 - url: https://files.pythonhosted.org/packages/61/9a/be5f00cd37ad4fab0e5d1dbf31404a66ac2c1c33973beda9fc8e248a37ab/tokenizers-0.20.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 4a717dcb08f2dabbf27ae4b6b20cbbb2ad7ed78ce05a829fae100ff4b3c7ff15 + url: https://files.pythonhosted.org/packages/f1/95/f1b56f4b1fbd54bd7f170aa64258d0650500e9f45de217ffe4d4663809b6/tokenizers-0.20.1-cp311-none-win_amd64.whl + sha256: 899152a78b095559c287b4c6d0099469573bb2055347bb8154db106651296f39 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -37450,8 +37450,8 @@ packages: - kind: pypi name: tokenizers version: 0.20.1 - url: https://files.pythonhosted.org/packages/09/6c/1b573998fe3f0e18ac5d434e43966de2d225d6837f099ce0df7df4274c87/tokenizers-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: ef3f1ae08fa9aea5891cbd69df29913e11d3841798e0bfb1ff78b78e4e7ea0a4 + url: https://files.pythonhosted.org/packages/2d/ca/f3a294ed89f2a1b900fba072ef4cb5331d4f156e2d5ea2d34f60160ef5bd/tokenizers-0.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 929c8f3afa16a5130a81ab5079c589226273ec618949cce79b46d96e59a84f61 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -37468,8 +37468,8 @@ packages: - kind: pypi name: tokenizers version: 0.20.1 - url: https://files.pythonhosted.org/packages/f1/95/f1b56f4b1fbd54bd7f170aa64258d0650500e9f45de217ffe4d4663809b6/tokenizers-0.20.1-cp311-none-win_amd64.whl - sha256: 899152a78b095559c287b4c6d0099469573bb2055347bb8154db106651296f39 + url: https://files.pythonhosted.org/packages/09/6c/1b573998fe3f0e18ac5d434e43966de2d225d6837f099ce0df7df4274c87/tokenizers-0.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: ef3f1ae08fa9aea5891cbd69df29913e11d3841798e0bfb1ff78b78e4e7ea0a4 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -37544,8 +37544,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/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 @@ -37571,8 +37571,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/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - typing-extensions>=4.8.0 @@ -37598,8 +37598,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 @@ -37679,8 +37679,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/56/8d/a153903bfd610450258ee7ac5d292d6b8f382aec14f49404845d8ba6207d/torchvision-0.17.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 833fd2e4216ced924c8aca0525733fe727f9a1af66dfad7c5be7257e97c39678 + 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 @@ -37690,8 +37690,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/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl + sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - torch==2.2.2 @@ -37701,8 +37701,8 @@ packages: - 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/56/8d/a153903bfd610450258ee7ac5d292d6b8f382aec14f49404845d8ba6207d/torchvision-0.17.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 833fd2e4216ced924c8aca0525733fe727f9a1af66dfad7c5be7257e97c39678 requires_dist: - numpy - torch==2.2.2 @@ -37712,8 +37712,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/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl + sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 requires_dist: - numpy - torch==2.2.2 @@ -37734,26 +37734,26 @@ packages: - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 + url: https://files.pythonhosted.org/packages/2e/0f/721e113a2fac2f1d7d124b3279a1da4c77622e104084f56119875019ffab/tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl + sha256: 6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/2e/0f/721e113a2fac2f1d7d124b3279a1da4c77622e104084f56119875019ffab/tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl - sha256: 6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14 + url: https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl + sha256: b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/22/d4/54f9d12668b58336bd30defe0307e6c61589a3e687b05c366f804b7faaf0/tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3 + url: https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl - sha256: b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 + url: https://files.pythonhosted.org/packages/22/d4/54f9d12668b58336bd30defe0307e6c61589a3e687b05c366f804b7faaf0/tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3 requires_python: '>=3.8' - kind: pypi name: tornado @@ -38547,6 +38547,12 @@ packages: url: https://files.pythonhosted.org/packages/d1/8d/10a5a3391225d3284cf4a9bcd3b7db3f769c8378e2e3c53d2a1034f280b6/uv-0.4.23-py3-none-manylinux_2_28_aarch64.whl sha256: cbb9754f18d0796337a1756e628f0faa74c215ffb139a35bf490ab07fa626ca8 requires_python: '>=3.8' +- kind: pypi + name: uv + version: 0.4.23 + url: https://files.pythonhosted.org/packages/a9/f1/3c473a2ff3fd8e09e0a2777c6f665133b68c65ea4378e15d0b4d70204496/uv-0.4.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 23269724349a1831881319e5f2854a5b8260f444ecb2528ac44ffe039a091ac4 + requires_python: '>=3.8' - kind: pypi name: uv version: 0.4.23 @@ -38565,12 +38571,6 @@ packages: url: https://files.pythonhosted.org/packages/9e/83/e821ccb4b10f12ea7278ee245e483818d53e0202ac3d074cc73934b7dbfc/uv-0.4.23-py3-none-macosx_10_12_x86_64.whl sha256: 1663219972c92cdd2a24ab0437284c4fcaac483814e3399e1cafa231c47b0c46 requires_python: '>=3.8' -- kind: pypi - name: uv - version: 0.4.23 - url: https://files.pythonhosted.org/packages/a9/f1/3c473a2ff3fd8e09e0a2777c6f665133b68c65ea4378e15d0b4d70204496/uv-0.4.23-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 23269724349a1831881319e5f2854a5b8260f444ecb2528ac44ffe039a091ac4 - requires_python: '>=3.8' - kind: conda name: vc version: '14.3' @@ -38700,40 +38700,40 @@ packages: - kind: pypi name: watchdog version: 5.0.3 - url: https://files.pythonhosted.org/packages/96/2b/b84e35d49e8b0bad77e5d086fc1e2c6c833bbfe74d53144cfe8b26117eff/watchdog-5.0.3-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 91b522adc25614cdeaf91f7897800b82c13b4b8ac68a42ca959f992f6990c490 + url: https://files.pythonhosted.org/packages/a0/58/edec25190b6403caf4426dd418234f2358a106634b7d6aa4aec6939b104f/watchdog-5.0.3-py3-none-manylinux2014_x86_64.whl + sha256: 0f9332243355643d567697c3e3fa07330a1d1abf981611654a1f2bf2175612b7 requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' - kind: pypi name: watchdog version: 5.0.3 - url: https://files.pythonhosted.org/packages/d5/3f/41b5d77c10f450b79921c17b7d0b416616048867bfe63acaa072a619a0cb/watchdog-5.0.3-cp311-cp311-macosx_11_0_arm64.whl - sha256: d52db5beb5e476e6853da2e2d24dbbbed6797b449c8bf7ea118a4ee0d2c9040e + url: https://files.pythonhosted.org/packages/91/b4/2b5b59358dadfa2c8676322f955b6c22cde4937602f40490e2f7403e548e/watchdog-5.0.3-py3-none-win_amd64.whl + sha256: f00b4cf737f568be9665563347a910f8bdc76f88c2970121c86243c8cfdf90e9 requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' - kind: pypi name: watchdog version: 5.0.3 - url: https://files.pythonhosted.org/packages/a0/58/edec25190b6403caf4426dd418234f2358a106634b7d6aa4aec6939b104f/watchdog-5.0.3-py3-none-manylinux2014_x86_64.whl - sha256: 0f9332243355643d567697c3e3fa07330a1d1abf981611654a1f2bf2175612b7 + url: https://files.pythonhosted.org/packages/60/33/7cb71c9df9a77b6927ee5f48d25e1de5562ce0fa7e0c56dcf2b0472e64a2/watchdog-5.0.3-py3-none-manylinux2014_aarch64.whl + sha256: dd021efa85970bd4824acacbb922066159d0f9e546389a4743d56919b6758b91 requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' - kind: pypi name: watchdog version: 5.0.3 - url: https://files.pythonhosted.org/packages/91/b4/2b5b59358dadfa2c8676322f955b6c22cde4937602f40490e2f7403e548e/watchdog-5.0.3-py3-none-win_amd64.whl - sha256: f00b4cf737f568be9665563347a910f8bdc76f88c2970121c86243c8cfdf90e9 + url: https://files.pythonhosted.org/packages/d5/3f/41b5d77c10f450b79921c17b7d0b416616048867bfe63acaa072a619a0cb/watchdog-5.0.3-cp311-cp311-macosx_11_0_arm64.whl + sha256: d52db5beb5e476e6853da2e2d24dbbbed6797b449c8bf7ea118a4ee0d2c9040e requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' - kind: pypi name: watchdog version: 5.0.3 - url: https://files.pythonhosted.org/packages/60/33/7cb71c9df9a77b6927ee5f48d25e1de5562ce0fa7e0c56dcf2b0472e64a2/watchdog-5.0.3-py3-none-manylinux2014_aarch64.whl - sha256: dd021efa85970bd4824acacbb922066159d0f9e546389a4743d56919b6758b91 + url: https://files.pythonhosted.org/packages/96/2b/b84e35d49e8b0bad77e5d086fc1e2c6c833bbfe74d53144cfe8b26117eff/watchdog-5.0.3-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 91b522adc25614cdeaf91f7897800b82c13b4b8ac68a42ca959f992f6990c490 requires_dist: - pyyaml>=3.10 ; extra == 'watchmedo' requires_python: '>=3.9' @@ -38840,6 +38840,12 @@ packages: 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 + requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 @@ -38858,12 +38864,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/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: x264 version: 1!164.3095 @@ -39958,8 +39958,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/be/a2/4272175d47c623ff78196f3c10e9dc7045c1b9caf3735bf041e65271eca4/zstandard-0.23.0-cp311-cp311-win_amd64.whl - sha256: 62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 + url: https://files.pythonhosted.org/packages/76/3f/dbafccf19cfeca25bbabf6f2dd81796b7218f768ec400f043edc767015a6/zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -39967,8 +39967,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/e8/46/66d5b55f4d737dd6ab75851b224abf0afe5774976fe511a54d2eb9063a41/zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 + url: https://files.pythonhosted.org/packages/be/a2/4272175d47c623ff78196f3c10e9dc7045c1b9caf3735bf041e65271eca4/zstandard-0.23.0-cp311-cp311-win_amd64.whl + sha256: 62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -39976,8 +39976,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/9e/40/f67e7d2c25a0e2dc1744dd781110b0b60306657f8696cafb7ad7579469bd/zstandard-0.23.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e + url: https://files.pythonhosted.org/packages/e8/46/66d5b55f4d737dd6ab75851b224abf0afe5774976fe511a54d2eb9063a41/zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -39985,8 +39985,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/76/3f/dbafccf19cfeca25bbabf6f2dd81796b7218f768ec400f043edc767015a6/zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca + url: https://files.pythonhosted.org/packages/9e/40/f67e7d2c25a0e2dc1744dd781110b0b60306657f8696cafb7ad7579469bd/zstandard-0.23.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index ed653856b52a..a8988fe6375c 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -70,6 +70,8 @@ extend-exclude = [ "docs/snippets/all/tutorials/timelines_example.py", # Intentionally incomplete snippets + "docs/snippets/all/tutorials/custom-application-id.py", + "docs/snippets/all/tutorials/custom-recording-id.py", "docs/snippets/all/concepts/static", # generated diff --git a/scripts/lint.py b/scripts/lint.py index 678f34d8ff0e..9af481f499c3 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -1204,7 +1204,11 @@ def main() -> None: "./CODE_STYLE.md", "./crates/build/re_types_builder/src/reflection.rs", # auto-generated "./crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs", # auto-generated + "./docs/content/concepts/app-model.md", # this really needs custom letter casing "./docs/content/reference/cli.md", # auto-generated + "./docs/snippets/all/tutorials/custom-application-id.cpp", # nuh-uh, I don't want rerun_example_ here + "./docs/snippets/all/tutorials/custom-application-id.py", # nuh-uh, I don't want rerun_example_ here + "./docs/snippets/all/tutorials/custom-application-id.rs", # nuh-uh, I don't want rerun_example_ here "./examples/assets", "./examples/python/detect_and_track_objects/cache/version.txt", "./examples/python/objectron/objectron/proto/", # auto-generated From 05b41fab5c4abd559be6d0c856fd94a841a0f300 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:51:25 +0200 Subject: [PATCH 6/8] naming --- crates/store/re_remote_store_types/src/codec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/store/re_remote_store_types/src/codec.rs b/crates/store/re_remote_store_types/src/codec.rs index b8cf09fdb37e..fedb885b0c5f 100644 --- a/crates/store/re_remote_store_types/src/codec.rs +++ b/crates/store/re_remote_store_types/src/codec.rs @@ -196,7 +196,7 @@ impl RecordingMetadata { } } - /// Get arrow data from `RecordingMetadata` + /// Get metadata as arrow data pub fn data(&self) -> Result<(ArrowSchema, ArrowChunk>), CodecError> { let mut reader = std::io::Cursor::new(self.payload.clone()); From 30775e187a90a1760b1c1f0c28da007c0430367d Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Mon, 28 Oct 2024 08:23:32 +0100 Subject: [PATCH 7/8] lint fix --- crates/store/re_remote_store_types/src/codec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/store/re_remote_store_types/src/codec.rs b/crates/store/re_remote_store_types/src/codec.rs index fedb885b0c5f..87343e65b230 100644 --- a/crates/store/re_remote_store_types/src/codec.rs +++ b/crates/store/re_remote_store_types/src/codec.rs @@ -326,7 +326,7 @@ mod tests { arrow2::datatypes::DataType::Int32, false, )]); - let my_ints = Int32Array::from_slice(&[42]); + let my_ints = Int32Array::from_slice([42]); let expected_chunk = ArrowChunk::new(vec![Box::new(my_ints) as _]); let metadata = From c16b2ff0c1e6e1a41a872cddb515acd35623135a Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Mon, 28 Oct 2024 09:18:09 +0100 Subject: [PATCH 8/8] common code for arrow serialization + unit test coverage --- .../store/re_remote_store_types/src/codec.rs | 131 ++++++++++-------- 1 file changed, 76 insertions(+), 55 deletions(-) diff --git a/crates/store/re_remote_store_types/src/codec.rs b/crates/store/re_remote_store_types/src/codec.rs index 87343e65b230..184126b10e17 100644 --- a/crates/store/re_remote_store_types/src/codec.rs +++ b/crates/store/re_remote_store_types/src/codec.rs @@ -79,14 +79,7 @@ impl TransportMessageV0 { let mut data: Vec = Vec::new(); MessageHader::RECORD_BATCH.encode(&mut data)?; - let options = write::WriteOptions { compression: None }; - let mut sw = write::StreamWriter::new(&mut data, options); - - sw.start(&chunk.schema, None) - .map_err(CodecError::ArrowSerialization)?; - sw.write(&chunk.data, None) - .map_err(CodecError::ArrowSerialization)?; - sw.finish().map_err(CodecError::ArrowSerialization)?; + write_arrow_to_bytes(&mut data, &chunk.schema, &chunk.data)?; Ok(data) } @@ -100,29 +93,14 @@ impl TransportMessageV0 { match header { MessageHader::NO_DATA => Ok(Self::NoData), MessageHader::RECORD_BATCH => { - let metadata = read::read_stream_metadata(&mut reader) - .map_err(CodecError::ArrowSerialization)?; - let mut stream = read::StreamReader::new(&mut reader, metadata, None); - - let schema = stream.schema().clone(); - // there should be at least one record batch in the stream - // TODO(zehiko) isn't there a "read one record batch from bytes" arrow2 function?? - let stream_state = stream - .next() - .ok_or(CodecError::MissingRecordBatch)? - .map_err(CodecError::ArrowSerialization)?; - - match stream_state { - read::StreamState::Waiting => Err(CodecError::UnexpectedStreamState), - read::StreamState::Some(chunk) => { - let tc = TransportChunk { - schema: schema.clone(), - data: chunk, - }; - - Ok(Self::RecordBatch(tc)) - } - } + let (schema, data) = read_arrow_from_bytes(&mut reader)?; + + let tc = TransportChunk { + schema: schema.clone(), + data, + }; + + Ok(Self::RecordBatch(tc)) } _ => Err(CodecError::UnknownMessageHeader), } @@ -160,7 +138,6 @@ pub fn decode(version: EncoderVersion, data: &[u8]) -> Result { let mut data: Vec = Vec::new(); - - let options = write::WriteOptions { compression: None }; - let mut sw = write::StreamWriter::new(&mut data, options); - - sw.start(schema, None) - .map_err(CodecError::ArrowSerialization)?; - sw.write(unit_batch, None) - .map_err(CodecError::ArrowSerialization)?; - sw.finish().map_err(CodecError::ArrowSerialization)?; + write_arrow_to_bytes(&mut data, schema, unit_batch)?; Ok(Self { encoder_version: version as i32, @@ -200,24 +169,55 @@ impl RecordingMetadata { pub fn data(&self) -> Result<(ArrowSchema, ArrowChunk>), CodecError> { let mut reader = std::io::Cursor::new(self.payload.clone()); - let metadata = - read::read_stream_metadata(&mut reader).map_err(CodecError::ArrowSerialization)?; - let mut stream = read::StreamReader::new(&mut reader, metadata, None); - - let schema = stream.schema().clone(); - // there should be at least one record batch in the stream - let stream_state = stream - .next() - .ok_or(CodecError::MissingRecordBatch)? - .map_err(CodecError::ArrowSerialization)?; - - match stream_state { - read::StreamState::Waiting => Err(CodecError::UnexpectedStreamState), - read::StreamState::Some(chunk) => Ok((schema, chunk)), + let encoder_version = EncoderVersion::try_from(self.encoder_version) + .map_err(|err| CodecError::InvalidArgument(err.to_string()))?; + + match encoder_version { + EncoderVersion::V0 => read_arrow_from_bytes(&mut reader), } } } +/// Helper function that serializes given arrow schema and record batch into bytes +/// using Arrow IPC format. +fn write_arrow_to_bytes( + writer: &mut W, + schema: &ArrowSchema, + data: &ArrowChunk>, +) -> Result<(), CodecError> { + let options = write::WriteOptions { compression: None }; + let mut sw = write::StreamWriter::new(writer, options); + + sw.start(schema, None) + .map_err(CodecError::ArrowSerialization)?; + sw.write(data, None) + .map_err(CodecError::ArrowSerialization)?; + sw.finish().map_err(CodecError::ArrowSerialization)?; + + Ok(()) +} + +/// Helper function that deserializes raw bytes into arrow schema and record batch +/// using Arrow IPC format. +fn read_arrow_from_bytes( + reader: &mut R, +) -> Result<(ArrowSchema, ArrowChunk>), CodecError> { + let metadata = read::read_stream_metadata(reader).map_err(CodecError::ArrowSerialization)?; + let mut stream = read::StreamReader::new(reader, metadata, None); + + let schema = stream.schema().clone(); + // there should be at least one record batch in the stream + let stream_state = stream + .next() + .ok_or(CodecError::MissingRecordBatch)? + .map_err(CodecError::ArrowSerialization)?; + + match stream_state { + read::StreamState::Waiting => Err(CodecError::UnexpectedStreamState), + read::StreamState::Some(chunk) => Ok((schema, chunk)), + } +} + #[cfg(test)] mod tests { @@ -338,4 +338,25 @@ mod tests { assert_eq!(expected_schema, schema); assert_eq!(expected_chunk, chunk); } + + #[test] + fn test_recording_metadata_fails_with_non_unit_batch() { + let expected_schema = ArrowSchema::from(vec![Field::new( + "my_int", + arrow2::datatypes::DataType::Int32, + false, + )]); + // more than 1 row in the batch + let my_ints = Int32Array::from_slice([41, 42]); + + let expected_chunk = ArrowChunk::new(vec![Box::new(my_ints) as _]); + + let metadata = + RecordingMetadata::try_from(EncoderVersion::V0, &expected_schema, &expected_chunk); + + assert!(matches!( + metadata.err().unwrap(), + CodecError::InvalidArgument(_) + )); + } }