diff --git a/examples/python/api_demo/main.py b/examples/python/api_demo/main.py index 5d56efb63879..d42e9a86d4ea 100755 --- a/examples/python/api_demo/main.py +++ b/examples/python/api_demo/main.py @@ -8,6 +8,7 @@ * Run all demos: `examples/python/api_demo/main.py` * Run specific demo: `examples/python/api_demo/main.py --demo rects` """ +from __future__ import annotations import argparse import logging diff --git a/examples/python/arkitscenes/download_dataset.py b/examples/python/arkitscenes/download_dataset.py index cc2e59d2cc5d..fd1c8944ceed 100644 --- a/examples/python/arkitscenes/download_dataset.py +++ b/examples/python/arkitscenes/download_dataset.py @@ -1,11 +1,13 @@ # Copied from https://github.com/apple/ARKitScenes/blob/main/download_data.py # Licensing information: https://github.com/apple/ARKitScenes/blob/main/LICENSE +from __future__ import annotations + import math import os import subprocess import zipfile from pathlib import Path -from typing import Final, List, Optional +from typing import Final import pandas as pd @@ -62,7 +64,7 @@ ] -def raw_files(video_id: str, assets: List[str], metadata: pd.DataFrame) -> List[str]: +def raw_files(video_id: str, assets: list[str], metadata: pd.DataFrame) -> list[str]: file_names = [] for asset in assets: if HIGRES_DEPTH_ASSET_NAME == asset: @@ -153,7 +155,7 @@ def download_laser_scanner_point_clouds_for_video(video_id: str, metadata: pd.Da download_laser_scanner_point_clouds(point_cloud_id, visit_id, download_dir) -def laser_scanner_point_clouds_for_visit_id(visit_id: int, download_dir: Path) -> List[str]: +def laser_scanner_point_clouds_for_visit_id(visit_id: int, download_dir: Path) -> list[str]: point_cloud_to_visit_id_mapping_filename = "laser_scanner_point_clouds_mapping.csv" if not os.path.exists(point_cloud_to_visit_id_mapping_filename): point_cloud_to_visit_id_mapping_url = ( @@ -209,11 +211,11 @@ def get_metadata(dataset: str, download_dir: Path) -> pd.DataFrame: def download_data( dataset: str, - video_ids: List[str], - dataset_splits: List[str], + video_ids: list[str], + dataset_splits: list[str], download_dir: Path, keep_zip: bool, - raw_dataset_assets: Optional[List[str]] = None, + raw_dataset_assets: list[str] | None = None, should_download_laser_scanner_point_cloud: bool = False, ) -> None: """ @@ -307,15 +309,20 @@ def ensure_recording_available(video_id: str, include_highres: bool) -> Path: Returns the path to the recording for a given video_id. Args: - video_id (str): Identifier for the recording. + ---- + video_id (str): + Identifier for the recording. + include_highres (bool): + Whether to include the high resolution recording. Returns ------- - Path: Path object representing the path to the recording. + Path: Path object representing the path to the recording. Raises ------ - AssertionError: If the recording path does not exist. + AssertionError: + If the recording path does not exist. """ recording_path = ensure_recording_downloaded(video_id, include_highres) assert recording_path.exists(), f"Recording path {recording_path} does not exist." diff --git a/examples/python/arkitscenes/main.py b/examples/python/arkitscenes/main.py index 96537f0b5952..d84ee47d1a07 100755 --- a/examples/python/arkitscenes/main.py +++ b/examples/python/arkitscenes/main.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 +from __future__ import annotations + import argparse import json import os from pathlib import Path, PosixPath -from typing import Any, Dict, List, Tuple +from typing import Any, Tuple import cv2 import matplotlib.pyplot as plt @@ -30,13 +32,13 @@ assert set(ORIENTATION.keys()) == set(AVAILABLE_RECORDINGS) -def load_json(js_path: Path) -> Dict[str, Any]: - with open(js_path, "r") as f: - json_data = json.load(f) # type: Dict[str, Any] +def load_json(js_path: Path) -> dict[str, Any]: + with open(js_path) as f: + json_data: dict[str, Any] = json.load(f) return json_data -def log_annotated_bboxes(annotation: Dict[str, Any]) -> Tuple[npt.NDArray[np.float64], List[str], List[Color]]: +def log_annotated_bboxes(annotation: dict[str, Any]) -> tuple[npt.NDArray[np.float64], list[str], list[Color]]: """ Logs annotated oriented bounding boxes to Rerun. @@ -229,11 +231,11 @@ def project_3d_bboxes_to_2d_keypoints( def log_camera( intri_path: Path, frame_id: str, - poses_from_traj: Dict[str, rr.TranslationRotationScale3D], + poses_from_traj: dict[str, rr.TranslationRotationScale3D], entity_id: str, bboxes: npt.NDArray[np.float64], - bbox_labels: List[str], - colors: List[Color], + bbox_labels: list[str], + colors: list[Color], ) -> None: """Logs camera transform and 3D bounding boxes in the image frame.""" w, h, fx, fy, cx, cy = np.loadtxt(intri_path) @@ -256,12 +258,14 @@ def log_camera( rr.log_pinhole(f"{entity_id}", child_from_parent=intrinsic, width=w, height=h) -def read_camera_from_world(traj_string: str) -> Tuple[str, rr.TranslationRotationScale3D]: +def read_camera_from_world(traj_string: str) -> tuple[str, rr.TranslationRotationScale3D]: """ Reads out camera_from_world transform from trajectory string. Args: - traj_string: A space-delimited file where each line represents a camera position at a particular timestamp. + ---- + traj_string: + A space-delimited file where each line represents a camera position at a particular timestamp. The file has seven columns: * Column 1: timestamp * Columns 2-4: rotation (axis-angle representation in radians) @@ -276,7 +280,8 @@ def read_camera_from_world(traj_string: str) -> Tuple[str, rr.TranslationRotatio Raises ------ - AssertionError: If the input string does not contain 7 tokens. + AssertionError: + If the input string does not contain 7 tokens. """ tokens = traj_string.split() # Split the input string into tokens assert len(tokens) == 7, f"Input string must have 7 tokens, but found {len(tokens)}." @@ -295,7 +300,7 @@ def read_camera_from_world(traj_string: str) -> Tuple[str, rr.TranslationRotatio return (ts, camera_from_world) -def find_closest_frame_id(target_id: str, frame_ids: Dict[str, Any]) -> str: +def find_closest_frame_id(target_id: str, frame_ids: dict[str, Any]) -> str: """Finds the closest frame id to the target id.""" target_value = float(target_id) closest_id = min(frame_ids.keys(), key=lambda x: abs(float(x) - target_value)) @@ -307,11 +312,16 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: Logs ARKit recording data using Rerun. Args: - recording_path (Path): The path to the ARKit recording. + ---- + recording_path (Path): + The path to the ARKit recording. + + include_highres (bool): + Whether to include high resolution data. Returns ------- - None + None """ video_id = recording_path.stem lowres_image_dir = recording_path / "lowres_wide" @@ -330,7 +340,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: # dict of timestamp to pose which is a tuple of translation and quaternion camera_from_world_dict = {} - with open(traj_path, "r", encoding="utf-8") as f: + with open(traj_path, encoding="utf-8") as f: trajectory = f.readlines() for line in trajectory: diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index 2893fb7a171a..84cbed10cc9a 100644 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -1,4 +1,5 @@ """Example of using the blueprint APIs to configure Rerun.""" +from __future__ import annotations import argparse diff --git a/examples/python/car/main.py b/examples/python/car/main.py index 0059790f3a4a..f2363baf9598 100755 --- a/examples/python/car/main.py +++ b/examples/python/car/main.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 """Shows how to use the Rerun SDK.""" +from __future__ import annotations import argparse from dataclasses import dataclass -from typing import Iterator, Tuple +from typing import Iterator import cv2 import numpy as np @@ -57,8 +58,8 @@ class DummyCar: def __init__( self, - center: Tuple[int, int], - size: Tuple[int, int], + center: tuple[int, int], + size: tuple[int, int], distance_mm: float, ): self.center: npt.NDArray[np.int32] = np.array(center, dtype=np.int32) @@ -157,7 +158,7 @@ class SampleFrame: camera: CameraParameters depth_image_mm: npt.NDArray[np.float32] rgb_image: npt.NDArray[np.float32] - car_bbox: Tuple[npt.NDArray[np.int32], npt.NDArray[np.int32]] + car_bbox: tuple[npt.NDArray[np.int32], npt.NDArray[np.int32]] class SimpleDepthCamera: diff --git a/examples/python/clock/main.py b/examples/python/clock/main.py index 4466bf9daca1..87e26fc46f86 100755 --- a/examples/python/clock/main.py +++ b/examples/python/clock/main.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 - """ An example showing usage of `log_arrow`. An analog clock is built with Rerun Arrow3D primitives. """ +from __future__ import annotations import argparse import math -from typing import Final, Tuple +from typing import Final import numpy as np import rerun as rr # pip install rerun-sdk @@ -23,7 +23,7 @@ def log_clock(steps: int) -> None: - def rotate(angle: float, len: float) -> Tuple[float, float, float]: + def rotate(angle: float, len: float) -> tuple[float, float, float]: return ( len * math.sin(angle), len * math.cos(angle), diff --git a/examples/python/colmap/main.py b/examples/python/colmap/main.py index 13b9490cdd84..16abb911a897 100755 --- a/examples/python/colmap/main.py +++ b/examples/python/colmap/main.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 """Example of using Rerun to log and visualize the output of COLMAP's sparse reconstruction.""" +from __future__ import annotations + import io import os import re import zipfile from argparse import ArgumentParser from pathlib import Path -from typing import Any, Final, Optional, Tuple +from typing import Any, Final import cv2 import numpy as np @@ -22,7 +24,7 @@ FILTER_MIN_VISIBLE: Final = 500 -def scale_camera(camera: Camera, resize: Tuple[int, int]) -> Tuple[Camera, npt.NDArray[np.float_]]: +def scale_camera(camera: Camera, resize: tuple[int, int]) -> tuple[Camera, npt.NDArray[np.float_]]: """Scale the camera intrinsics to match the resized image.""" assert camera.model == "PINHOLE" new_width = resize[0] @@ -88,9 +90,7 @@ def download_with_progress(url: str) -> io.BytesIO: return zip_file -def read_and_log_sparse_reconstruction( - dataset_path: Path, filter_output: bool, resize: Optional[Tuple[int, int]] -) -> None: +def read_and_log_sparse_reconstruction(dataset_path: Path, filter_output: bool, resize: tuple[int, int] | None) -> None: print("Reading sparse COLMAP reconstruction") cameras, images, points3D = read_model(dataset_path / "sparse", ext=".bin") print("Building visualization by logging to Rerun") diff --git a/examples/python/colmap/read_write_model.py b/examples/python/colmap/read_write_model.py index dd2043803d12..9598cdaeb188 100644 --- a/examples/python/colmap/read_write_model.py +++ b/examples/python/colmap/read_write_model.py @@ -1,6 +1,5 @@ # This file is adapted from # https://github.com/colmap/colmap/blob/bf3e19140f491c3042bfd85b7192ef7d249808ec/scripts/python/read_write_model.py - # Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. # All rights reserved. # @@ -31,8 +30,8 @@ # POSSIBILITY OF SUCH DAMAGE. # # Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de) - # type: ignore +from __future__ import annotations import argparse import collections @@ -110,7 +109,7 @@ def read_cameras_text(path: Path): void Reconstruction::ReadCamerasText(const std::string& path) """ cameras = {} - with open(path, "r") as fid: + with open(path) as fid: while True: line = fid.readline() if not line: @@ -161,7 +160,7 @@ def write_cameras_text(cameras, path): HEADER = ( "# Camera list with one line of data per camera:\n" + "# CAMERA_ID, MODEL, WIDTH, HEIGHT, PARAMS[]\n" - + "# Number of cameras: {}\n".format(len(cameras)) + + f"# Number of cameras: {len(cameras)}\n" ) with open(path, "w") as fid: fid.write(HEADER) @@ -195,7 +194,7 @@ def read_images_text(path: Path): void Reconstruction::WriteImagesText(const std::string& path) """ images = {} - with open(path, "r") as fid: + with open(path) as fid: while True: line = fid.readline() if not line: @@ -273,7 +272,7 @@ def write_images_text(images, path): "# Image list with two lines of data per image:\n" + "# IMAGE_ID, QW, QX, QY, QZ, TX, TY, TZ, CAMERA_ID, NAME\n" + "# POINTS2D[] as (X, Y, POINT3D_ID)\n" - + "# Number of images: {}, mean observations per image: {}\n".format(len(images), mean_observations) + + f"# Number of images: {len(images)}, mean observations per image: {mean_observations}\n" ) with open(path, "w") as fid: @@ -317,7 +316,7 @@ def read_points3D_text(path): void Reconstruction::WritePoints3DText(const std::string& path) """ points3D = {} - with open(path, "r") as fid: + with open(path) as fid: while True: line = fid.readline() if not line: @@ -375,7 +374,7 @@ def write_points3D_text(points3D, path): HEADER = ( "# 3D point list with one line of data per point:\n" + "# POINT3D_ID, X, Y, Z, R, G, B, ERROR, TRACK[] as (IMAGE_ID, POINT2D_IDX)\n" - + "# Number of points: {}, mean track length: {}\n".format(len(points3D), mean_track_length) + + f"# Number of points: {len(points3D)}, mean track length: {mean_track_length}\n" ) with open(path, "w") as fid: diff --git a/examples/python/deep_sdf/download_dataset.py b/examples/python/deep_sdf/download_dataset.py index 7d3c8b08d431..5d50b811d86f 100755 --- a/examples/python/deep_sdf/download_dataset.py +++ b/examples/python/deep_sdf/download_dataset.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 +from __future__ import annotations import io import os import zipfile from pathlib import Path -from typing import Final, Optional +from typing import Final import requests @@ -49,7 +50,7 @@ def download_mesh(name: str) -> Path: raise RuntimeError(f"Unknown mesh named: {name}") -def find_mesh_path_if_downloaded(name: str) -> Optional[Path]: +def find_mesh_path_if_downloaded(name: str) -> Path | None: for mesh_format in ("obj", "glb"): for path in DOWNLOADED_DIR.glob(f"{name}/**/*.{mesh_format}"): return path diff --git a/examples/python/deep_sdf/main.py b/examples/python/deep_sdf/main.py index 12dd7d90978e..b0833370abd5 100755 --- a/examples/python/deep_sdf/main.py +++ b/examples/python/deep_sdf/main.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - """ Generate SDFs for arbitrary meshes and visualize the results using the Rerun SDK. @@ -26,13 +25,13 @@ examples/python/deep_sdf/main.py ``` """ - +from __future__ import annotations import argparse import os from pathlib import Path from timeit import default_timer as timer -from typing import Tuple, cast +from typing import cast import mesh_to_sdf import numpy as np @@ -88,7 +87,7 @@ def compute_voxel_sdf(mesh: Trimesh, resolution: int) -> npt.NDArray[np.float32] @log_timing_decorator("global/sample_sdf", rr.LogLevel.DEBUG) # type: ignore[misc] -def compute_sample_sdf(mesh: Trimesh, num_points: int) -> Tuple[npt.NDArray[np.float32], npt.NDArray[np.float32]]: +def compute_sample_sdf(mesh: Trimesh, num_points: int) -> tuple[npt.NDArray[np.float32], npt.NDArray[np.float32]]: print("computing sample-based SDF") points, sdf, _ = mesh_to_sdf.sample_sdf_near_surface(mesh, number_of_points=num_points, return_gradients=True) return (points, sdf) diff --git a/examples/python/dicom/main.py b/examples/python/dicom/main.py index f1693008820f..4ffbbb97fd45 100755 --- a/examples/python/dicom/main.py +++ b/examples/python/dicom/main.py @@ -7,13 +7,14 @@ python3 examples/python/dicom/main.py ``` """ +from __future__ import annotations import argparse import io import os import zipfile from pathlib import Path -from typing import Final, Iterable, Tuple +from typing import Final, Iterable import dicom_numpy import numpy as np @@ -28,7 +29,7 @@ def extract_voxel_data( dicom_files: Iterable[Path], -) -> Tuple[npt.NDArray[np.int16], npt.NDArray[np.float32]]: +) -> tuple[npt.NDArray[np.int16], npt.NDArray[np.float32]]: slices = [dicom.read_file(f) for f in dicom_files] # type: ignore[misc] try: voxel_ndarray, ijk_to_xyz = dicom_numpy.combine_slices(slices) diff --git a/examples/python/dna/main.py b/examples/python/dna/main.py index 63a295e7bfba..717e21fa0884 100755 --- a/examples/python/dna/main.py +++ b/examples/python/dna/main.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 - """ The example from our Getting Started page. `examples/python/dna/main.py` """ +from __future__ import annotations from math import tau diff --git a/examples/python/minimal/main.py b/examples/python/minimal/main.py index 44bcf6e465c5..174b212f7c3b 100755 --- a/examples/python/minimal/main.py +++ b/examples/python/minimal/main.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 - """Demonstrates the most barebone usage of the Rerun SDK.""" - +from __future__ import annotations import numpy as np import rerun as rr # pip install rerun-sdk diff --git a/examples/python/minimal_options/main.py b/examples/python/minimal_options/main.py index ad93c0c4b4c1..dd11d830fdaa 100755 --- a/examples/python/minimal_options/main.py +++ b/examples/python/minimal_options/main.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 - """Demonstrates the most barebone usage of the Rerun SDK, with standard options.""" - +from __future__ import annotations import argparse diff --git a/examples/python/mp_pose/main.py b/examples/python/mp_pose/main.py index d91ecdba0420..04789620a25e 100755 --- a/examples/python/mp_pose/main.py +++ b/examples/python/mp_pose/main.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 """Use the MediaPipe Pose solution to detect and track a human pose in video.""" +from __future__ import annotations + import argparse import logging import os from contextlib import closing from dataclasses import dataclass from pathlib import Path -from typing import Any, Final, Iterator, Optional +from typing import Any, Final, Iterator import cv2 as cv import mediapipe as mp @@ -62,7 +64,7 @@ def read_landmark_positions_2d( results: Any, image_width: int, image_height: int, -) -> Optional[npt.NDArray[np.float32]]: +) -> npt.NDArray[np.float32] | None: if results.pose_landmarks is None: return None else: @@ -72,7 +74,7 @@ def read_landmark_positions_2d( def read_landmark_positions_3d( results: Any, -) -> Optional[npt.NDArray[np.float32]]: +) -> npt.NDArray[np.float32] | None: if results.pose_landmarks is None: return None else: diff --git a/examples/python/multiprocessing/main.py b/examples/python/multiprocessing/main.py index e43cbd6b008a..0b5bd1c17fcc 100755 --- a/examples/python/multiprocessing/main.py +++ b/examples/python/multiprocessing/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 - """Shows how rerun can work with multiprocessing.""" +from __future__ import annotations import argparse import multiprocessing diff --git a/examples/python/multithreading/main.py b/examples/python/multithreading/main.py index d0c8973876fb..40eb2c596907 100755 --- a/examples/python/multithreading/main.py +++ b/examples/python/multithreading/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 - """Demonstration of using rerun from multiple threads.""" +from __future__ import annotations import argparse import random @@ -29,9 +29,7 @@ def main() -> None: threads = [] for i in range(10): - t = threading.Thread( - target=rect_logger, args=("thread/{}".format(i), [random.randrange(255) for _ in range(3)]) - ) + t = threading.Thread(target=rect_logger, args=(f"thread/{i}", [random.randrange(255) for _ in range(3)])) t.start() threads.append(t) diff --git a/examples/python/nyud/main.py b/examples/python/nyud/main.py index cb5bbe9b7a1c..7ab6059029c9 100755 --- a/examples/python/nyud/main.py +++ b/examples/python/nyud/main.py @@ -4,13 +4,14 @@ https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html """ +from __future__ import annotations import argparse import os import zipfile from datetime import datetime from pathlib import Path -from typing import Final, Tuple +from typing import Final import cv2 import numpy as np @@ -32,7 +33,7 @@ def parse_timestamp(filename: str) -> datetime: return datetime.fromtimestamp(float(time)) -def camera_for_image(h: float, w: float) -> Tuple[float, float, float]: +def camera_for_image(h: float, w: float) -> tuple[float, float, float]: """Returns a tuple of (u_center, v_center, focal_length) for a camera image.""" return (w / 2, h / 2, 0.7 * w) diff --git a/examples/python/objectron/download_dataset.py b/examples/python/objectron/download_dataset.py index df67a129bf87..9059f92a524c 100644 --- a/examples/python/objectron/download_dataset.py +++ b/examples/python/objectron/download_dataset.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import logging import os from pathlib import Path -from typing import Final, Optional +from typing import Final import cv2 import requests @@ -37,7 +39,7 @@ def ensure_downloaded(src_url: str, dst_path: Path) -> None: f.write(chunk) -def find_path_if_downloaded(recording_name: str, local_dataset_dir: Path) -> Optional[Path]: +def find_path_if_downloaded(recording_name: str, local_dataset_dir: Path) -> Path | None: local_recording_dir = local_dataset_dir / recording_name paths = list(local_recording_dir.glob(f"**/{ANNOTATIONS_FILENAME}")) if paths: diff --git a/examples/python/objectron/main.py b/examples/python/objectron/main.py index cca79c67da92..4cd971870167 100755 --- a/examples/python/objectron/main.py +++ b/examples/python/objectron/main.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 - """ Example of using the Rerun SDK to log the Objectron dataset. Example: `examples/python/objectron/main.py --recording chair` """ +from __future__ import annotations import argparse import logging @@ -14,7 +14,7 @@ import time from dataclasses import dataclass from pathlib import Path -from typing import Iterable, Iterator, List +from typing import Iterable, Iterator import numpy as np import numpy.typing as npt @@ -27,15 +27,7 @@ LOCAL_DATASET_DIR, ensure_recording_available, ) -from proto.objectron.proto import ( - ARCamera, - ARFrame, - ARPointCloud, - FrameAnnotation, - Object, - ObjectType, - Sequence, -) +from proto.objectron.proto import ARCamera, ARFrame, ARPointCloud, FrameAnnotation, Object, ObjectType, Sequence from scipy.spatial.transform import Rotation as R @@ -192,7 +184,7 @@ def log_annotated_bboxes(bboxes: Iterable[Object]) -> None: ) -def log_frame_annotations(frame_times: List[float], frame_annotations: List[FrameAnnotation]) -> None: +def log_frame_annotations(frame_times: list[float], frame_annotations: list[FrameAnnotation]) -> None: """Maps annotations to their associated `ARFrame` then logs them using the Rerun SDK.""" for frame_ann in frame_annotations: diff --git a/examples/python/objectron/proto/objectron/proto.py b/examples/python/objectron/proto/objectron/proto.py index 114acf7f7b01..8dbe6f56d38d 100644 --- a/examples/python/objectron/proto/objectron/proto.py +++ b/examples/python/objectron/proto/objectron/proto.py @@ -1,6 +1,8 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # sources: a_r_capture_metadata.proto, object.proto, annotation_data.proto # plugin: python-betterproto +from __future__ import annotations + from dataclasses import dataclass from typing import List @@ -97,7 +99,7 @@ class AVCameraCalibrationData(betterproto.Message): # 3x3 row-major matrix relating a camera's internal properties to an ideal # pinhole-camera model. - intrinsic_matrix: List[float] = betterproto.float_field(1) + intrinsic_matrix: list[float] = betterproto.float_field(1) # The image dimensions to which the intrinsic_matrix values are relative. intrinsic_matrix_reference_dimension_width: float = betterproto.float_field(2) intrinsic_matrix_reference_dimension_height: float = betterproto.float_field(3) @@ -107,15 +109,15 @@ class AVCameraCalibrationData(betterproto.Message): # translation vector's units are millimeters. For example: |r1,1 # r2,1 r3,1 | t1| [R | t] = |r1,2 r2,2 r3,2 | t2| |r1,3 r2,3 # r3,3 | t3| is stored as [r11, r21, r31, t1, r12, r22, r32, t2, ...] - extrinsic_matrix: List[float] = betterproto.float_field(4) + extrinsic_matrix: list[float] = betterproto.float_field(4) # The size, in millimeters, of one image pixel. pixel_size: float = betterproto.float_field(5) # A list of floating-point values describing radial distortions imparted by # the camera lens, for use in rectifying camera images. - lens_distortion_lookup_values: List[float] = betterproto.float_field(6) + lens_distortion_lookup_values: list[float] = betterproto.float_field(6) # A list of floating-point values describing radial distortions for use in # reapplying camera geometry to a rectified image. - inverse_lens_distortion_lookup_values: List[float] = betterproto.float_field(7) + inverse_lens_distortion_lookup_values: list[float] = betterproto.float_field(7) # The offset of the distortion center of the camera lens from the top-left # corner of the image. lens_distortion_center_x: float = betterproto.float_field(8) @@ -132,12 +134,12 @@ class AVDepthData(betterproto.Message): depth_data_map: bytes = betterproto.bytes_field(1) # Pixel format type of the original captured depth data. depth_data_type: str = betterproto.string_field(2) - depth_data_accuracy: "AVDepthDataAccuracy" = betterproto.enum_field(3) + depth_data_accuracy: AVDepthDataAccuracy = betterproto.enum_field(3) # Indicates whether the depth_data_map contains temporally smoothed data. depth_data_filtered: bool = betterproto.bool_field(4) - depth_data_quality: "AVDepthDataQuality" = betterproto.enum_field(5) + depth_data_quality: AVDepthDataQuality = betterproto.enum_field(5) # Associated calibration data for the depth_data_map. - camera_calibration_data: "AVCameraCalibrationData" = betterproto.message_field(6) + camera_calibration_data: AVCameraCalibrationData = betterproto.message_field(6) # The original range of values expressed by the depth_data_map, before # grayscale normalization. For example, if the minimum and maximum values # indicate a range of [0.5, 2.2], and the depth_data_type value indicates it @@ -173,10 +175,10 @@ class ARLightEstimate(betterproto.Message): # Second-level spherical harmonics in separate red, green, and blue data # planes. Thus, this buffer contains 3 sets of 9 coefficients, or a total of # 27 values. - spherical_harmonics_coefficients: List[float] = betterproto.float_field(3) + spherical_harmonics_coefficients: list[float] = betterproto.float_field(3) # A vector indicating the orientation of the strongest directional light # source, normalized in the world-coordinate space. - primary_light_direction: "ARLightEstimateDirectionVector" = betterproto.message_field(4) + primary_light_direction: ARLightEstimateDirectionVector = betterproto.message_field(4) # The estimated intensity, in lumens, of the strongest directional light # source in the scene. primary_light_intensity: float = betterproto.float_field(5) @@ -196,25 +198,25 @@ class ARCamera(betterproto.Message): captured video frame. """ - tracking_state: "ARCameraTrackingState" = betterproto.enum_field(1) - tracking_state_reason: "ARCameraTrackingStateReason" = betterproto.enum_field(2) + tracking_state: ARCameraTrackingState = betterproto.enum_field(1) + tracking_state_reason: ARCameraTrackingStateReason = betterproto.enum_field(2) # 4x4 row-major matrix expressing position and orientation of the camera in # world coordinate space. - transform: List[float] = betterproto.float_field(3) - euler_angles: "ARCameraEulerAngles" = betterproto.message_field(4) + transform: list[float] = betterproto.float_field(3) + euler_angles: ARCameraEulerAngles = betterproto.message_field(4) # The width and height, in pixels, of the captured camera image. image_resolution_width: int = betterproto.int32_field(5) image_resolution_height: int = betterproto.int32_field(6) # 3x3 row-major matrix that converts between the 2D camera plane and 3D world # coordinate space. - intrinsics: List[float] = betterproto.float_field(7) + intrinsics: list[float] = betterproto.float_field(7) # 4x4 row-major transform matrix appropriate for rendering 3D content to # match the image captured by the camera. - projection_matrix: List[float] = betterproto.float_field(8) + projection_matrix: list[float] = betterproto.float_field(8) # 4x4 row-major transform matrix appropriate for converting from world-space # to camera space. Relativized for the captured_image orientation (i.e. # UILandscapeOrientationRight). - view_matrix: List[float] = betterproto.float_field(9) + view_matrix: list[float] = betterproto.float_field(9) @dataclass @@ -232,10 +234,10 @@ class ARCameraEulerAngles(betterproto.Message): class ARFaceGeometry(betterproto.Message): """Container for a 3D mesh describing face topology.""" - vertices: List["ARFaceGeometryVertex"] = betterproto.message_field(1) + vertices: list[ARFaceGeometryVertex] = betterproto.message_field(1) # The number of elements in the vertices list. vertex_count: int = betterproto.int32_field(2) - texture_coordinates: List["ARFaceGeometryTextureCoordinate"] = betterproto.message_field(3) + texture_coordinates: list[ARFaceGeometryTextureCoordinate] = betterproto.message_field(3) # The number of elements in the texture_coordinates list. texture_coordinate_count: int = betterproto.int32_field(4) # Each integer value in this ordered list represents an index into the @@ -243,7 +245,7 @@ class ARFaceGeometry(betterproto.Message): # identifies the vertices comprising a single triangle in the mesh. Each set # of three indices forms a triangle, so the number of indices in the # triangle_indices buffer is three times the triangle_count value. - triangle_indices: List[int] = betterproto.int32_field(5) + triangle_indices: list[int] = betterproto.int32_field(5) # The number of triangles described by the triangle_indices buffer. triangle_count: int = betterproto.int32_field(6) @@ -278,7 +280,7 @@ class ARBlendShapeMap(betterproto.Message): blend shape location to its associated coefficient. """ - entries: List["ARBlendShapeMapMapEntry"] = betterproto.message_field(1) + entries: list[ARBlendShapeMapMapEntry] = betterproto.message_field(1) @dataclass @@ -297,13 +299,13 @@ class ARFaceAnchor(betterproto.Message): """ # A coarse triangle mesh representing the topology of the detected face. - geometry: "ARFaceGeometry" = betterproto.message_field(1) + geometry: ARFaceGeometry = betterproto.message_field(1) # A map of named coefficients representing the detected facial expression in # terms of the movement of specific facial features. - blend_shapes: "ARBlendShapeMap" = betterproto.message_field(2) + blend_shapes: ARBlendShapeMap = betterproto.message_field(2) # 4x4 row-major matrix encoding the position, orientation, and scale of the # anchor relative to the world coordinate space. - transform: List[float] = betterproto.float_field(3) + transform: list[float] = betterproto.float_field(3) # Indicates whether the anchor's transform is valid. Frames that have a face # anchor with this value set to NO should probably be ignored. is_tracked: bool = betterproto.bool_field(4) @@ -314,11 +316,11 @@ class ARPlaneGeometry(betterproto.Message): """Container for a 3D mesh.""" # A buffer of vertex positions for each point in the plane mesh. - vertices: List["ARPlaneGeometryVertex"] = betterproto.message_field(1) + vertices: list[ARPlaneGeometryVertex] = betterproto.message_field(1) # The number of elements in the vertices buffer. vertex_count: int = betterproto.int32_field(2) # A buffer of texture coordinate values for each point in the plane mesh. - texture_coordinates: List["ARPlaneGeometryTextureCoordinate"] = betterproto.message_field(3) + texture_coordinates: list[ARPlaneGeometryTextureCoordinate] = betterproto.message_field(3) # The number of elements in the texture_coordinates buffer. texture_coordinate_count: int = betterproto.int32_field(4) # Each integer value in this ordered list represents an index into the @@ -326,14 +328,14 @@ class ARPlaneGeometry(betterproto.Message): # identifies the vertices comprising a single triangle in the mesh. Each set # of three indices forms a triangle, so the number of indices in the # triangle_indices buffer is three times the triangle_count value. - triangle_indices: List[int] = betterproto.int32_field(5) + triangle_indices: list[int] = betterproto.int32_field(5) # Each set of three indices forms a triangle, so the number of indices in the # triangle_indices buffer is three times the triangle_count value. triangle_count: int = betterproto.int32_field(6) # Each value in this buffer represents the position of a vertex along the # boundary polygon of the estimated plane. The owning plane anchor's # transform matrix defines the coordinate system for these points. - boundary_vertices: List["ARPlaneGeometryVertex"] = betterproto.message_field(7) + boundary_vertices: list[ARPlaneGeometryVertex] = betterproto.message_field(7) # The number of elements in the boundary_vertices buffer. boundary_vertex_count: int = betterproto.int32_field(8) @@ -367,20 +369,20 @@ class ARPlaneAnchor(betterproto.Message): identifier: str = betterproto.string_field(1) # 4x4 row-major matrix encoding the position, orientation, and scale of the # anchor relative to the world coordinate space. - transform: List[float] = betterproto.float_field(2) + transform: list[float] = betterproto.float_field(2) # The general orientation of the detected plane with respect to gravity. - alignment: "ARPlaneAnchorAlignment" = betterproto.enum_field(3) + alignment: ARPlaneAnchorAlignment = betterproto.enum_field(3) # A coarse triangle mesh representing the general shape of the detected # plane. - geometry: "ARPlaneGeometry" = betterproto.message_field(4) + geometry: ARPlaneGeometry = betterproto.message_field(4) # The center point of the plane relative to its anchor position. Although the # type of this property is a 3D vector, a plane anchor is always two- # dimensional, and is always positioned in only the x and z directions # relative to its transform position. (That is, the y-component of this # vector is always zero.) - center: "ARPlaneAnchorPlaneVector" = betterproto.message_field(5) + center: ARPlaneAnchorPlaneVector = betterproto.message_field(5) # The estimated width and length of the detected plane. - extent: "ARPlaneAnchorPlaneVector" = betterproto.message_field(6) + extent: ARPlaneAnchorPlaneVector = betterproto.message_field(6) # A Boolean value that indicates whether plane classification is available on # the current device. On devices without plane classification support, all # plane anchors report a classification value of NONE and a @@ -388,12 +390,12 @@ class ARPlaneAnchor(betterproto.Message): classification_supported: bool = betterproto.bool_field(7) # A general characterization of what kind of real-world surface the plane # anchor represents. - classification: "ARPlaneAnchorPlaneClassification" = betterproto.enum_field(8) + classification: ARPlaneAnchorPlaneClassification = betterproto.enum_field(8) # The current state of process for classifying the plane anchor. When this # property's value is KNOWN, the classification property represents # characterization of the real-world surface corresponding to the plane # anchor. - classification_status: "ARPlaneAnchorPlaneClassificationStatus" = betterproto.enum_field(9) + classification_status: ARPlaneAnchorPlaneClassificationStatus = betterproto.enum_field(9) @dataclass @@ -415,11 +417,11 @@ class ARPointCloud(betterproto.Message): # The number of points in the cloud. count: int = betterproto.int32_field(1) # The list of detected points. - point: List["ARPointCloudPoint"] = betterproto.message_field(2) + point: list[ARPointCloudPoint] = betterproto.message_field(2) # A list of unique identifiers corresponding to detected feature points. Each # identifier in this list corresponds to the point at the same index in the # points array. - identifier: List[int] = betterproto.int64_field(3) + identifier: list[int] = betterproto.int64_field(3) @dataclass @@ -445,9 +447,9 @@ class CMCalibratedMagneticField(betterproto.Message): """ # Vector of magnetic field estimate. - field: "CMVector" = betterproto.message_field(1) + field: CMVector = betterproto.message_field(1) # Calibration accuracy of a magnetic field estimate. - calibration_accuracy: "CMCalibratedMagneticFieldCalibrationAccuracy" = betterproto.enum_field(2) + calibration_accuracy: CMCalibratedMagneticFieldCalibrationAccuracy = betterproto.enum_field(2) @dataclass @@ -465,16 +467,16 @@ class CMDeviceMotion(betterproto.Message): timestamp: float = betterproto.double_field(1) # The quaternion representing the device’s orientation relative to a known # frame of reference at a point in time. - attitude_quaternion: "CMDeviceMotionQuaternion" = betterproto.message_field(2) + attitude_quaternion: CMDeviceMotionQuaternion = betterproto.message_field(2) # The gravity acceleration vector expressed in the device's reference frame. - gravity: "CMVector" = betterproto.message_field(3) + gravity: CMVector = betterproto.message_field(3) # The acceleration that the user is giving to the device. - user_acceleration: "CMVector" = betterproto.message_field(4) + user_acceleration: CMVector = betterproto.message_field(4) # Returns the magnetic field vector filtered with respect to the device bias. - magnetic_field: "CMCalibratedMagneticField" = betterproto.message_field(5) + magnetic_field: CMCalibratedMagneticField = betterproto.message_field(5) # The rotation rate of the device adjusted by bias-removing Core Motion # algorithms. - rotation_rate: "CMVector" = betterproto.message_field(6) + rotation_rate: CMVector = betterproto.message_field(6) @dataclass @@ -494,7 +496,7 @@ class CMAccelerometerData(betterproto.Message): timestamp: float = betterproto.double_field(1) # Raw acceleration measured by the accelerometer which effectively is a sum # of gravity and user_acceleration of CMDeviceMotion object. - acceleration: "CMVector" = betterproto.message_field(2) + acceleration: CMVector = betterproto.message_field(2) @dataclass @@ -505,7 +507,7 @@ class CMGyroData(betterproto.Message): # value since the data may be collected at higher rate. timestamp: float = betterproto.double_field(1) # Raw rotation rate as measured by the gyroscope. - rotation_rate: "CMVector" = betterproto.message_field(2) + rotation_rate: CMVector = betterproto.message_field(2) @dataclass @@ -516,7 +518,7 @@ class CMMagnetometerData(betterproto.Message): # value since the data may be collected at higher rate. timestamp: float = betterproto.double_field(1) # Raw magnetic field measured by the magnetometer. - magnetic_field: "CMVector" = betterproto.message_field(2) + magnetic_field: CMVector = betterproto.message_field(2) @dataclass @@ -524,13 +526,13 @@ class CMMotionManagerSnapshot(betterproto.Message): """Contains most recent snapshots of device motion data""" # Most recent samples of device motion data. - device_motion: List["CMDeviceMotion"] = betterproto.message_field(1) + device_motion: list[CMDeviceMotion] = betterproto.message_field(1) # Most recent samples of raw accelerometer data. - accelerometer_data: List["CMAccelerometerData"] = betterproto.message_field(2) + accelerometer_data: list[CMAccelerometerData] = betterproto.message_field(2) # Most recent samples of raw gyroscope data. - gyro_data: List["CMGyroData"] = betterproto.message_field(3) + gyro_data: list[CMGyroData] = betterproto.message_field(3) # Most recent samples of raw magnetometer data. - magnetometer_data: List["CMMagnetometerData"] = betterproto.message_field(4) + magnetometer_data: list[CMMagnetometerData] = betterproto.message_field(4) @dataclass @@ -540,29 +542,29 @@ class ARFrame(betterproto.Message): # The timestamp for the frame. timestamp: float = betterproto.double_field(1) # The depth data associated with the frame. Not all frames have depth data. - depth_data: "AVDepthData" = betterproto.message_field(2) + depth_data: AVDepthData = betterproto.message_field(2) # The depth data object timestamp associated with the frame. May differ from # the frame timestamp value. Is only set when the frame has depth_data. depth_data_timestamp: float = betterproto.double_field(3) # Camera information associated with the frame. - camera: "ARCamera" = betterproto.message_field(4) + camera: ARCamera = betterproto.message_field(4) # Light information associated with the frame. - light_estimate: "ARLightEstimate" = betterproto.message_field(5) + light_estimate: ARLightEstimate = betterproto.message_field(5) # Face anchor information associated with the frame. Not all frames have an # active face anchor. - face_anchor: "ARFaceAnchor" = betterproto.message_field(6) + face_anchor: ARFaceAnchor = betterproto.message_field(6) # Plane anchors associated with the frame. Not all frames have a plane # anchor. Plane anchors and face anchors are mutually exclusive. - plane_anchor: List["ARPlaneAnchor"] = betterproto.message_field(7) + plane_anchor: list[ARPlaneAnchor] = betterproto.message_field(7) # The current intermediate results of the scene analysis used to perform # world tracking. - raw_feature_points: "ARPointCloud" = betterproto.message_field(8) + raw_feature_points: ARPointCloud = betterproto.message_field(8) # Snapshot of Core Motion CMMotionManager object containing most recent # motion data associated with the frame. Since motion data capture rates can # be higher than rates of AR capture, the entities of this object reflect all # of the aggregated events which have occurred since the last ARFrame was # recorded. - motion_manager_snapshot: "CMMotionManagerSnapshot" = betterproto.message_field(9) + motion_manager_snapshot: CMMotionManagerSnapshot = betterproto.message_field(9) @dataclass @@ -570,16 +572,16 @@ class ARMeshGeometry(betterproto.Message): """Mesh geometry data stored in an array-based format.""" # The vertices of the mesh. - vertices: List["ARMeshGeometryVertex"] = betterproto.message_field(1) + vertices: list[ARMeshGeometryVertex] = betterproto.message_field(1) # The faces of the mesh. - faces: List["ARMeshGeometryFace"] = betterproto.message_field(2) + faces: list[ARMeshGeometryFace] = betterproto.message_field(2) # Rays that define which direction is outside for each face. Normals contain # 'rays that define which direction is outside for each face', in practice # the normals count is always identical to vertices count which looks like # vertices normals and not faces normals. - normals: List["ARMeshGeometryVertex"] = betterproto.message_field(3) + normals: list[ARMeshGeometryVertex] = betterproto.message_field(3) # Classification for each face in the mesh. - classification: List["ARMeshGeometryMeshClassification"] = betterproto.enum_field(4) + classification: list[ARMeshGeometryMeshClassification] = betterproto.enum_field(4) @dataclass @@ -593,7 +595,7 @@ class ARMeshGeometryVertex(betterproto.Message): class ARMeshGeometryFace(betterproto.Message): # / Indices of vertices defining the face from correspondent array of parent/ # message. A typical face is triangular. - vertex_indices: List[int] = betterproto.int32_field(1) + vertex_indices: list[int] = betterproto.int32_field(1) @dataclass @@ -607,9 +609,9 @@ class ARMeshAnchor(betterproto.Message): identifier: str = betterproto.string_field(1) # 4x4 row-major matrix encoding the position, orientation, and scale of the # anchor relative to the world coordinate space. - transform: List[float] = betterproto.float_field(2) + transform: list[float] = betterproto.float_field(2) # 3D information about the mesh such as its shape and classifications. - geometry: "ARMeshGeometry" = betterproto.message_field(3) + geometry: ARMeshGeometry = betterproto.message_field(3) @dataclass @@ -624,7 +626,7 @@ class ARMeshData(betterproto.Message): # The timestamp for the data. timestamp: float = betterproto.double_field(1) # Set of mesh anchors containing the mesh data. - mesh_anchor: List["ARMeshAnchor"] = betterproto.message_field(2) + mesh_anchor: list[ARMeshAnchor] = betterproto.message_field(2) @dataclass @@ -653,16 +655,16 @@ class Object(betterproto.Message): # instance or person identity. This provides additional context for the # object type. category: str = betterproto.string_field(2) - type: "ObjectType" = betterproto.enum_field(3) + type: ObjectType = betterproto.enum_field(3) # 3x3 row-major rotation matrix describing the orientation of the rigid # object's frame of reference in the world-coordinate system. - rotation: List[float] = betterproto.float_field(4) + rotation: list[float] = betterproto.float_field(4) # 3x1 vector describing the translation of the rigid object's frame of # reference in the world-coordinate system in meters. - translation: List[float] = betterproto.float_field(5) + translation: list[float] = betterproto.float_field(5) # 3x1 vector describing the scale of the rigid object's frame of reference in # the world-coordinate system in meters. - scale: List[float] = betterproto.float_field(6) + scale: list[float] = betterproto.float_field(6) # List of all the key points associated with this object in the object # coordinate system. The first keypoint is always the object's frame of # reference, e.g. the centroid of the box. E.g. bounding box with its center @@ -672,8 +674,8 @@ class Object(betterproto.Message): # world-coordinate system, we first scale the box then transform the scaled # box. For example, bounding box in the world coordinate system is rotation * # scale * keypoints + translation - keypoints: List["KeyPoint"] = betterproto.message_field(7) - method: "ObjectMethod" = betterproto.enum_field(8) + keypoints: list[KeyPoint] = betterproto.message_field(7) + method: ObjectMethod = betterproto.enum_field(8) @dataclass @@ -701,9 +703,9 @@ class Skeleton(betterproto.Message): # Initialization value for all the keypoints in the skeleton in the object's # local coordinate system. Pursuit will transform these points using object's # transformation to get the keypoint in the world-coordinate. - keypoints: List["KeyPoint"] = betterproto.message_field(3) + keypoints: list[KeyPoint] = betterproto.message_field(3) # List of edges connecting keypoints - edges: List["Edge"] = betterproto.message_field(4) + edges: list[Edge] = betterproto.message_field(4) @dataclass @@ -714,7 +716,7 @@ class Skeletons(betterproto.Message): box. We can have multiple skeletons in the same file. """ - object: List["Skeleton"] = betterproto.message_field(1) + object: list[Skeleton] = betterproto.message_field(1) @dataclass @@ -743,8 +745,8 @@ class Point3D(betterproto.Message): @dataclass class AnnotatedKeyPoint(betterproto.Message): id: int = betterproto.int32_field(1) - point_3d: "Point3D" = betterproto.message_field(2) - point_2d: "NormalizedPoint2D" = betterproto.message_field(3) + point_3d: Point3D = betterproto.message_field(2) + point_2d: NormalizedPoint2D = betterproto.message_field(3) @dataclass @@ -755,7 +757,7 @@ class ObjectAnnotation(betterproto.Message): # boxes, we have 8 keypoints, hands = 21 keypoints, etc. These normalized # points are the projection of the Object's 3D keypoint on the current # frame's camera poses. - keypoints: List["AnnotatedKeyPoint"] = betterproto.message_field(2) + keypoints: list[AnnotatedKeyPoint] = betterproto.message_field(2) # Visibiity of this annotation in a frame. visibility: float = betterproto.float_field(3) @@ -767,15 +769,15 @@ class FrameAnnotation(betterproto.Message): # List of the annotated objects in this frame. Depending on how many object # are observable in this frame, we might have non or as much as # sequence.objects_size() annotations. - annotations: List["ObjectAnnotation"] = betterproto.message_field(2) + annotations: list[ObjectAnnotation] = betterproto.message_field(2) # Information about the camera transformation (in the world coordinate) and # imaging characteristics for a captured video frame. - camera: "ARCamera" = betterproto.message_field(3) + camera: ARCamera = betterproto.message_field(3) # The timestamp for the frame. timestamp: float = betterproto.double_field(4) # Plane center and normal in camera frame. - plane_center: List[float] = betterproto.float_field(5) - plane_normal: List[float] = betterproto.float_field(6) + plane_center: list[float] = betterproto.float_field(5) + plane_normal: list[float] = betterproto.float_field(6) @dataclass @@ -788,6 +790,6 @@ class Sequence(betterproto.Message): # Coordinate system. Given the camera poses of each frame (also in the world- # coordinate) these objects bounding boxes can be projected to each frame to # get the per-frame annotation (i.e. image_annotation below). - objects: List["Object"] = betterproto.message_field(1) + objects: list[Object] = betterproto.message_field(1) # List of annotated data per each frame in sequence + frame information. - frame_annotations: List["FrameAnnotation"] = betterproto.message_field(2) + frame_annotations: list[FrameAnnotation] = betterproto.message_field(2) diff --git a/examples/python/opencv_canny/main.py b/examples/python/opencv_canny/main.py index 361f32dec117..a376fbbcc643 100755 --- a/examples/python/opencv_canny/main.py +++ b/examples/python/opencv_canny/main.py @@ -20,15 +20,15 @@ ``` """ +from __future__ import annotations import argparse -from typing import Optional import cv2 import rerun as rr # pip install rerun-sdk -def run_canny(num_frames: Optional[int]) -> None: +def run_canny(num_frames: int | None) -> None: # Create a new video capture cap = cv2.VideoCapture(0) diff --git a/examples/python/plots/main.py b/examples/python/plots/main.py index c296fae0a11b..77deb5d89728 100755 --- a/examples/python/plots/main.py +++ b/examples/python/plots/main.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - """ Demonstrates how to log simple plots with the Rerun SDK. @@ -8,7 +7,7 @@ ./examples/python/plot/main.py ``` """ - +from __future__ import annotations import argparse import random diff --git a/examples/python/raw_mesh/download_dataset.py b/examples/python/raw_mesh/download_dataset.py index 7d3c8b08d431..5d50b811d86f 100755 --- a/examples/python/raw_mesh/download_dataset.py +++ b/examples/python/raw_mesh/download_dataset.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 +from __future__ import annotations import io import os import zipfile from pathlib import Path -from typing import Final, Optional +from typing import Final import requests @@ -49,7 +50,7 @@ def download_mesh(name: str) -> Path: raise RuntimeError(f"Unknown mesh named: {name}") -def find_mesh_path_if_downloaded(name: str) -> Optional[Path]: +def find_mesh_path_if_downloaded(name: str) -> Path | None: for mesh_format in ("obj", "glb"): for path in DOWNLOADED_DIR.glob(f"{name}/**/*.{mesh_format}"): return path diff --git a/examples/python/raw_mesh/main.py b/examples/python/raw_mesh/main.py index 9639601eb405..066784e2ddc4 100755 --- a/examples/python/raw_mesh/main.py +++ b/examples/python/raw_mesh/main.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - """ Shows how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy. @@ -9,10 +8,11 @@ examples/python/raw_mesh/main.py ``` """ +from __future__ import annotations import argparse from pathlib import Path -from typing import Optional, cast +from typing import cast import numpy as np import rerun as rr # pip install rerun-sdk @@ -28,7 +28,7 @@ def load_scene(path: Path) -> trimesh.Scene: # NOTE: The scene hierarchy will look different compared to the Rust example, as this is using the # trimesh hierarchy, not the raw glTF hierarchy. -def log_scene(scene: trimesh.Scene, node: str, path: Optional[str] = None) -> None: +def log_scene(scene: trimesh.Scene, node: str, path: str | None = None) -> None: path = path + "/" + node if path else node parent = scene.graph.transforms.parents.get(node) diff --git a/examples/python/ros/main.py b/examples/python/ros/main.py index cf09f4a448b9..cc5b50417934 100644 --- a/examples/python/ros/main.py +++ b/examples/python/ros/main.py @@ -9,6 +9,7 @@ NOTE: Unlike many of the other examples, this example requires a system installation of ROS in addition to the packages from requirements.txt. """ +from __future__ import annotations import argparse import sys @@ -162,7 +163,7 @@ def log_tf_as_rigid3(self, path: str, time: Time) -> None: path, rr.TranslationRotationScale3D([t.x, t.y, t.z], rr.Quaternion([q.x, q.y, q.z, q.w])) ) except TransformException as ex: - print("Failed to get transform: {}".format(ex)) + print(f"Failed to get transform: {ex}") def cam_info_callback(self, info: CameraInfo) -> None: """Log a `CameraInfo` with `log_pinhole`.""" diff --git a/examples/python/ros/rerun_urdf.py b/examples/python/ros/rerun_urdf.py index 85b1642efbe2..48b2ead21d25 100644 --- a/examples/python/ros/rerun_urdf.py +++ b/examples/python/ros/rerun_urdf.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import io import os -from typing import Optional, cast +from typing import cast from urllib.parse import urlparse import numpy as np @@ -25,7 +27,7 @@ def load_urdf_from_msg(msg: String) -> URDF: return URDF.load(f, filename_handler=ament_locate_package) -def log_scene(scene: trimesh.Scene, node: str, path: Optional[str] = None, timeless: bool = False) -> None: +def log_scene(scene: trimesh.Scene, node: str, path: str | None = None, timeless: bool = False) -> None: """Log a trimesh scene to rerun.""" path = path + "/" + node if path else node diff --git a/examples/python/segment_anything/main.py b/examples/python/segment_anything/main.py index f8615875f5ef..ce670ec01cc2 100755 --- a/examples/python/segment_anything/main.py +++ b/examples/python/segment_anything/main.py @@ -16,7 +16,7 @@ python main.py --device cuda --model vit_h /path/to/my_image.jpg ``` """ - +from __future__ import annotations import argparse import logging @@ -74,11 +74,11 @@ def create_sam(model: str, device: str) -> Sam: """Load the segment-anything model, fetching the model-file as necessary.""" model_path = get_downloaded_model_path(model) - logging.info("PyTorch version: {}".format(torch.__version__)) - logging.info("Torchvision version: {}".format(torchvision.__version__)) - logging.info("CUDA is available: {}".format(torch.cuda.is_available())) + logging.info(f"PyTorch version: {torch.__version__}") + logging.info(f"Torchvision version: {torchvision.__version__}") + logging.info(f"CUDA is available: {torch.cuda.is_available()}") - logging.info("Building sam from: {}".format(model_path)) + logging.info(f"Building sam from: {model_path}") sam = sam_model_registry[model](checkpoint=model_path) return sam.to(device=device) @@ -90,7 +90,7 @@ def run_segmentation(mask_generator: SamAutomaticMaskGenerator, image: Mat) -> N logging.info("Finding masks") masks = mask_generator.generate(image) - logging.info("Found {} masks".format(len(masks))) + logging.info(f"Found {len(masks)} masks") # Log all the masks stacked together as a tensor # TODO(jleibs): Tensors with class-ids and annotation-coloring would make this much slicker @@ -139,7 +139,7 @@ def is_url(path: str) -> bool: def load_image(image_uri: str) -> Mat: """Conditionally download an image from URL or load it from disk.""" - logging.info("Loading: {}".format(image_uri)) + logging.info(f"Loading: {image_uri}") if is_url(image_uri): response = requests.get(image_uri) response.raise_for_status() diff --git a/examples/python/stable_diffusion/huggingface_pipeline.py b/examples/python/stable_diffusion/huggingface_pipeline.py index cfc3c8fa4a4d..b5ee019e39e2 100644 --- a/examples/python/stable_diffusion/huggingface_pipeline.py +++ b/examples/python/stable_diffusion/huggingface_pipeline.py @@ -20,43 +20,41 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - # type: ignore +from __future__ import annotations import contextlib import inspect -from typing import Callable, List, Optional, Union +from typing import Callable +from typing import List +from typing import Optional +from typing import Union import numpy as np import PIL +import rerun as rr # pip install rerun-sdk import torch from diffusers.configuration_utils import FrozenDict -from diffusers.models import AutoencoderKL, UNet2DConditionModel -from diffusers.pipeline_utils import DiffusionPipeline, ImagePipelineOutput -from diffusers.schedulers import ( - DDIMScheduler, - DPMSolverMultistepScheduler, - EulerAncestralDiscreteScheduler, - EulerDiscreteScheduler, - LMSDiscreteScheduler, - PNDMScheduler, -) -from diffusers.utils import ( - PIL_INTERPOLATION, - deprecate, - is_accelerate_available, - logging, - randn_tensor, -) +from diffusers.models import AutoencoderKL +from diffusers.models import UNet2DConditionModel +from diffusers.pipeline_utils import DiffusionPipeline +from diffusers.pipeline_utils import ImagePipelineOutput +from diffusers.schedulers import DDIMScheduler +from diffusers.schedulers import DPMSolverMultistepScheduler +from diffusers.schedulers import EulerAncestralDiscreteScheduler +from diffusers.schedulers import EulerDiscreteScheduler +from diffusers.schedulers import LMSDiscreteScheduler +from diffusers.schedulers import PNDMScheduler +from diffusers.utils import deprecate +from diffusers.utils import is_accelerate_available +from diffusers.utils import logging +from diffusers.utils import PIL_INTERPOLATION +from diffusers.utils import randn_tensor from packaging import version -from transformers import ( - CLIPTextModel, - CLIPTokenizer, - DPTFeatureExtractor, - DPTForDepthEstimation, -) - -import rerun as rr # pip install rerun-sdk +from transformers import CLIPTextModel +from transformers import CLIPTokenizer +from transformers import DPTFeatureExtractor +from transformers import DPTForDepthEstimation logger = logging.get_logger(__name__) # pylint: disable=invalid-name logger.addHandler(rr.log.text.LoggingHandler("logs")) @@ -111,14 +109,14 @@ def __init__( text_encoder: CLIPTextModel, tokenizer: CLIPTokenizer, unet: UNet2DConditionModel, - scheduler: Union[ - DDIMScheduler, - PNDMScheduler, - LMSDiscreteScheduler, - EulerDiscreteScheduler, - EulerAncestralDiscreteScheduler, - DPMSolverMultistepScheduler, - ], + scheduler: ( + DDIMScheduler + | PNDMScheduler + | LMSDiscreteScheduler + | EulerDiscreteScheduler + | EulerAncestralDiscreteScheduler + | DPMSolverMultistepScheduler + ), depth_estimator: DPTForDepthEstimation, feature_extractor: DPTFeatureExtractor, ): @@ -249,7 +247,7 @@ def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_fr # get unconditional embeddings for classifier free guidance if do_classifier_free_guidance: - uncond_tokens: List[str] + uncond_tokens: list[str] if negative_prompt is None: uncond_tokens = [""] * batch_size elif type(prompt) is not type(negative_prompt): @@ -461,20 +459,20 @@ def prepare_depth_map(self, image, depth_map, batch_size, do_classifier_free_gui @torch.no_grad() def __call__( self, - prompt: Union[str, List[str]], - image: Union[torch.FloatTensor, PIL.Image.Image], - depth_map: Optional[torch.FloatTensor] = None, + prompt: str | list[str], + image: torch.FloatTensor | PIL.Image.Image, + depth_map: torch.FloatTensor | None = None, strength: float = 0.8, - num_inference_steps: Optional[int] = 50, - guidance_scale: Optional[float] = 7.5, - negative_prompt: Optional[Union[str, List[str]]] = None, - num_images_per_prompt: Optional[int] = 1, - eta: Optional[float] = 0.0, - generator: Optional[torch.Generator] = None, - output_type: Optional[str] = "pil", + num_inference_steps: int | None = 50, + guidance_scale: float | None = 7.5, + negative_prompt: str | list[str] | None = None, + num_images_per_prompt: int | None = 1, + eta: float | None = 0.0, + generator: torch.Generator | None = None, + output_type: str | None = "pil", return_dict: bool = True, - callback: Optional[Callable[[int, int, torch.FloatTensor], None]] = None, - callback_steps: Optional[int] = 1, + callback: Callable[[int, int, torch.FloatTensor], None] | None = None, + callback_steps: int | None = 1, ): r""" Function invoked when calling the pipeline for generation. diff --git a/examples/python/stable_diffusion/main.py b/examples/python/stable_diffusion/main.py index ff7d94e370d6..008fc8d04c48 100755 --- a/examples/python/stable_diffusion/main.py +++ b/examples/python/stable_diffusion/main.py @@ -4,6 +4,8 @@ For more info see: https://github.com/Stability-AI/stablediffusion """ +from __future__ import annotations + import argparse import os import platform diff --git a/examples/python/text_logging/main.py b/examples/python/text_logging/main.py index 20f2336c9082..3346a0713a52 100755 --- a/examples/python/text_logging/main.py +++ b/examples/python/text_logging/main.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - """ How to integrate python's native `logging` with the Rerun SDK. @@ -8,7 +7,7 @@ ./examples/python/text_logging/main.py ``` """ - +from __future__ import annotations import argparse import logging diff --git a/examples/python/tracking_hf_opencv/main.py b/examples/python/tracking_hf_opencv/main.py index 2ba17bd2fea2..2e3ede04ad31 100755 --- a/examples/python/tracking_hf_opencv/main.py +++ b/examples/python/tracking_hf_opencv/main.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 """Example applying simple object detection and tracking on a video.""" +from __future__ import annotations + import argparse import json import logging import os from dataclasses import dataclass from pathlib import Path -from typing import Any, Dict, Final, List, Sequence +from typing import Any, Final, Sequence import cv2 as cv import numpy as np @@ -40,16 +42,16 @@ class Detection: """Information about a detected object.""" class_id: int - bbox_xywh: List[float] + bbox_xywh: list[float] image_width: int image_height: int - def scaled_to_fit_image(self, target_image: npt.NDArray[Any]) -> "Detection": + def scaled_to_fit_image(self, target_image: npt.NDArray[Any]) -> Detection: """Rescales detection to fit to target image.""" target_height, target_width = target_image.shape[:2] return self.scaled_to_fit_size(target_width=target_width, target_height=target_height) - def scaled_to_fit_size(self, target_width: int, target_height: int) -> "Detection": + def scaled_to_fit_size(self, target_width: int, target_height: int) -> Detection: """Rescales detection to fit to target image with given size.""" if target_height == self.image_height and target_width == self.image_width: return self @@ -67,14 +69,14 @@ def scaled_to_fit_size(self, target_width: int, target_height: int) -> "Detectio class Detector: """Detects objects to track.""" - def __init__(self, coco_categories: List[Dict[str, Any]]) -> None: + def __init__(self, coco_categories: list[dict[str, Any]]) -> None: logging.info("Initializing neural net for detection and segmentation.") self.feature_extractor = DetrFeatureExtractor.from_pretrained("facebook/detr-resnet-50-panoptic") self.model = DetrForSegmentation.from_pretrained("facebook/detr-resnet-50-panoptic") - self.is_thing_from_id = {cat["id"]: bool(cat["isthing"]) for cat in coco_categories} # type: Dict[int, bool] + self.is_thing_from_id: dict[int, bool] = {cat["id"]: bool(cat["isthing"]) for cat in coco_categories} - def detect_objects_to_track(self, rgb: npt.NDArray[np.uint8], frame_idx: int) -> List[Detection]: + def detect_objects_to_track(self, rgb: npt.NDArray[np.uint8], frame_idx: int) -> list[Detection]: logging.info("Looking for things to track on frame %d", frame_idx) logging.debug("Preprocess image for detection network") @@ -105,7 +107,7 @@ def detect_objects_to_track(self, rgb: npt.NDArray[np.uint8], frame_idx: int) -> self.log_detections(boxes, class_ids, things) - objects_to_track = [] # type: List[Detection] + objects_to_track: list[Detection] = [] for idx, (class_id, is_thing) in enumerate(zip(class_ids, things)): if is_thing: x_min, y_min, x_max, y_max = boxes[idx, :] @@ -121,7 +123,7 @@ def detect_objects_to_track(self, rgb: npt.NDArray[np.uint8], frame_idx: int) -> return objects_to_track - def log_detections(self, boxes: npt.NDArray[np.float32], class_ids: List[int], things: List[bool]) -> None: + def log_detections(self, boxes: npt.NDArray[np.float32], class_ids: list[int], things: list[bool]) -> None: things_np = np.array(things) class_ids_np = np.array(class_ids, dtype=np.uint16) @@ -165,7 +167,7 @@ def __init__(self, tracking_id: int, detection: Detection, bgr: npt.NDArray[np.u self.log_tracked() @classmethod - def create_new_tracker(cls, detection: Detection, bgr: npt.NDArray[np.uint8]) -> "Tracker": + def create_new_tracker(cls, detection: Detection, bgr: npt.NDArray[np.uint8]) -> Tracker: new_tracker = cls(cls.next_tracking_id, detection, bgr) cls.next_tracking_id += 1 return new_tracker @@ -234,7 +236,7 @@ def match_score(self, other: Detection) -> float: return box_iou(tracked_bbox, other_bbox) -def box_iou(first: List[float], second: List[float]) -> float: +def box_iou(first: list[float], second: list[float]) -> float: """Calculate Intersection over Union (IoU) between two 2D rectangles in XYWH format.""" left = max(first[0], second[0]) right = min(first[0] + first[2], second[0] + second[2]) @@ -252,7 +254,7 @@ def box_iou(first: List[float], second: List[float]) -> float: return intersection_area / union_area -def clip_bbox_to_image(bbox_xywh: List[float], image_width: int, image_height: int) -> List[float]: +def clip_bbox_to_image(bbox_xywh: list[float], image_width: int, image_height: int) -> list[float]: x_min = max(0, bbox_xywh[0]) y_min = max(0, bbox_xywh[1]) x_max = min(image_width - 1, bbox_xywh[0] + bbox_xywh[2]) @@ -262,11 +264,11 @@ def clip_bbox_to_image(bbox_xywh: List[float], image_width: int, image_height: i def update_trackers_with_detections( - trackers: List[Tracker], + trackers: list[Tracker], detections: Sequence[Detection], label_strs: Sequence[str], bgr: npt.NDArray[np.uint8], -) -> List[Tracker]: +) -> list[Tracker]: """ Tries to match detections to existing trackers and updates the trackers if they match. @@ -274,7 +276,7 @@ def update_trackers_with_detections( Returns the new set of trackers. """ non_updated_trackers = list(trackers) # shallow copy - updated_trackers = [] # type: List[Tracker] + updated_trackers: list[Tracker] = [] logging.debug("Updating %d trackers with %d new detections", len(trackers), len(detections)) for detection in detections: @@ -322,7 +324,7 @@ def track_objects(video_path: str) -> None: frame_idx = 0 label_strs = [cat["name"] or str(cat["id"]) for cat in coco_categories] - trackers = [] # type: List[Tracker] + trackers: list[Tracker] = [] while cap.isOpened(): ret, bgr = cap.read() rr.set_time_sequence("frame", frame_idx) @@ -400,7 +402,7 @@ def main() -> None: setup_looging() - video_path = args.video_path # type: str + video_path: str = args.video_path if not video_path: video_path = get_downloaded_path(args.dataset_dir, args.video) diff --git a/justfile b/justfile index d1383a345e80..22a9dc4b8ead 100644 --- a/justfile +++ b/justfile @@ -62,7 +62,7 @@ py-format: set -euxo pipefail black --config rerun_py/pyproject.toml {{py_folders}} blackdoc {{py_folders}} - pyupgrade --py37-plus `find rerun_py/rerun/ -name "*.py" -type f` + pyupgrade --py38-plus `find {{py_folders}} -name "*.py" -type f` ruff --fix --config rerun_py/pyproject.toml {{py_folders}} # Check that all the requirements.txt files for all the examples are correct diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index ce81f1e4fb2c..8493ae926327 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -1,10 +1,10 @@ """The Rerun Python SDK, which is a wrapper around the re_sdk crate.""" +from __future__ import annotations import atexit import logging import sys from inspect import getmembers, isfunction -from typing import Optional import rerun_bindings as bindings # type: ignore[attr-defined] @@ -51,13 +51,13 @@ set_global_data_recording, set_thread_local_data_recording, ) - -# --- Init RecordingStream class --- from rerun.recording_stream import _patch as recording_stream_patch from rerun.script_helpers import script_add_args, script_setup, script_teardown from rerun.sinks import connect, disconnect, memory_recording, save, serve, spawn from rerun.time import reset_time, set_time_nanos, set_time_seconds, set_time_sequence +# --- Init RecordingStream class --- + # Inject all relevant methods into the `RecordingStream` class. # We need to do this from here to avoid circular import issues. recording_stream_patch( @@ -163,7 +163,7 @@ def init( application_id: str, - recording_id: Optional[str] = None, + recording_id: str | None = None, spawn: bool = False, init_logging: bool = True, default_enabled: bool = True, @@ -249,7 +249,7 @@ def init( def new_recording( application_id: str, - recording_id: Optional[str] = None, + recording_id: str | None = None, make_default: bool = False, make_thread_default: bool = False, spawn: bool = False, diff --git a/rerun_py/rerun_sdk/rerun/__main__.py b/rerun_py/rerun_sdk/rerun/__main__.py index 8213af58ec28..3af923bf37bf 100644 --- a/rerun_py/rerun_sdk/rerun/__main__.py +++ b/rerun_py/rerun_sdk/rerun/__main__.py @@ -1,8 +1,9 @@ """See `python3 -m rerun --help`.""" +from __future__ import annotations import sys -from rerun import bindings, unregister_shutdown # type: ignore[attr-defined] +from rerun import bindings, unregister_shutdown def main() -> None: diff --git a/rerun_py/rerun_sdk/rerun/color_conversion.py b/rerun_py/rerun_sdk/rerun/color_conversion.py index acebb0560b7d..8d0cf599d363 100644 --- a/rerun_py/rerun_sdk/rerun/color_conversion.py +++ b/rerun_py/rerun_sdk/rerun/color_conversion.py @@ -1,5 +1,5 @@ """Color conversion utilities.""" -from typing import Union +from __future__ import annotations import numpy as np import numpy.typing as npt @@ -33,7 +33,7 @@ def u8_array_to_rgba(arr: npt.NDArray[np.uint8]) -> npt.NDArray[np.uint32]: return arr # type: ignore[return-value] -def linear_to_gamma_u8_value(linear: npt.NDArray[Union[np.float32, np.float64]]) -> npt.NDArray[np.uint8]: +def linear_to_gamma_u8_value(linear: npt.NDArray[np.float32 | np.float64]) -> npt.NDArray[np.uint8]: """ Transform color values from linear [0.0, 1.0] to gamma encoded [0, 255]. @@ -73,7 +73,7 @@ def linear_to_gamma_u8_value(linear: npt.NDArray[Union[np.float32, np.float64]]) return gamma.astype(np.uint8) -def linear_to_gamma_u8_pixel(linear: npt.NDArray[Union[np.float32, np.float64]]) -> npt.NDArray[np.uint8]: +def linear_to_gamma_u8_pixel(linear: npt.NDArray[np.float32 | np.float64]) -> npt.NDArray[np.uint8]: """ Transform color pixels from linear [0, 1] to gamma encoded [0, 255]. diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 2476e09ecb52..983b41c21bfd 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -1,5 +1,4 @@ """The components package defines Python wrapper types for common registered Rerun components.""" - from __future__ import annotations from typing import Any, Final, Type, cast diff --git a/rerun_py/rerun_sdk/rerun/components/disconnected_space.py b/rerun_py/rerun_sdk/rerun/components/disconnected_space.py index 2be6f77e976d..1ce505c81bfc 100644 --- a/rerun_py/rerun_sdk/rerun/components/disconnected_space.py +++ b/rerun_py/rerun_sdk/rerun/components/disconnected_space.py @@ -2,10 +2,7 @@ import pyarrow as pa -from rerun.components import ( - REGISTERED_COMPONENT_NAMES, - ComponentTypeFactory, -) +from rerun.components import REGISTERED_COMPONENT_NAMES, ComponentTypeFactory __all__ = [ "DisconnectedSpaceArray", diff --git a/rerun_py/rerun_sdk/rerun/components/pinhole.py b/rerun_py/rerun_sdk/rerun/components/pinhole.py index 8ef6cf663af7..dc1a423cc8e3 100644 --- a/rerun_py/rerun_sdk/rerun/components/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/components/pinhole.py @@ -1,16 +1,12 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Union import numpy as np import numpy.typing as npt import pyarrow as pa -from rerun.components import ( - REGISTERED_COMPONENT_NAMES, - ComponentTypeFactory, -) +from rerun.components import REGISTERED_COMPONENT_NAMES, ComponentTypeFactory from rerun.log import _normalize_matrix3 __all__ = [ @@ -27,7 +23,7 @@ class Pinhole: image_from_cam: npt.ArrayLike # Pixel resolution (usually integers) of child image space. Width and height. - resolution: Union[npt.ArrayLike, None] + resolution: npt.ArrayLike | None class PinholeArray(pa.ExtensionArray): # type: ignore[misc] diff --git a/rerun_py/rerun_sdk/rerun/components/rect2d.py b/rerun_py/rerun_sdk/rerun/components/rect2d.py index a0d521e5f6ca..55fb918a4bb4 100644 --- a/rerun_py/rerun_sdk/rerun/components/rect2d.py +++ b/rerun_py/rerun_sdk/rerun/components/rect2d.py @@ -6,11 +6,7 @@ import numpy.typing as npt import pyarrow as pa -from rerun.components import ( - REGISTERED_COMPONENT_NAMES, - ComponentTypeFactory, - build_dense_union, -) +from rerun.components import REGISTERED_COMPONENT_NAMES, ComponentTypeFactory, build_dense_union __all__ = [ "Rect2DArray", diff --git a/rerun_py/rerun_sdk/rerun/components/tensor.py b/rerun_py/rerun_sdk/rerun/components/tensor.py index b5d50cd2933e..3ccc8ee70c02 100644 --- a/rerun_py/rerun_sdk/rerun/components/tensor.py +++ b/rerun_py/rerun_sdk/rerun/components/tensor.py @@ -8,11 +8,7 @@ import pyarrow as pa from rerun import bindings -from rerun.components import ( - REGISTERED_COMPONENT_NAMES, - ComponentTypeFactory, - build_dense_union, -) +from rerun.components import REGISTERED_COMPONENT_NAMES, ComponentTypeFactory, build_dense_union __all__ = [ "TensorArray", diff --git a/rerun_py/rerun_sdk/rerun/components/transform3d.py b/rerun_py/rerun_sdk/rerun/components/transform3d.py index 412056414934..701169e0f350 100644 --- a/rerun_py/rerun_sdk/rerun/components/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/components/transform3d.py @@ -1,7 +1,6 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Union import numpy as np import numpy.typing as npt @@ -49,10 +48,10 @@ class Transform3D: class TranslationAndMat3: """Representation of a affine transform via a 3x3 translation matrix paired with a translation.""" - translation: Union[npt.ArrayLike, Translation3D, None] = None + translation: npt.ArrayLike | Translation3D | None = None """3D translation vector, applied after the matrix. Uses (0, 0, 0) if not set.""" - matrix: Union[npt.ArrayLike, None] = None + matrix: npt.ArrayLike | None = None """The row-major 3x3 matrix for scale, rotation & skew matrix. Uses identity if not set.""" @@ -60,10 +59,10 @@ class TranslationAndMat3: class Rigid3D: """Representation of a rigid transform via separate translation & rotation.""" - translation: Union[Translation3D, npt.ArrayLike, None] = None + translation: Translation3D | npt.ArrayLike | None = None """3D translation vector, applied last.""" - rotation: Union[Quaternion, RotationAxisAngle, None] = None + rotation: Quaternion | RotationAxisAngle | None = None """3D rotation, represented as a quaternion or axis + angle, applied second.""" @@ -71,13 +70,13 @@ class Rigid3D: class TranslationRotationScale3D: """Representation of an affine transform via separate translation, rotation & scale.""" - translation: Union[Translation3D, npt.ArrayLike, None] = None + translation: Translation3D | npt.ArrayLike | None = None """3D translation vector, applied last.""" - rotation: Union[Quaternion, RotationAxisAngle, None] = None + rotation: Quaternion | RotationAxisAngle | None = None """3D rotation, represented as a quaternion or axis + angle, applied second.""" - scale: Union[Scale3D, npt.ArrayLike, float, None] = None + scale: Scale3D | npt.ArrayLike | float | None = None """3D scaling either a 3D vector, scalar or None. Applied first.""" @@ -92,7 +91,7 @@ class Translation3D: class Scale3D: """3D scale expressed as either a uniform scale or a vector.""" - scale: Union[npt.ArrayLike, float] + scale: npt.ArrayLike | float @dataclass @@ -107,14 +106,14 @@ class RotationAxisAngle: If normalization fails (typically because the vector is length zero), the rotation is silently ignored. """ - degrees: Union[float, None] = None + degrees: float | None = None """3D rotation angle in degrees. Only one of `degrees` or `radians` should be set.""" - radians: Union[float, None] = None + radians: float | None = None """3D rotation angle in radians. Only one of `degrees` or `radians` should be set.""" -def optional_translation_to_arrow(translation: Union[npt.ArrayLike, Translation3D, None]) -> pa.UnionArray: +def optional_translation_to_arrow(translation: npt.ArrayLike | Translation3D | None) -> pa.UnionArray: # "unpack" rr.Translation3D first. if isinstance(translation, Translation3D): translation = translation.translation @@ -195,7 +194,7 @@ def build_union_array_from_rotation( def build_union_array_from_scale( - scale: Union[Scale3D, npt.ArrayLike, float, None], type: pa.DenseUnionType + scale: Scale3D | npt.ArrayLike | float | None, type: pa.DenseUnionType ) -> pa.UnionArray: # "unpack" rr.Scale3D first. if isinstance(scale, Scale3D): diff --git a/rerun_py/rerun_sdk/rerun/experimental.py b/rerun_py/rerun_sdk/rerun/experimental.py index fcde61db61fa..bccd985f59db 100644 --- a/rerun_py/rerun_sdk/rerun/experimental.py +++ b/rerun_py/rerun_sdk/rerun/experimental.py @@ -4,6 +4,7 @@ These features are not yet stable and may change in future releases without going through the normal deprecation cycle. """ +from __future__ import annotations from rerun.log.experimental.blueprint import add_space_view, new_blueprint, set_auto_space_views, set_panels from rerun.log.experimental.text import log_text_box diff --git a/rerun_py/rerun_sdk/rerun/log/__init__.py b/rerun_py/rerun_sdk/rerun/log/__init__.py index b401b5b644a4..4388a09810b7 100644 --- a/rerun_py/rerun_sdk/rerun/log/__init__.py +++ b/rerun_py/rerun_sdk/rerun/log/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional, Sequence, Union import numpy as np @@ -11,11 +13,11 @@ OptionalKeyPointIds = Optional[Union[int, npt.ArrayLike]] -def _to_sequence(array: Optional[npt.ArrayLike]) -> Optional[Sequence[float]]: +def _to_sequence(array: npt.ArrayLike | None) -> Sequence[float] | None: return np.require(array, float).tolist() # type: ignore[no-any-return] -def _normalize_colors(colors: Optional[Union[Color, Colors]] = None) -> npt.NDArray[np.uint8]: +def _normalize_colors(colors: Color | Colors | None = None) -> npt.NDArray[np.uint8]: """ Normalize flexible colors arrays. @@ -47,7 +49,7 @@ def _normalize_ids(class_ids: OptionalClassIds = None) -> npt.NDArray[np.uint16] return np.atleast_1d(np.array(class_ids, dtype=np.uint16, copy=False)) -def _normalize_radii(radii: Optional[npt.ArrayLike] = None) -> npt.NDArray[np.float32]: +def _normalize_radii(radii: npt.ArrayLike | None = None) -> npt.NDArray[np.float32]: """Normalize flexible radii arrays.""" if radii is None: return np.array((), dtype=np.float32) @@ -55,14 +57,14 @@ def _normalize_radii(radii: Optional[npt.ArrayLike] = None) -> npt.NDArray[np.fl return np.atleast_1d(np.array(radii, dtype=np.float32, copy=False)) -def _normalize_labels(labels: Optional[Union[str, Sequence[str]]]) -> Sequence[str]: +def _normalize_labels(labels: str | Sequence[str] | None) -> Sequence[str]: if labels is None: return [] else: return labels -def _normalize_matrix3(matrix: Union[npt.ArrayLike, None]) -> npt.ArrayLike: +def _normalize_matrix3(matrix: npt.ArrayLike | None) -> npt.ArrayLike: matrix = np.eye(3) if matrix is None else matrix matrix = np.array(matrix, dtype=np.float32, order="F") if matrix.shape != (3, 3): diff --git a/rerun_py/rerun_sdk/rerun/log/annotation.py b/rerun_py/rerun_sdk/rerun/log/annotation.py index e55ec0723630..3d204f9062aa 100644 --- a/rerun_py/rerun_sdk/rerun/log/annotation.py +++ b/rerun_py/rerun_sdk/rerun/log/annotation.py @@ -1,5 +1,7 @@ +from __future__ import annotations + from dataclasses import dataclass -from typing import Iterable, Optional, Sequence, Tuple, Union +from typing import Iterable, Sequence, Tuple, Union from rerun import bindings from rerun.log import Color, _normalize_colors @@ -25,10 +27,10 @@ class AnnotationInfo: id: int = 0 """The id of the class or key-point to annotate""" - label: Optional[str] = None + label: str | None = None """The label that will be shown in the UI""" - color: Optional[Color] = None + color: Color | None = None """The color that will be applied to the annotated entity""" @@ -53,13 +55,13 @@ class ClassDescription: Keypoints in turn may be connected to each other by connections (typically used for skeleton edges). """ - info: Optional[AnnotationInfoLike] = None + info: AnnotationInfoLike | None = None """The annotation info for the class""" - keypoint_annotations: Optional[Iterable[AnnotationInfoLike]] = None + keypoint_annotations: Iterable[AnnotationInfoLike] | None = None """The annotation infos for the all key-points""" - keypoint_connections: Optional[Iterable[Union[int, Tuple[int, int]]]] = None + keypoint_connections: Iterable[int | tuple[int, int]] | None = None """The connections between key-points""" @@ -77,10 +79,10 @@ def coerce_class_descriptor_like(arg: ClassDescriptionLike) -> ClassDescription: @log_decorator def log_annotation_context( entity_path: str, - class_descriptions: Union[ClassDescriptionLike, Iterable[ClassDescriptionLike]], + class_descriptions: ClassDescriptionLike | Iterable[ClassDescriptionLike], *, timeless: bool = True, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log an annotation context made up of a collection of [ClassDescription][rerun.log.annotation.ClassDescription]s. @@ -131,7 +133,7 @@ def log_annotation_context( # Convert back to fixed tuple for easy pyo3 conversion # This is pretty messy but will likely go away / be refactored with pending data-model changes. - def info_to_tuple(info: Optional[AnnotationInfoLike]) -> Tuple[int, Optional[str], Optional[Sequence[int]]]: + def info_to_tuple(info: AnnotationInfoLike | None) -> tuple[int, str | None, Sequence[int] | None]: if info is None: return (0, None, None) info = coerce_annotation_info(info) @@ -139,7 +141,7 @@ def info_to_tuple(info: Optional[AnnotationInfoLike]) -> Tuple[int, Optional[str return (info.id, info.label, color) def keypoint_connections_to_flat_list( - keypoint_connections: Optional[Iterable[Union[int, Tuple[int, int]]]] + keypoint_connections: Iterable[int | tuple[int, int]] | None ) -> Sequence[int]: if keypoint_connections is None: return [] diff --git a/rerun_py/rerun_sdk/rerun/log/arrow.py b/rerun_py/rerun_sdk/rerun/log/arrow.py index 570261077345..ca01b302a4e9 100644 --- a/rerun_py/rerun_sdk/rerun/log/arrow.py +++ b/rerun_py/rerun_sdk/rerun/log/arrow.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import Any import numpy as np import numpy.typing as npt @@ -22,15 +24,15 @@ @log_decorator def log_arrow( entity_path: str, - origin: Optional[npt.ArrayLike], - vector: Optional[npt.ArrayLike] = None, + origin: npt.ArrayLike | None, + vector: npt.ArrayLike | None = None, *, - color: Optional[Color] = None, - label: Optional[str] = None, - width_scale: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + color: Color | None = None, + label: str | None = None, + width_scale: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a 3D arrow. @@ -66,8 +68,8 @@ def log_arrow( """ - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if origin is not None: if vector is None: diff --git a/rerun_py/rerun_sdk/rerun/log/bounding_box.py b/rerun_py/rerun_sdk/rerun/log/bounding_box.py index 2bc1b3eba163..bbb17943cc89 100644 --- a/rerun_py/rerun_sdk/rerun/log/bounding_box.py +++ b/rerun_py/rerun_sdk/rerun/log/bounding_box.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import Any import numpy as np import numpy.typing as npt @@ -26,16 +28,16 @@ def log_obb( entity_path: str, *, - half_size: Optional[npt.ArrayLike], - position: Optional[npt.ArrayLike] = None, - rotation_q: Optional[npt.ArrayLike] = None, - color: Optional[Color] = None, - stroke_width: Optional[float] = None, - label: Optional[str] = None, - class_id: Optional[int] = None, - ext: Optional[Dict[str, Any]] = None, + half_size: npt.ArrayLike | None, + position: npt.ArrayLike | None = None, + rotation_q: npt.ArrayLike | None = None, + color: Color | None = None, + stroke_width: float | None = None, + label: str | None = None, + class_id: int | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a 3D Oriented Bounding Box, or OBB. @@ -76,8 +78,8 @@ def log_obb( """ recording = RecordingStream.to_native(recording) - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if half_size is not None: half_size = np.require(half_size, dtype="float32") diff --git a/rerun_py/rerun_sdk/rerun/log/camera.py b/rerun_py/rerun_sdk/rerun/log/camera.py index 3743881feb7d..0a3b306cb669 100644 --- a/rerun_py/rerun_sdk/rerun/log/camera.py +++ b/rerun_py/rerun_sdk/rerun/log/camera.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations import numpy.typing as npt @@ -20,7 +20,7 @@ def log_pinhole( width: int, height: int, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a perspective camera model. diff --git a/rerun_py/rerun_sdk/rerun/log/clear.py b/rerun_py/rerun_sdk/rerun/log/clear.py index 4a0ab3ddc13d..ff94e55d5ab8 100644 --- a/rerun_py/rerun_sdk/rerun/log/clear.py +++ b/rerun_py/rerun_sdk/rerun/log/clear.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations from rerun import bindings from rerun.recording_stream import RecordingStream @@ -8,7 +8,7 @@ def log_cleared( entity_path: str, *, recursive: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Indicate that an entity at a given path should no longer be displayed. diff --git a/rerun_py/rerun_sdk/rerun/log/error_utils.py b/rerun_py/rerun_sdk/rerun/log/error_utils.py index 4a4366235e50..07eb9feec92e 100644 --- a/rerun_py/rerun_sdk/rerun/log/error_utils.py +++ b/rerun_py/rerun_sdk/rerun/log/error_utils.py @@ -1,6 +1,7 @@ +from __future__ import annotations + import inspect import logging -from typing import Optional import rerun from rerun.log.text_internal import LogLevel, log_text_entry_internal @@ -20,7 +21,7 @@ def _build_warning_context_string(skip_first: int) -> str: def _send_warning( message: str, depth_to_user_code: int, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Sends a warning about the usage of the Rerun SDK. diff --git a/rerun_py/rerun_sdk/rerun/log/experimental/blueprint.py b/rerun_py/rerun_sdk/rerun/log/experimental/blueprint.py index 539f19f8dea2..244a8b951f4a 100644 --- a/rerun_py/rerun_sdk/rerun/log/experimental/blueprint.py +++ b/rerun_py/rerun_sdk/rerun/log/experimental/blueprint.py @@ -1,5 +1,5 @@ # TODO(jleibs): docstrings -from typing import List, Optional +from __future__ import annotations import rerun_bindings as bindings # type: ignore[attr-defined] @@ -9,7 +9,7 @@ def new_blueprint( application_id: str, *, - blueprint_id: Optional[str] = None, + blueprint_id: str | None = None, make_default: bool = False, make_thread_default: bool = False, spawn: bool = False, @@ -88,9 +88,9 @@ def new_blueprint( def add_space_view( *, origin: str, - name: Optional[str], - entity_paths: Optional[List[str]], - blueprint: Optional[RecordingStream] = None, + name: str | None, + entity_paths: list[str] | None, + blueprint: RecordingStream | None = None, ) -> None: """ Add a new space view to the blueprint. @@ -117,11 +117,11 @@ def add_space_view( def set_panels( *, - all_expanded: Optional[bool] = None, - blueprint_view_expanded: Optional[bool] = None, - selection_view_expanded: Optional[bool] = None, - timeline_view_expanded: Optional[bool] = None, - blueprint: Optional[RecordingStream] = None, + all_expanded: bool | None = None, + blueprint_view_expanded: bool | None = None, + selection_view_expanded: bool | None = None, + timeline_view_expanded: bool | None = None, + blueprint: RecordingStream | None = None, ) -> None: """ Change the visibility of the view panels. @@ -150,7 +150,7 @@ def set_panels( def set_auto_space_views( enabled: bool, - blueprint: Optional[RecordingStream] = None, + blueprint: RecordingStream | None = None, ) -> None: """ Change whether or not the blueprint automatically adds space views for all entities. diff --git a/rerun_py/rerun_sdk/rerun/log/experimental/text.py b/rerun_py/rerun_sdk/rerun/log/experimental/text.py index a46e554bf5e4..1e75ecbcb38b 100644 --- a/rerun_py/rerun_sdk/rerun/log/experimental/text.py +++ b/rerun_py/rerun_sdk/rerun/log/experimental/text.py @@ -1,20 +1,23 @@ +from __future__ import annotations + import logging -from typing import Any, Dict, Optional +from typing import Any -# Fully qualified to avoid circular import import rerun.log.extension_components from rerun import bindings from rerun.components.experimental.text_box import TextBoxArray from rerun.components.instance import InstanceArray from rerun.log.log_decorator import log_decorator +# Fully qualified to avoid circular import + @log_decorator def log_text_box( entity_path: str, text: str, *, - ext: Optional[Dict[str, Any]] = None, + ext: dict[str, Any] | None = None, timeless: bool = False, ) -> None: """ @@ -34,8 +37,8 @@ def log_text_box( Whether the text-box should be timeless. """ - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if text: instanced["rerun.text_box"] = TextBoxArray.from_bodies([(text,)]) diff --git a/rerun_py/rerun_sdk/rerun/log/extension_components.py b/rerun_py/rerun_sdk/rerun/log/extension_components.py index c68ebcd3cd61..1580bdd95799 100644 --- a/rerun_py/rerun_sdk/rerun/log/extension_components.py +++ b/rerun_py/rerun_sdk/rerun/log/extension_components.py @@ -1,16 +1,19 @@ -from typing import Any, Dict, Optional, Sequence +from __future__ import annotations + +from typing import Any, Sequence import numpy as np import numpy.typing as npt import pyarrow as pa -# Fully qualified to avoid circular import import rerun.log.error_utils from rerun import bindings from rerun.components.instance import InstanceArray from rerun.log.log_decorator import log_decorator from rerun.recording_stream import RecordingStream +# Fully qualified to avoid circular import + __all__ = [ "_add_extension_components", "log_extension_components", @@ -18,14 +21,14 @@ EXT_PREFIX = "ext." -EXT_COMPONENT_TYPES: Dict[str, Any] = {} +EXT_COMPONENT_TYPES: dict[str, Any] = {} def _add_extension_components( - instanced: Dict[str, Any], - splats: Dict[str, Any], - ext: Dict[str, Any], - identifiers: Optional[npt.NDArray[np.uint64]], + instanced: dict[str, Any], + splats: dict[str, Any], + ext: dict[str, Any], + identifiers: npt.NDArray[np.uint64] | None, ) -> None: for name, value in ext.items(): # Don't log empty components @@ -66,11 +69,11 @@ def _add_extension_components( @log_decorator def log_extension_components( entity_path: str, - ext: Dict[str, Any], + ext: dict[str, Any], *, - identifiers: Optional[Sequence[int]] = None, + identifiers: Sequence[int] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log an arbitrary collection of extension components. @@ -126,8 +129,8 @@ def log_extension_components( except ValueError: rerun.log.error_utils._send_warning("Only integer identifiers supported", 1) - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if len(identifiers_np): instanced["rerun.instance_key"] = InstanceArray.from_numpy(identifiers_np) diff --git a/rerun_py/rerun_sdk/rerun/log/file.py b/rerun_py/rerun_sdk/rerun/log/file.py index a916bb6726bf..056acda18f9e 100644 --- a/rerun_py/rerun_sdk/rerun/log/file.py +++ b/rerun_py/rerun_sdk/rerun/log/file.py @@ -1,7 +1,8 @@ +from __future__ import annotations + from dataclasses import dataclass from enum import Enum from pathlib import Path -from typing import Optional import numpy as np import numpy.typing as npt @@ -49,11 +50,11 @@ def log_mesh_file( entity_path: str, mesh_format: MeshFormat, *, - mesh_bytes: Optional[bytes] = None, - mesh_path: Optional[Path] = None, - transform: Optional[npt.ArrayLike] = None, + mesh_bytes: bytes | None = None, + mesh_path: Path | None = None, + transform: npt.ArrayLike | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log the contents of a mesh file (.gltf, .glb, .obj, …). @@ -116,11 +117,11 @@ def log_mesh_file( def log_image_file( entity_path: str, *, - img_bytes: Optional[bytes] = None, - img_path: Optional[Path] = None, - img_format: Optional[ImageFormat] = None, + img_bytes: bytes | None = None, + img_path: Path | None = None, + img_format: ImageFormat | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log an image file given its contents or path on disk. diff --git a/rerun_py/rerun_sdk/rerun/log/image.py b/rerun_py/rerun_sdk/rerun/log/image.py index 696b62f8f142..e457eeb2e201 100644 --- a/rerun_py/rerun_sdk/rerun/log/image.py +++ b/rerun_py/rerun_sdk/rerun/log/image.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import Any import numpy as np import numpy.typing as npt @@ -21,10 +23,10 @@ def log_image( entity_path: str, image: Tensor, *, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a gray or color image. @@ -96,11 +98,11 @@ def log_depth_image( entity_path: str, image: Tensor, *, - draw_order: Optional[float] = None, - meter: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + draw_order: float | None = None, + meter: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a depth image. @@ -175,10 +177,10 @@ def log_segmentation_image( entity_path: str, image: npt.ArrayLike, *, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log an image made up of integer class-ids. diff --git a/rerun_py/rerun_sdk/rerun/log/lines.py b/rerun_py/rerun_sdk/rerun/log/lines.py index a8df9bf4eac3..888369a98789 100644 --- a/rerun_py/rerun_sdk/rerun/log/lines.py +++ b/rerun_py/rerun_sdk/rerun/log/lines.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import Any import numpy as np import numpy.typing as npt @@ -25,13 +27,13 @@ @deprecated(version="0.2.0", reason="Use log_line_strip instead") def log_path( entity_path: str, - positions: Optional[npt.ArrayLike], + positions: npt.ArrayLike | None, *, - stroke_width: Optional[float] = None, - color: Optional[Color] = None, - ext: Optional[Dict[str, Any]] = None, + stroke_width: float | None = None, + color: Color | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: log_line_strip( entity_path, positions, stroke_width=stroke_width, color=color, ext=ext, timeless=timeless, recording=recording @@ -41,14 +43,14 @@ def log_path( @log_decorator def log_line_strip( entity_path: str, - positions: Optional[npt.ArrayLike], + positions: npt.ArrayLike | None, *, - stroke_width: Optional[float] = None, - color: Optional[Color] = None, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + stroke_width: float | None = None, + color: Color | None = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: r""" Log a line strip through 2D or 3D space. @@ -92,8 +94,8 @@ def log_line_strip( if positions is not None: positions = np.require(positions, dtype="float32") - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if positions is not None: if positions.shape[1] == 2: @@ -132,12 +134,12 @@ def log_line_segments( entity_path: str, positions: npt.ArrayLike, *, - stroke_width: Optional[float] = None, - color: Optional[Color] = None, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + stroke_width: float | None = None, + color: Color | None = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: r""" Log many 2D or 3D line segments. @@ -181,8 +183,8 @@ def log_line_segments( positions = np.require([], dtype="float32") positions = np.require(positions, dtype="float32") - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if positions is not None: # If not a multiple of 2, drop the last row diff --git a/rerun_py/rerun_sdk/rerun/log/log_decorator.py b/rerun_py/rerun_sdk/rerun/log/log_decorator.py index 0d1db629c5f0..330b018471e2 100644 --- a/rerun_py/rerun_sdk/rerun/log/log_decorator.py +++ b/rerun_py/rerun_sdk/rerun/log/log_decorator.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import logging import traceback diff --git a/rerun_py/rerun_sdk/rerun/log/mesh.py b/rerun_py/rerun_sdk/rerun/log/mesh.py index ccf78f61f51a..d24cf3ad8127 100644 --- a/rerun_py/rerun_sdk/rerun/log/mesh.py +++ b/rerun_py/rerun_sdk/rerun/log/mesh.py @@ -1,13 +1,12 @@ -from typing import Any, Optional, Sequence +from __future__ import annotations + +from typing import Any, Sequence import numpy as np import numpy.typing as npt from rerun import bindings -from rerun.log import ( - Colors, - _normalize_colors, -) +from rerun.log import Colors, _normalize_colors from rerun.log.log_decorator import log_decorator from rerun.recording_stream import RecordingStream @@ -22,12 +21,12 @@ def log_mesh( entity_path: str, positions: Any, *, - indices: Optional[Any] = None, - normals: Optional[Any] = None, - albedo_factor: Optional[Any] = None, - vertex_colors: Optional[Colors] = None, + indices: Any | None = None, + normals: Any | None = None, + albedo_factor: Any | None = None, + vertex_colors: Colors | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a raw 3D mesh by specifying its vertex positions, and optionally indices, normals and albedo factor. @@ -113,12 +112,12 @@ def log_meshes( entity_path: str, position_buffers: Sequence[npt.ArrayLike], *, - vertex_color_buffers: Sequence[Optional[Colors]], - index_buffers: Sequence[Optional[npt.ArrayLike]], - normal_buffers: Sequence[Optional[npt.ArrayLike]], - albedo_factors: Sequence[Optional[npt.ArrayLike]], + vertex_color_buffers: Sequence[Colors | None], + index_buffers: Sequence[npt.ArrayLike | None], + normal_buffers: Sequence[npt.ArrayLike | None], + albedo_factors: Sequence[npt.ArrayLike | None], timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log multiple raw 3D meshes by specifying their different buffers and albedo factors. diff --git a/rerun_py/rerun_sdk/rerun/log/points.py b/rerun_py/rerun_sdk/rerun/log/points.py index cde9ff86c715..c71bdf5bb6af 100644 --- a/rerun_py/rerun_sdk/rerun/log/points.py +++ b/rerun_py/rerun_sdk/rerun/log/points.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Sequence, Union +from __future__ import annotations + +from typing import Any, Sequence import numpy as np import numpy.typing as npt @@ -35,17 +37,17 @@ @log_decorator def log_point( entity_path: str, - position: Optional[npt.ArrayLike] = None, + position: npt.ArrayLike | None = None, *, - radius: Optional[float] = None, - color: Optional[Color] = None, - label: Optional[str] = None, - class_id: Optional[int] = None, - keypoint_id: Optional[int] = None, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + radius: float | None = None, + color: Color | None = None, + label: str | None = None, + class_id: int | None = None, + keypoint_id: int | None = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a 2D or 3D point, with a position and optional color, radii, label, etc. @@ -103,8 +105,8 @@ def log_point( if position is not None: position = np.require(position, dtype="float32") - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if position is not None: if position.size == 2: @@ -147,18 +149,18 @@ def log_point( @log_decorator def log_points( entity_path: str, - positions: Optional[npt.ArrayLike] = None, + positions: npt.ArrayLike | None = None, *, - identifiers: Optional[npt.ArrayLike] = None, - colors: Optional[Union[Color, Colors]] = None, - radii: Optional[npt.ArrayLike] = None, - labels: Optional[Sequence[str]] = None, + identifiers: npt.ArrayLike | None = None, + colors: Color | Colors | None = None, + radii: npt.ArrayLike | None = None, + labels: Sequence[str] | None = None, class_ids: OptionalClassIds = None, keypoint_ids: OptionalKeyPointIds = None, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log 2D or 3D points, with positions and optional colors, radii, labels, etc. diff --git a/rerun_py/rerun_sdk/rerun/log/rects.py b/rerun_py/rerun_sdk/rerun/log/rects.py index 8b3987c8f581..7d6fcce35e57 100644 --- a/rerun_py/rerun_sdk/rerun/log/rects.py +++ b/rerun_py/rerun_sdk/rerun/log/rects.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional, Sequence, Union +from __future__ import annotations + +from typing import Any, Sequence import numpy as np import numpy.typing as npt @@ -10,14 +12,7 @@ from rerun.components.instance import InstanceArray from rerun.components.label import LabelArray from rerun.components.rect2d import Rect2DArray, RectFormat -from rerun.log import ( - Color, - Colors, - OptionalClassIds, - _normalize_colors, - _normalize_ids, - _normalize_labels, -) +from rerun.log import Color, Colors, OptionalClassIds, _normalize_colors, _normalize_ids, _normalize_labels from rerun.log.error_utils import _send_warning from rerun.log.extension_components import _add_extension_components from rerun.log.log_decorator import log_decorator @@ -33,16 +28,16 @@ @log_decorator def log_rect( entity_path: str, - rect: Optional[npt.ArrayLike], + rect: npt.ArrayLike | None, *, rect_format: RectFormat = RectFormat.XYWH, - color: Optional[Color] = None, - label: Optional[str] = None, - class_id: Optional[int] = None, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + color: Color | None = None, + label: str | None = None, + class_id: int | None = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a 2D rectangle. @@ -85,8 +80,8 @@ def log_rect( rects = np.zeros((0, 4), dtype="float32") assert type(rects) is np.ndarray - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} instanced["rerun.rect2d"] = Rect2DArray.from_numpy_and_format(rects, rect_format) @@ -129,17 +124,17 @@ def log_rect( @log_decorator def log_rects( entity_path: str, - rects: Optional[npt.ArrayLike], + rects: npt.ArrayLike | None, *, rect_format: RectFormat = RectFormat.XYWH, - identifiers: Optional[Sequence[int]] = None, - colors: Optional[Union[Color, Colors]] = None, - labels: Optional[Sequence[str]] = None, + identifiers: Sequence[int] | None = None, + colors: Color | Colors | None = None, + labels: Sequence[str] | None = None, class_ids: OptionalClassIds = None, - draw_order: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + draw_order: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log multiple 2D rectangles. diff --git a/rerun_py/rerun_sdk/rerun/log/scalar.py b/rerun_py/rerun_sdk/rerun/log/scalar.py index 74bd5cf11ba0..6e4d9f909d5e 100644 --- a/rerun_py/rerun_sdk/rerun/log/scalar.py +++ b/rerun_py/rerun_sdk/rerun/log/scalar.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Optional +from __future__ import annotations + +from typing import Any import numpy as np @@ -23,12 +25,12 @@ def log_scalar( entity_path: str, scalar: float, *, - label: Optional[str] = None, - color: Optional[Color] = None, - radius: Optional[float] = None, - scattered: Optional[bool] = None, - ext: Optional[Dict[str, Any]] = None, - recording: Optional[RecordingStream] = None, + label: str | None = None, + color: Color | None = None, + radius: float | None = None, + scattered: bool | None = None, + ext: dict[str, Any] | None = None, + recording: RecordingStream | None = None, ) -> None: """ Log a double-precision scalar that will be visualized as a timeseries plot. @@ -120,8 +122,8 @@ def log_scalar( """ recording = RecordingStream.to_native(recording) - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} instanced["rerun.scalar"] = ScalarArray.from_numpy(np.array([scalar])) diff --git a/rerun_py/rerun_sdk/rerun/log/tensor.py b/rerun_py/rerun_sdk/rerun/log/tensor.py index 89f5e9136572..9ea4087d8b11 100644 --- a/rerun_py/rerun_sdk/rerun/log/tensor.py +++ b/rerun_py/rerun_sdk/rerun/log/tensor.py @@ -1,4 +1,6 @@ -from typing import Any, Dict, Iterable, Optional, Protocol, Union +from __future__ import annotations + +from typing import Any, Iterable, Protocol, Union import numpy as np import numpy.typing as npt @@ -45,11 +47,11 @@ def log_tensor( entity_path: str, tensor: npt.ArrayLike, *, - names: Optional[Iterable[Optional[str]]] = None, - meter: Optional[float] = None, - ext: Optional[Dict[str, Any]] = None, + names: Iterable[str | None] | None = None, + meter: float | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log an n-dimensional tensor. @@ -88,13 +90,13 @@ def log_tensor( def _log_tensor( entity_path: str, tensor: npt.NDArray[Any], - draw_order: Optional[float] = None, - names: Optional[Iterable[Optional[str]]] = None, - meter: Optional[float] = None, + draw_order: float | None = None, + names: Iterable[str | None] | None = None, + meter: float | None = None, meaning: bindings.TensorDataMeaning = None, - ext: Optional[Dict[str, Any]] = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """Log a general tensor, perhaps with named dimensions.""" @@ -134,8 +136,8 @@ def _log_tensor( ) return - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} instanced["rerun.tensor"] = TensorArray.from_numpy(tensor, names, meaning, meter) diff --git a/rerun_py/rerun_sdk/rerun/log/text.py b/rerun_py/rerun_sdk/rerun/log/text.py index 83e735102a2f..2cc333ba6240 100644 --- a/rerun_py/rerun_sdk/rerun/log/text.py +++ b/rerun_py/rerun_sdk/rerun/log/text.py @@ -1,7 +1,8 @@ +from __future__ import annotations + import logging -from typing import Any, Dict, Final, Optional +from typing import Any, Final -# Fully qualified to avoid circular import import rerun.log.extension_components from rerun import bindings from rerun.components.color import ColorRGBAArray @@ -12,6 +13,8 @@ from rerun.log.text_internal import LogLevel from rerun.recording_stream import RecordingStream +# Fully qualified to avoid circular import + __all__ = [ "LogLevel", "LoggingHandler", @@ -51,7 +54,7 @@ class LoggingHandler(logging.Handler): logging.DEBUG: LogLevel.DEBUG, } - def __init__(self, root_entity_path: Optional[str] = None): + def __init__(self, root_entity_path: str | None = None): logging.Handler.__init__(self) self.root_entity_path = root_entity_path @@ -72,11 +75,11 @@ def log_text_entry( entity_path: str, text: str, *, - level: Optional[str] = LogLevel.INFO, - color: Optional[Color] = None, - ext: Optional[Dict[str, Any]] = None, + level: str | None = LogLevel.INFO, + color: Color | None = None, + ext: dict[str, Any] | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a text entry, with optional level. @@ -106,8 +109,8 @@ def log_text_entry( recording = RecordingStream.to_native(recording) - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if text: instanced["rerun.text_entry"] = TextEntryArray.from_bodies_and_levels([(text, level)]) diff --git a/rerun_py/rerun_sdk/rerun/log/text_internal.py b/rerun_py/rerun_sdk/rerun/log/text_internal.py index da7ab108eaf1..620bef756671 100644 --- a/rerun_py/rerun_sdk/rerun/log/text_internal.py +++ b/rerun_py/rerun_sdk/rerun/log/text_internal.py @@ -1,8 +1,9 @@ +from __future__ import annotations + import logging from dataclasses import dataclass -from typing import Any, Dict, Final, Optional +from typing import Any, Final -# Fully qualified to avoid circular import from rerun import bindings from rerun.components.color import ColorRGBAArray from rerun.components.instance import InstanceArray @@ -10,6 +11,8 @@ from rerun.log import Color, _normalize_colors from rerun.recording_stream import RecordingStream +# Fully qualified to avoid circular import + __all__ = [ "LogLevel", "log_text_entry_internal", @@ -48,10 +51,10 @@ def log_text_entry_internal( entity_path: str, text: str, *, - level: Optional[str] = LogLevel.INFO, - color: Optional[Color] = None, + level: str | None = LogLevel.INFO, + color: Color | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Internal API to log a text entry, with optional level. @@ -81,8 +84,8 @@ def log_text_entry_internal( """ recording = RecordingStream.to_native(recording) - instanced: Dict[str, Any] = {} - splats: Dict[str, Any] = {} + instanced: dict[str, Any] = {} + splats: dict[str, Any] = {} if text: instanced["rerun.text_entry"] = TextEntryArray.from_bodies_and_levels([(text, level)]) diff --git a/rerun_py/rerun_sdk/rerun/log/transform.py b/rerun_py/rerun_sdk/rerun/log/transform.py index ec9a66ace116..8988f6a9d0ee 100644 --- a/rerun_py/rerun_sdk/rerun/log/transform.py +++ b/rerun_py/rerun_sdk/rerun/log/transform.py @@ -3,7 +3,9 @@ Learn more about transforms [in the manual](https://www.rerun.io/docs/concepts/spaces-and-transforms) """ -from typing import Any, Dict, Optional, Tuple, Union +from __future__ import annotations + +from typing import Any import numpy.typing as npt from deprecated import deprecated @@ -40,9 +42,9 @@ def log_view_coordinates( *, xyz: str = "", up: str = "", - right_handed: Optional[bool] = None, + right_handed: bool | None = None, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log the view coordinates for an entity. @@ -131,7 +133,7 @@ def log_view_coordinates( def log_unknown_transform( entity_path: str, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log that this entity is NOT in the same space as the parent, but you do not (yet) know how they relate. @@ -151,7 +153,7 @@ def log_unknown_transform( """ recording = RecordingStream.to_native(recording) - instanced: Dict[str, Any] = {} + instanced: dict[str, Any] = {} instanced["rerun.disconnected_transform"] = DisconnectedSpaceArray.single() bindings.log_arrow_msg(entity_path, components=instanced, timeless=timeless, recording=recording) @@ -160,7 +162,7 @@ def log_unknown_transform( def log_disconnected_space( entity_path: str, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log that this entity is NOT in the same space as the parent. @@ -183,7 +185,7 @@ def log_disconnected_space( """ recording = RecordingStream.to_native(recording) - instanced: Dict[str, Any] = {} + instanced: dict[str, Any] = {} instanced["rerun.disconnected_transform"] = DisconnectedSpaceArray.single() bindings.log_arrow_msg(entity_path, components=instanced, timeless=timeless, recording=recording) @@ -191,19 +193,19 @@ def log_disconnected_space( @log_decorator def log_transform3d( entity_path: str, - transform: Union[ - TranslationAndMat3, - TranslationRotationScale3D, - RotationAxisAngle, - Translation3D, - Scale3D, - Quaternion, - Rigid3D, - ], + transform: ( + TranslationAndMat3 + | TranslationRotationScale3D + | RotationAxisAngle + | Translation3D + | Scale3D + | Quaternion + | Rigid3D + ), *, from_parent: bool = False, timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log an (affine) 3D transform between this entity and the parent. @@ -288,11 +290,11 @@ def log_transform3d( def log_rigid3( entity_path: str, *, - parent_from_child: Optional[Tuple[npt.ArrayLike, npt.ArrayLike]] = None, - child_from_parent: Optional[Tuple[npt.ArrayLike, npt.ArrayLike]] = None, + parent_from_child: tuple[npt.ArrayLike, npt.ArrayLike] | None = None, + child_from_parent: tuple[npt.ArrayLike, npt.ArrayLike] | None = None, xyz: str = "", timeless: bool = False, - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> None: """ Log a proper rigid 3D transform between this entity and the parent. diff --git a/rerun_py/rerun_sdk/rerun/recording.py b/rerun_py/rerun_sdk/rerun/recording.py index 717739c0b330..5ff52055f38b 100644 --- a/rerun_py/rerun_sdk/rerun/recording.py +++ b/rerun_py/rerun_sdk/rerun/recording.py @@ -1,10 +1,11 @@ """Helper functions for directly working with recordings.""" +from __future__ import annotations import base64 import logging import random import string -from typing import Any, Optional +from typing import Any from rerun import bindings @@ -29,9 +30,9 @@ def as_html( self, width: int = DEFAULT_WIDTH, height: int = DEFAULT_HEIGHT, - app_url: Optional[str] = None, + app_url: str | None = None, timeout_ms: int = DEFAULT_TIMEOUT, - other: Optional["MemoryRecording"] = None, + other: MemoryRecording | None = None, ) -> str: """ Generate an HTML snippet that displays the recording in an IFrame. @@ -106,10 +107,10 @@ def as_html( def show( self, - other: Optional["MemoryRecording"] = None, + other: MemoryRecording | None = None, width: int = DEFAULT_WIDTH, height: int = DEFAULT_HEIGHT, - app_url: Optional[str] = None, + app_url: str | None = None, timeout_ms: int = DEFAULT_TIMEOUT, ) -> Any: """ diff --git a/rerun_py/rerun_sdk/rerun/recording_stream.py b/rerun_py/rerun_sdk/rerun/recording_stream.py index bb769496dc47..fa731ce34c6e 100644 --- a/rerun_py/rerun_sdk/rerun/recording_stream.py +++ b/rerun_py/rerun_sdk/rerun/recording_stream.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations from rerun import bindings @@ -67,7 +67,7 @@ class RecordingStream: def __init__(self, inner: bindings.PyRecordingStream) -> None: self.inner = inner - self._prev: Optional["RecordingStream"] = None + self._prev: RecordingStream | None = None def __enter__(self): # type: ignore[no-untyped-def] self._prev = set_thread_local_data_recording(self) @@ -77,7 +77,7 @@ def __exit__(self, type, value, traceback): # type: ignore[no-untyped-def] self._prev = set_thread_local_data_recording(self._prev) # type: ignore[arg-type] # NOTE: The type is a string because we cannot reference `RecordingStream` yet at this point. - def to_native(self: Optional["RecordingStream"]) -> Optional[bindings.PyRecordingStream]: + def to_native(self: RecordingStream | None) -> bindings.PyRecordingStream | None: return self.inner if self is not None else None def __del__(self): # type: ignore[no-untyped-def] @@ -115,7 +115,7 @@ def wrapper(self, *args: Any, **kwargs: Any) -> Any: # type: ignore[no-untyped- def is_enabled( - recording: Optional[RecordingStream] = None, + recording: RecordingStream | None = None, ) -> bool: """ Is this Rerun recording enabled. @@ -131,8 +131,8 @@ def is_enabled( def get_application_id( - recording: Optional[RecordingStream] = None, -) -> Optional[str]: + recording: RecordingStream | None = None, +) -> str | None: """ Get the application ID that this recording is associated with, if any. @@ -154,8 +154,8 @@ def get_application_id( def get_recording_id( - recording: Optional[RecordingStream] = None, -) -> Optional[str]: + recording: RecordingStream | None = None, +) -> str | None: """ Get the recording ID that this recording is logging to, as a UUIDv4, if any. @@ -191,8 +191,8 @@ def get_recording_id( def get_data_recording( - recording: Optional[RecordingStream] = None, -) -> Optional[RecordingStream]: + recording: RecordingStream | None = None, +) -> RecordingStream | None: """ Returns the most appropriate recording to log data to, in the current context, if any. @@ -217,7 +217,7 @@ def get_data_recording( return RecordingStream(result) if result is not None else None -def get_global_data_recording() -> Optional[RecordingStream]: +def get_global_data_recording() -> RecordingStream | None: """ Returns the currently active global recording, if any. @@ -230,7 +230,7 @@ def get_global_data_recording() -> Optional[RecordingStream]: return RecordingStream(result) if result is not None else None -def set_global_data_recording(recording: RecordingStream) -> Optional[RecordingStream]: +def set_global_data_recording(recording: RecordingStream) -> RecordingStream | None: """ Replaces the currently active global recording with the specified one. @@ -243,7 +243,7 @@ def set_global_data_recording(recording: RecordingStream) -> Optional[RecordingS return RecordingStream(result) if result is not None else None -def get_thread_local_data_recording() -> Optional[RecordingStream]: +def get_thread_local_data_recording() -> RecordingStream | None: """ Returns the currently active thread-local recording, if any. @@ -256,7 +256,7 @@ def get_thread_local_data_recording() -> Optional[RecordingStream]: return RecordingStream(result) if result is not None else None -def set_thread_local_data_recording(recording: RecordingStream) -> Optional[RecordingStream]: +def set_thread_local_data_recording(recording: RecordingStream) -> RecordingStream | None: """ Replaces the currently active thread-local recording with the specified one. diff --git a/rerun_py/rerun_sdk/rerun/script_helpers.py b/rerun_py/rerun_sdk/rerun/script_helpers.py index b8cbdbf1b443..253963de8647 100644 --- a/rerun_py/rerun_sdk/rerun/script_helpers.py +++ b/rerun_py/rerun_sdk/rerun/script_helpers.py @@ -18,6 +18,8 @@ ``` """ +from __future__ import annotations + from argparse import ArgumentParser, Namespace import rerun as rr diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index ad854e38d1ac..c00ad0fc53f6 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -1,5 +1,6 @@ +from __future__ import annotations + import logging -from typing import Optional import rerun_bindings as bindings # type: ignore[attr-defined] @@ -9,7 +10,7 @@ # --- Sinks --- -def connect(addr: Optional[str] = None, recording: Optional[RecordingStream] = None) -> None: +def connect(addr: str | None = None, recording: RecordingStream | None = None) -> None: """ Connect to a remote Rerun Viewer on the given ip:port. @@ -34,7 +35,7 @@ def connect(addr: Optional[str] = None, recording: Optional[RecordingStream] = N _connect = connect # we need this because Python scoping is horrible -def save(path: str, recording: Optional[RecordingStream] = None) -> None: +def save(path: str, recording: RecordingStream | None = None) -> None: """ Stream all log-data to a file. @@ -57,7 +58,7 @@ def save(path: str, recording: Optional[RecordingStream] = None) -> None: bindings.save(path=path, recording=recording) -def disconnect(recording: Optional[RecordingStream] = None) -> None: +def disconnect(recording: RecordingStream | None = None) -> None: """ Closes all TCP connections, servers, and files. @@ -77,7 +78,7 @@ def disconnect(recording: Optional[RecordingStream] = None) -> None: bindings.disconnect(recording=recording) -def memory_recording(recording: Optional[RecordingStream] = None) -> MemoryRecording: +def memory_recording(recording: RecordingStream | None = None) -> MemoryRecording: """ Streams all log-data to a memory buffer. @@ -103,9 +104,9 @@ def memory_recording(recording: Optional[RecordingStream] = None) -> MemoryRecor def serve( open_browser: bool = True, - web_port: Optional[int] = None, - ws_port: Optional[int] = None, - recording: Optional[RecordingStream] = None, + web_port: int | None = None, + ws_port: int | None = None, + recording: RecordingStream | None = None, ) -> None: """ Serve log-data over WebSockets and serve a Rerun web viewer over HTTP. @@ -134,7 +135,7 @@ def serve( bindings.serve(open_browser, web_port, ws_port, recording=recording) -def spawn(port: int = 9876, connect: bool = True, recording: Optional[RecordingStream] = None) -> None: +def spawn(port: int = 9876, connect: bool = True, recording: RecordingStream | None = None) -> None: """ Spawn a Rerun Viewer, listening on the given port. diff --git a/rerun_py/rerun_sdk/rerun/time.py b/rerun_py/rerun_sdk/rerun/time.py index 4c2370d3581a..9aa6a57d2a3e 100644 --- a/rerun_py/rerun_sdk/rerun/time.py +++ b/rerun_py/rerun_sdk/rerun/time.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations import rerun_bindings as bindings # type: ignore[attr-defined] @@ -7,7 +7,7 @@ # --- Time --- -def set_time_sequence(timeline: str, sequence: Optional[int], recording: Optional[RecordingStream] = None) -> None: +def set_time_sequence(timeline: str, sequence: int | None, recording: RecordingStream | None = None) -> None: """ Set the current time for this thread as an integer sequence. @@ -36,7 +36,7 @@ def set_time_sequence(timeline: str, sequence: Optional[int], recording: Optiona bindings.set_time_sequence(timeline, sequence, recording=recording) -def set_time_seconds(timeline: str, seconds: Optional[float], recording: Optional[RecordingStream] = None) -> None: +def set_time_seconds(timeline: str, seconds: float | None, recording: RecordingStream | None = None) -> None: """ Set the current time for this thread in seconds. @@ -73,7 +73,7 @@ def set_time_seconds(timeline: str, seconds: Optional[float], recording: Optiona bindings.set_time_seconds(timeline, seconds, recording=recording) -def set_time_nanos(timeline: str, nanos: Optional[int], recording: Optional[RecordingStream] = None) -> None: +def set_time_nanos(timeline: str, nanos: int | None, recording: RecordingStream | None = None) -> None: """ Set the current time for this thread. @@ -111,7 +111,7 @@ def set_time_nanos(timeline: str, nanos: Optional[int], recording: Optional[Reco bindings.set_time_nanos(timeline, nanos, recording=recording) -def reset_time(recording: Optional[RecordingStream] = None) -> None: +def reset_time(recording: RecordingStream | None = None) -> None: """ Clear all timeline information on this thread. diff --git a/rerun_py/rerun_sdk/rerun_demo/__init__.py b/rerun_py/rerun_sdk/rerun_demo/__init__.py index 9f07b733fc92..64e1b3805f76 100644 --- a/rerun_py/rerun_sdk/rerun_demo/__init__.py +++ b/rerun_py/rerun_sdk/rerun_demo/__init__.py @@ -21,4 +21,6 @@ cannot carry any dependencies beyond those of rerun itself. This generally limits demos to only using the standard library and numpy for data generation. """ +from __future__ import annotations + __all__ = ["data", "turbo", "util"] diff --git a/rerun_py/rerun_sdk/rerun_demo/__main__.py b/rerun_py/rerun_sdk/rerun_demo/__main__.py index dcb58f23d1ef..72ba5a54d28b 100644 --- a/rerun_py/rerun_sdk/rerun_demo/__main__.py +++ b/rerun_py/rerun_sdk/rerun_demo/__main__.py @@ -1,4 +1,5 @@ """Demo program which loads an rrd file built into the package.""" +from __future__ import annotations import argparse import pathlib @@ -46,7 +47,7 @@ def run_colmap(args): rrd_file = pathlib.Path(__file__).parent.joinpath("colmap_fiat.rrd").resolve() if not rrd_file.exists(): - print("No demo file found at {}. Package was built without demo support".format(rrd_file), file=sys.stderr) + print(f"No demo file found at {rrd_file}. Package was built without demo support", file=sys.stderr) exit(1) else: exit(bindings.main([sys.argv[0], str(rrd_file)] + serve_opts)) diff --git a/rerun_py/rerun_sdk/rerun_demo/data.py b/rerun_py/rerun_sdk/rerun_demo/data.py index 24d6ec894e2b..20c7c5f90332 100644 --- a/rerun_py/rerun_sdk/rerun_demo/data.py +++ b/rerun_py/rerun_sdk/rerun_demo/data.py @@ -1,4 +1,5 @@ """Simple data to be used for Rerun demos.""" +from __future__ import annotations from collections import namedtuple from math import cos, sin, tau diff --git a/rerun_py/rerun_sdk/rerun_demo/turbo.py b/rerun_py/rerun_sdk/rerun_demo/turbo.py index 9e454e8b2194..cc77461ca838 100644 --- a/rerun_py/rerun_sdk/rerun_demo/turbo.py +++ b/rerun_py/rerun_sdk/rerun_demo/turbo.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np turbo_colormap_data = np.array( diff --git a/rerun_py/rerun_sdk/rerun_demo/util.py b/rerun_py/rerun_sdk/rerun_demo/util.py index 76496e1a4135..03f5172ddecb 100644 --- a/rerun_py/rerun_sdk/rerun_demo/util.py +++ b/rerun_py/rerun_sdk/rerun_demo/util.py @@ -1,4 +1,5 @@ """Simpe utilities to be used for Rerun demos.""" +from __future__ import annotations import numpy as np diff --git a/scripts/fetch_crashes.py b/scripts/fetch_crashes.py index 66b608056b7c..06faae1aae11 100755 --- a/scripts/fetch_crashes.py +++ b/scripts/fetch_crashes.py @@ -20,6 +20,7 @@ ``` python scripts/fetch_crashes.py --help ``` + """ import argparse @@ -125,7 +126,7 @@ def count_uniques(backtrace): - return len(set([prop["user_id"] for prop in backtrace[1]])) + return len({prop["user_id"] for prop in backtrace[1]}) backtraces = list(backtraces.items()) @@ -140,13 +141,13 @@ def count_uniques(backtrace): signal = props[0].get("signal") title = file_line if file_line is not None else signal - timestamps = sorted(list(set([prop["timestamp"] for prop in props]))) + timestamps = sorted(list({prop["timestamp"] for prop in props})) first_occurrence = timestamps[0] last_occurrence = timestamps[-1] - targets = sorted(list(set([prop["target"] for prop in props]))) - rust_versions = sorted(list(set([prop["rust_version"] for prop in props]))) - rerun_versions = sorted(list(set([prop["rerun_version"] for prop in props]))) + targets = sorted(list({prop["target"] for prop in props})) + rust_versions = sorted(list({prop["rust_version"] for prop in props})) + rerun_versions = sorted(list({prop["rerun_version"] for prop in props})) print( f"## {n} distinct user(s) affected by {event} crash @ `{title}`\n" diff --git a/scripts/generate_changelog.py b/scripts/generate_changelog.py index a4aea1b2bd48..e1a5ab0c3b3b 100755 --- a/scripts/generate_changelog.py +++ b/scripts/generate_changelog.py @@ -55,7 +55,7 @@ def get_github_token() -> str: token_file = os.path.join(home_dir, ".githubtoken") try: - with open(token_file, "r") as f: + with open(token_file) as f: token = f.read().strip() return token except Exception: diff --git a/scripts/generate_pr_summary.py b/scripts/generate_pr_summary.py index 9cf3025b9187..8d8d5180968b 100644 --- a/scripts/generate_pr_summary.py +++ b/scripts/generate_pr_summary.py @@ -38,34 +38,34 @@ def generate_pr_summary(github_token: str, github_repository: str, pr_number: in for commit in all_commits: commit_short = commit[:7] - print("Checking commit: {}...".format(commit_short)) + print(f"Checking commit: {commit_short}...") found: Dict[str, Any] = {} # Check if there is a hosted app for the current commit app_blob = viewer_bucket.blob(f"commit/{commit_short}/index.html") if app_blob.exists(): - print("Found web assets commit: {}".format(commit_short)) + print(f"Found web assets commit: {commit_short}") found["hosted_app"] = f"https://app.rerun.io/commit/{commit_short}" # Check if there are benchmark results bench_blob = builds_bucket.blob(f"commit/{commit_short}/bench_results.txt") if bench_blob.exists(): - print("Found benchmark results: {}".format(commit_short)) + print(f"Found benchmark results: {commit_short}") found["bench_results"] = f"https://build.rerun.io/{bench_blob.name}" # Check if there are notebook results notebook_blobs = list(builds_bucket.list_blobs(prefix=f"commit/{commit_short}/notebooks")) notebooks = [f"https://build.rerun.io/{blob.name}" for blob in notebook_blobs if blob.name.endswith(".html")] if notebooks: - print("Found notebooks for commit: {}".format(commit_short)) + print(f"Found notebooks for commit: {commit_short}") found["notebooks"] = notebooks # Get the wheel files for the commit wheel_blobs = list(builds_bucket.list_blobs(prefix=f"commit/{commit_short}/wheels")) wheels = [f"https://build.rerun.io/{blob.name}" for blob in wheel_blobs if blob.name.endswith(".whl")] if wheels: - print("Found wheels for commit: {}".format(commit_short)) + print(f"Found wheels for commit: {commit_short}") found["wheels"] = wheels if found: @@ -83,7 +83,7 @@ def generate_pr_summary(github_token: str, github_repository: str, pr_number: in if upload: upload_blob = builds_bucket.blob(f"pull_request/{pr_number}/index.html") - print("Uploading results to {}".format(upload_blob.name)) + print(f"Uploading results to {upload_blob.name}") upload_blob.upload_from_file(buffer, content_type="text/html") # If there's a {{ pr-build-summary }} string in the PR description, replace it with a link to the summary page. diff --git a/scripts/generate_prerelease_pip_index.py b/scripts/generate_prerelease_pip_index.py index 64dee36e358e..67ce20649942 100644 --- a/scripts/generate_prerelease_pip_index.py +++ b/scripts/generate_prerelease_pip_index.py @@ -28,7 +28,7 @@ def generate_pip_index(commit: str, upload: bool) -> None: wheels_bucket = gcs_client.bucket("rerun-builds") commit_short = commit[:7] - print("Checking commit: {}...".format(commit_short)) + print(f"Checking commit: {commit_short}...") found: Dict[str, Any] = {} @@ -36,7 +36,7 @@ def generate_pip_index(commit: str, upload: bool) -> None: wheel_blobs = list(wheels_bucket.list_blobs(prefix=f"commit/{commit_short}/wheels")) wheels = [blob.name.split("/")[-1] for blob in wheel_blobs if blob.name.endswith(".whl")] if wheels: - print("Found wheels for commit: {}: {}".format(commit_short, wheels)) + print(f"Found wheels for commit: {commit_short}: {wheels}") found["wheels"] = wheels if found: @@ -54,7 +54,7 @@ def generate_pip_index(commit: str, upload: bool) -> None: if upload: upload_blob = wheels_bucket.blob(f"commit/{commit_short}/wheels/index.html") - print("Uploading results to {}".format(upload_blob.name)) + print(f"Uploading results to {upload_blob.name}") upload_blob.upload_from_file(buffer, content_type="text/html") diff --git a/scripts/version_util.py b/scripts/version_util.py index e694f24c0b80..514b2ac1f1b6 100755 --- a/scripts/version_util.py +++ b/scripts/version_util.py @@ -62,7 +62,7 @@ def main() -> None: if len(sys.argv) != 2: raise Exception("Invalid number of arguments") - with open("Cargo.toml", "r") as f: + with open("Cargo.toml") as f: cargo_toml = f.read() cargo_version = get_cargo_version(cargo_toml)