Skip to content

Commit

Permalink
Codegen/IDL 5: auto-generated Python code for Points2D (#2374)
Browse files Browse the repository at this point in the history
The auto-generated Python code, and nothing else.

Hand written tests and extensions (including the actual body of the
mixins!) will make an appearance in follow-up PRs.

---

Codegen/IDL PR series:
- #2362
- #2363
- #2369
- #2370 
- #2374 
- #2375 
- #2410
- #2432

---------

Co-authored-by: Andreas Reich <[email protected]>
  • Loading branch information
teh-cmc and Wumpf authored Jun 14, 2023
1 parent 35449d8 commit 1d7cf3f
Show file tree
Hide file tree
Showing 19 changed files with 908 additions and 6 deletions.
1 change: 1 addition & 0 deletions crates/re_types/definitions/rerun/archetypes/points2d.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace rerun.archetypes;
// TODO(#2371): archetype IDL definitions must always be tables
// TODO(#2372): archetype IDL definitions must refer to objects of kind component
// TODO(#2373): `attr.rerun.component_required` implies `required`
// TODO(#2427): distinguish optional vs. recommended in language backends

/// A 2D point cloud with positions and optional colors, radii, labels, etc.
table Points2D (
Expand Down
2 changes: 1 addition & 1 deletion crates/re_types/source_hash.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This is a sha256 hash for all direct and indirect dependencies of this crate's build script.
# It can be safely removed at anytime to force the build script to run again.
# Check out build.rs to see how it's computed.
95c13226f31d47e4639e155fc80ee6830579c50e38ee1d997b4bda4d23ba03b6
95c13226f31d47e4639e155fc80ee6830579c50e38ee1d997b4bda4d23ba03b6
9 changes: 5 additions & 4 deletions crates/re_types_builder/src/codegen/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ impl QuotedObject {
if obj.kind == ObjectKind::Archetype {
code.push_text(quote_builder_from_obj(objects, obj), 1, 4);
} else {
code.push_text(quote_aliases_from_object(obj), 1, 4);
code.push_text(quote_aliases_from_object(obj), 1, 0);
}

code.push_text(quote_arrow_support_from_obj(arrow_registry, obj), 1, 4);
code.push_text(quote_arrow_support_from_obj(arrow_registry, obj), 1, 0);

let mut filepath = PathBuf::from(filepath);
filepath.set_extension("py");
Expand Down Expand Up @@ -402,8 +402,9 @@ impl QuotedObject {
code.push_text(quote_str_repr_from_obj(obj), 1, 4);
code.push_text(quote_array_method_from_obj(objects, obj), 1, 4);
code.push_text(quote_str_method_from_obj(objects, obj), 1, 4);
code.push_text(quote_aliases_from_object(obj), 1, 4);
code.push_text(quote_arrow_support_from_obj(arrow_registry, obj), 1, 4);

code.push_text(quote_aliases_from_object(obj), 1, 0);
code.push_text(quote_arrow_support_from_obj(arrow_registry, obj), 1, 0);

let mut filepath = PathBuf::from(filepath);
filepath.set_extension("py");
Expand Down
6 changes: 5 additions & 1 deletion rerun_py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,8 @@ required-imports = ["from __future__ import annotations"]
# See https://github.com/rerun-io/rerun/pull/1085 for more details
include = ["rerun_sdk.pth", "rerun_sdk/rerun_demo/colmap_fiat.rrd"]
locked = true
python-packages = ["rerun_sdk/rerun", "rerun_sdk/rerun_demo"]
python-packages = [
"rerun_sdk/rerun",
"rerun_sdk/rerun2",
"rerun_sdk/rerun_demo",
]
26 changes: 26 additions & 0 deletions rerun_py/rerun2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
A shim necessary to make maturin dev builds work properly.
Our maturin builds stick our package inside of a "rerun_sdk" folder
to avoid conflicting with the non-rerun "rerun" package. In released
builds, we include a rerun_sdk.pth file that makes things work properly,
but that doesn't work in dev builds where maturin generates its own
.pth file that points 1 level too high.
When we encounter this file on import, we instead redirect to the
real rerun module by adding it to the path and then, and then
replacing our own module content with it.
"""
from __future__ import annotations

import pathlib
import sys

real_path = pathlib.Path(__file__).parent.parent.joinpath("rerun_sdk").resolve()

print(f"DEV ENVIRONMENT DETECTED! Re-importing rerun2 from: {real_path}", file=sys.stderr)

sys.path.insert(0, str(real_path))

del sys.modules["rerun2"]
sys.modules["rerun2"] = __import__("rerun2")
7 changes: 7 additions & 0 deletions rerun_py/rerun_sdk/rerun2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# NOTE: This file was autogenerated by re_types_builder; DO NOT EDIT.

from __future__ import annotations

__all__ = ["Points2D"]

from rerun2.archetypes import Points2D
8 changes: 8 additions & 0 deletions rerun_py/rerun_sdk/rerun2/archetypes/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# NOTE: This file was autogenerated by re_types_builder; DO NOT EDIT.

from __future__ import annotations

__all__ = ["Points2D"]

# NOTE: we use fully qualified paths to prevent lazy circular imports.
from rerun2.archetypes.points2d import Points2D
115 changes: 115 additions & 0 deletions rerun_py/rerun_sdk/rerun2/archetypes/points2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# NOTE: This file was autogenerated by re_types_builder; DO NOT EDIT.

from __future__ import annotations

__all__ = ["Points2D"]


from dataclasses import dataclass

from rerun2 import components


@dataclass
class Points2D:
"""A 2D point cloud with positions and optional colors, radii, labels, etc."""

points: components.Point2DArray
"""
All the actual 2D points that make up the point cloud.
"""

radii: components.RadiusArray | None = None
"""
Optional radii for the points, effectively turning them into circles.
"""

colors: components.ColorArray | None = None
"""
Optional colors for the points.
The colors are interpreted as RGB or RGBA in sRGB gamma-space,
As either 0-1 floats or 0-255 integers, with separate alpha.
"""

labels: components.LabelArray | None = None
"""
Optional text labels for the points.
"""

draw_order: components.DrawOrderArray | None = None
"""
An optional floating point value that specifies the 2D drawing order.
Objects with higher values are drawn on top of those with lower values.
The default for 2D points is 30.0.
"""

class_ids: components.ClassIdArray | None = None
"""
Optional class Ids for the points.
The class ID provides colors and labels if not specified explicitly.
"""

keypoint_ids: components.KeypointIdArray | None = None
"""
Optional keypoint IDs for the points, identifying them within a class.
If keypoint IDs are passed in but no class IDs were specified, the class ID will
default to 0.
This is useful to identify points within a single classification (which is identified
with `class_id`).
E.g. the classification might be 'Person' and the keypoints refer to joints on a
detected skeleton.
"""

instance_keys: components.InstanceKeyArray | None = None
"""
Unique identifiers for each individual point in the batch.
"""

def __str__(self):
s = f"rr.{type(self).__name__}(\n"

from dataclasses import fields

for field in fields(self):
data = getattr(self, field.name)
datatype = getattr(data, "type", None)
if datatype:
name = datatype.extension_name
typ = datatype.storage_type
s += f" {name}<{typ}>(\n {data.to_pylist()}\n )\n"

s += ")"

return s

def __repr__(self):
return str(self)

def __init__(
self,
points: components.Point2DArrayLike,
*,
radii: components.RadiusArrayLike | None = None,
colors: components.ColorArrayLike | None = None,
labels: components.LabelArrayLike | None = None,
draw_order: components.DrawOrderLike | None = None,
class_ids: components.ClassIdArrayLike | None = None,
keypoint_ids: components.KeypointIdArrayLike | None = None,
instance_keys: components.InstanceKeyArrayLike | None = None,
) -> None:
# Required components
self.points = components.Point2DArray.from_similar(points)

# Optional components

self.radii = components.RadiusArray.from_similar(radii)
self.colors = components.ColorArray.from_similar(colors)
self.labels = components.LabelArray.from_similar(labels)
self.draw_order = components.DrawOrderArray.from_similar(draw_order)
self.class_ids = components.ClassIdArray.from_similar(class_ids)
self.keypoint_ids = components.KeypointIdArray.from_similar(keypoint_ids)
self.instance_keys = components.InstanceKeyArray.from_similar(instance_keys)
68 changes: 68 additions & 0 deletions rerun_py/rerun_sdk/rerun2/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# NOTE: This file was autogenerated by re_types_builder; DO NOT EDIT.

from __future__ import annotations

__all__ = [
"ClassId",
"ClassIdArray",
"ClassIdArrayLike",
"ClassIdLike",
"ClassIdType",
"Color",
"ColorArray",
"ColorArrayLike",
"ColorLike",
"ColorType",
"DrawOrder",
"DrawOrderArray",
"DrawOrderArrayLike",
"DrawOrderLike",
"DrawOrderType",
"InstanceKey",
"InstanceKeyArray",
"InstanceKeyArrayLike",
"InstanceKeyLike",
"InstanceKeyType",
"KeypointId",
"KeypointIdArray",
"KeypointIdArrayLike",
"KeypointIdLike",
"KeypointIdType",
"Label",
"LabelArray",
"LabelArrayLike",
"LabelLike",
"LabelType",
"Point2D",
"Point2DArray",
"Point2DArrayLike",
"Point2DLike",
"Point2DType",
"Radius",
"RadiusArray",
"RadiusArrayLike",
"RadiusLike",
"RadiusType",
]

# NOTE: we use fully qualified paths to prevent lazy circular imports.
from rerun2.components.class_id import ClassId, ClassIdArray, ClassIdArrayLike, ClassIdLike, ClassIdType
from rerun2.components.color import Color, ColorArray, ColorArrayLike, ColorLike, ColorType
from rerun2.components.draw_order import DrawOrder, DrawOrderArray, DrawOrderArrayLike, DrawOrderLike, DrawOrderType
from rerun2.components.instance_key import (
InstanceKey,
InstanceKeyArray,
InstanceKeyArrayLike,
InstanceKeyLike,
InstanceKeyType,
)
from rerun2.components.keypoint_id import (
KeypointId,
KeypointIdArray,
KeypointIdArrayLike,
KeypointIdLike,
KeypointIdType,
)
from rerun2.components.label import Label, LabelArray, LabelArrayLike, LabelLike, LabelType
from rerun2.components.point2d import Point2D, Point2DArray, Point2DArrayLike, Point2DLike, Point2DType
from rerun2.components.radius import Radius, RadiusArray, RadiusArrayLike, RadiusLike, RadiusType
72 changes: 72 additions & 0 deletions rerun_py/rerun_sdk/rerun2/components/class_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# NOTE: This file was autogenerated by re_types_builder; DO NOT EDIT.

from __future__ import annotations

__all__ = ["ClassId", "ClassIdArray", "ClassIdArrayLike", "ClassIdLike", "ClassIdType"]

from dataclasses import dataclass
from typing import Any, Sequence, Union

import numpy as np
import numpy.typing as npt
import pyarrow as pa


@dataclass
class ClassId:
"""A 16-bit ID representing a type of semantic class."""

id: int

def __array__(self):
return np.asarray(self.id)


ClassIdLike = Union[ClassId, float]

ClassIdArrayLike = Union[
ClassIdLike, Sequence[ClassIdLike], npt.NDArray[np.uint8], npt.NDArray[np.uint16], npt.NDArray[np.uint32]
]


# --- Arrow support ---

from rerun2.components.class_id_ext import ClassIdArrayExt # noqa: E402


class ClassIdType(pa.ExtensionType):
def __init__(self: type[pa.ExtensionType]) -> None:
pa.ExtensionType.__init__(self, pa.uint16(), "rerun.components.ClassId")

def __arrow_ext_serialize__(self: type[pa.ExtensionType]) -> bytes:
# since we don't have a parameterized type, we don't need extra metadata to be deserialized
return b""

@classmethod
def __arrow_ext_deserialize__(
cls: type[pa.ExtensionType], storage_type: Any, serialized: Any
) -> type[pa.ExtensionType]:
# return an instance of this subclass given the serialized metadata.
return ClassIdType()

def __arrow_ext_class__(self: type[pa.ExtensionType]) -> type[pa.ExtensionArray]:
return ClassIdArray


pa.register_extension_type(ClassIdType())


class ClassIdArray(pa.ExtensionArray, ClassIdArrayExt): # type: ignore[misc]
@staticmethod
def from_similar(data: ClassIdArrayLike | None):
if data is None:
return ClassIdType().wrap_array(pa.array([], type=ClassIdType().storage_type))
else:
return ClassIdArrayExt._from_similar(
data,
mono=ClassId,
mono_aliases=ClassIdLike,
many=ClassIdArray,
many_aliases=ClassIdArrayLike,
arrow=ClassIdType,
)
Loading

0 comments on commit 1d7cf3f

Please sign in to comment.