Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codegen/IDL 5: auto-generated Python code for Points2D #2374

Merged
merged 37 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b44c087
more build tools
teh-cmc Jun 11, 2023
6bb6b2b
self-review
teh-cmc Jun 11, 2023
40483d7
addressing PR comments
teh-cmc Jun 13, 2023
aa918bd
introduce re_types_builder
teh-cmc Jun 11, 2023
3f6f388
generate reflection code
teh-cmc Jun 11, 2023
262597a
unindent 0.1 everywhere
teh-cmc Jun 11, 2023
61ceeba
self-review
teh-cmc Jun 11, 2023
e67d12a
adhering to py38+ style guide
teh-cmc Jun 12, 2023
c95a659
vscode flatbuffer things. Fix comment typo
Wumpf Jun 12, 2023
6fe324e
turn the inner from_similar into _from_similar to appease linters
teh-cmc Jun 13, 2023
796c7ea
generate __all__ everywhere to make python tools behave
teh-cmc Jun 13, 2023
7f086dd
make sure __all__ manifests are lexically sorted
teh-cmc Jun 13, 2023
3ddb05d
adressing PR comments
teh-cmc Jun 14, 2023
edb7ec8
introduce re_types
teh-cmc Jun 11, 2023
2c0621e
self-review
teh-cmc Jun 11, 2023
9e1f6fd
python shall output to rerun_py/rerun_sdk/rerun2
teh-cmc Jun 12, 2023
dc1336a
addressing PR comments
teh-cmc Jun 14, 2023
e4e24a2
Rerun attributes' definitions
teh-cmc Jun 11, 2023
0c608d1
Rerun datatypes' definitions
teh-cmc Jun 11, 2023
a0f7d9c
Rerun components' definitions
teh-cmc Jun 11, 2023
24f5124
Rerun archetypes' definitions
teh-cmc Jun 11, 2023
974f735
fixing typo in re_types_builder doc
teh-cmc Jun 11, 2023
33fed4f
self-review
teh-cmc Jun 11, 2023
67c37f8
fix DrawOrder missing PartialEq & PartialOrd
teh-cmc Jun 12, 2023
aa2d5c0
addressing PR comments
teh-cmc Jun 14, 2023
77b06f4
fixing typo in re_types_builder doc
teh-cmc Jun 11, 2023
7f8d182
autogenerated python code
teh-cmc Jun 11, 2023
eaa57a4
freshly autogenerated python code for new py38+ style guide
teh-cmc Jun 12, 2023
5e3c2f5
python shall go into rerun_py/rerun_sdk/rerun2
teh-cmc Jun 12, 2023
06062e3
setting up pyproject and runtime redirections apropriately
teh-cmc Jun 12, 2023
2917bc1
regen after rebase
teh-cmc Jun 13, 2023
78098c0
regen post rebase
teh-cmc Jun 13, 2023
b6711ad
addressing PR comments
teh-cmc Jun 14, 2023
9c98dfb
force regen this so the PR train makes sense
teh-cmc Jun 14, 2023
08a412f
fixed wrong indent in python codegen
teh-cmc Jun 14, 2023
29d3de8
left a dbg didnt i
teh-cmc Jun 14, 2023
3c6bb40
broke git
teh-cmc Jun 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the top level file not specify all exposed components and archetypes as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's pretty good the way it is now.

Keep in mind:

  1. Components can have the same name as archetypes (we probably will not do that, but nothing prevent users from doing so)
  2. In python, users very rarely care about components (pretty much never in fact), and even less so about datatypes


# 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.
teh-cmc marked this conversation as resolved.
Show resolved Hide resolved

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Don't think in python anything is preventing us to call this type

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure but I already have enough issues with python as it is, I don't really feel like shadowing keywords...

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)
Comment on lines +109 to +110
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not wrong but those two were under "recommended" components, so it's a bit confusing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I mean, backends are free to do whatever they want with that information; in this case I didn't bother coming up with anything better than just ignoring it, for now.

I'll open an issue and add a link.

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