-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Include generated stubs in python package #6917
base: main
Are you sure you want to change the base?
Conversation
Thanks for submitting this pull request! The maintainers of this repository would appreciate if you could update the CHANGELOG.md based on your changes. |
This is ready for review now. In 85dd074 I moved the namespace fixing ( I added a cmake flag |
The open3d python package installs the following now:
Note the following new files:
|
I fixed some build errors from CI checks. There is still an issue when open3d-ml is included. I will fix that later today. |
I fixed some CI stuff, but there are still two issues left in the Windows checks:
Not sure right now how to fix those. |
I disabled stubgen for windows shared libs and windows cuda workflows by introducing the Currently, I cannot really check if stubgen works for CUDA since I do not have access to a GPU supporting CUDA at home right now. Open3D/python/open3d/__init__.py Lines 65 to 69 in 6cb32f6
So pybind11-stubgen does not work if no device is available.
At this point, I would love to get some feedback. |
Looking forward to this to get merged! This will improve a lot the safety and use of Open3D in large applications. |
Hi @timohl thanks for this very useful contribution! The goal of this PR is to improve type checking support when using Open3D. One way to test this is by running mypy over the Python examples and looking at the output with and without this PR (i.e. with open3d v0.18 installed vs the Python wheel from this PR installed.) When I tried that, I ran into this error with the wheel from this PR: $ mypy examples/python/geometry/triangle_mesh_with_numpy.py
/Users/ssheorey/.pyenv/versions/3.11.4/envs/o3d-311/lib/python3.11/site-packages/open3d/__init__.pyi:51: error: invalid syntax [syntax]
Found 1 error in 1 file (errors prevented further checking) Here's what it's complaining about (last line of open3d = Can you take a look? |
Honestly, I am not sure why there is this Now mypy has a new errror: mypy examples/python/geometry/triangle_mesh_with_numpy.py
/home/timohl/projects/Open3D/.venv/lib/python3.10/site-packages/open3d/cpu/pybind/core/__init__.pyi:732: error: non-default argument follows default argument [syntax]
Found 1 error in 1 file (errors prevented further checking) refering to: @staticmethod
@typing.overload
def arange(start: int | None = None, stop: int, step: int | None = None, dtype: Dtype | None = None, device: Device | None = None) -> Tensor:
"""
Create a 1D tensor with evenly spaced values in the given interval.
""" I will try to fix all mypy errors, but soonest I can find time for that might be next weekend. |
…gent_plane. `lambda` is a reserved keyword in python and causes mypy to complain.
This is in line with the cpp implementation and avoids named args before positional args.
I fixed some mypy errors: Changed Tensor.arange signature to be like in numpy (230a9a6).This is how numpy defines arange: @overload
def arange( # type: ignore[misc]
stop: _IntLike_co,
/, *,
dtype: None = ...,
device: None | L["cpu"] = ...,
like: None | _SupportsArrayFunc = ...,
) -> _1DArray[int, signedinteger[Any]]: ...
@overload
def arange( # type: ignore[misc]
start: _IntLike_co,
stop: _IntLike_co,
step: _IntLike_co = ...,
dtype: None = ...,
*,
device: None | L["cpu"] = ...,
like: None | _SupportsArrayFunc = ...,
) -> _1DArray[int, signedinteger[Any]]: ... Note how Also, it adds Changed
|
mypy now does not complain about anything in the stub files (I applied #6896 as well though), but has two errors in the example code: mypy examples/python/geometry/triangle_mesh_with_numpy.py
examples/python/geometry/triangle_mesh_with_numpy.py:14: error: Argument 1 to "read_triangle_mesh" has incompatible type "str"; expected "PathLike[Any]" [arg-type]
examples/python/geometry/triangle_mesh_with_numpy.py:15: error: Argument 1 to "paint_uniform_color" of "TriangleMesh" has incompatible type "list[float]"; expected "ndarray[Any, Any]" [arg-type]
Found 2 errors in 1 file (checked 1 source file) The first error comes from pybind11 generating We could change The second error involves this signature in the stubs: def paint_uniform_color(self, arg0: numpy.ndarray[numpy.float64[3, 1]]) -> MeshBase:
... pybind11 uses |
288d51d also seems to cause an error in CI: Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/home/runner/work/Open3D/Open3D/open3d_test.venv/lib/python3.11/site-packages/open3d/__init__.py", line 61, in <module>
load_cdll(str(next((Path(__file__).parent / "cpu").glob("pybind*"))))
File "/home/runner/work/Open3D/Open3D/open3d_test.venv/lib/python3.11/site-packages/open3d/__init__.py", line 36, in load_cdll
raise FileNotFoundError(f"Shared library file not found: {path}.")
FileNotFoundError: Shared library file not found: /home/runner/work/Open3D/Open3D/open3d_test.venv/lib/python3.11/site-packages/open3d/cpu/pybind. https://github.com/isl-org/Open3D/actions/runs/10647126362/job/29514998533?pr=6917 |
Strings are implicitly convertible to `fs::path`, but pybind11 just uses `os.PathLike` and not `os.PathLike | str` as type annotation. Python does not support implicit conversions for annotations, so this corrects the annotations to be explicit.
70b3f81 fixes The major amount of remaining mypy errors are implicit conversions from Another common error is mypy not resolving imports correctly: mypy examples/python/io/realsense_io.py
examples/python/io/realsense_io.py:28: error: Cannot find implementation or library stub for module named "open3d.t.io" [import-not-found]
examples/python/io/realsense_io.py:28: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
examples/python/io/realsense_io.py:28: error: Cannot find implementation or library stub for module named "open3d.t" [import-not-found]
examples/python/io/realsense_io.py:29: error: Cannot find implementation or library stub for module named "open3d.t.geometry" [import-not-found]
examples/python/io/realsense_io.py:30: error: Cannot find implementation or library stub for module named "open3d.visualization.gui" [import-not-found]
examples/python/io/realsense_io.py:31: error: Cannot find implementation or library stub for module named "open3d.visualization.rendering" [import-not-found]
examples/python/io/realsense_io.py:69: error: "Callable[[Any, Any, Any, Any, Any], Any]" has no attribute "fid" [attr-defined]
Found 6 errors in 1 file (checked 1 source file) mypy is able to |
Some notes (mostly for myself, but happy for any help/advice) regarding implicit list -> np.ndarray conversions causing mypy errors like this: mypy examples/python/geometry/triangle_mesh_with_numpy.py
examples/python/geometry/triangle_mesh_with_numpy.py:15: error: Argument 1 to "paint_uniform_color" of "TriangleMesh" has incompatible type "list[float]"; expected "ndarray[Any, Any]" [arg-type]
Found 1 errors in 1 file (checked 1 source file) list is not always convertible to np.ndarray, but only when using Eigen typesExample: import numpy as np
import open3d as o3d
#[1] Uses Eigen::Vector3d
bb = o3d.geometry.AxisAlignedBoundingBox([0, 0, 0], np.array([1, 1, 1]))
print(bb)
#[2] Uses explicit overloads for py::list
t1 = o3d.core.Tensor([0, 1.5, 0], dtype=o3d.core.float32)
print(t1)
#[3] Same as [2]. shape is a ambigous here, since this will not set the shape but initilize the Tensor with those values
t2 = o3d.core.Tensor(shape=[0, 1, 0], dtype=o3d.core.float32)
print(t2)
#[4] Uses py::array -> Error when passing list
t3 = o3d.core.Tensor.from_numpy([0, 5, 0])
print(t3) Output: AxisAlignedBoundingBox: min: (0, 0, 0), max: (1, 1, 1)
[0 1.5 0]
Tensor[shape={3}, stride={1}, Float32, CPU:0, 0x5623bc51ff80]
[0 1 0]
Tensor[shape={3}, stride={1}, Float32, CPU:0, 0x5623bc562150]
Traceback (most recent call last):
File "/home/timohl/projects/pybind11-stubgen/o3d_test.py", line 10, in <module>
t3 = o3d.core.Tensor.from_numpy([0, 5, 0])
TypeError: from_numpy(): incompatible function arguments. The following argument types are supported:
1. (arg0: numpy.ndarray) -> open3d.cpu.pybind.core.Tensor
Invoked with: [0, 5, 0] How could annotation using ArrayLike for Eigen types look like?Using imports this is a more compact view and could easily be displayed in sphinx docs like this: import numpy as np
import numpy.typing as npt
from typing import Annotated
def f1(arg0: np.ndarray[np.float64[3, 1]] | npt.ArrayLike) -> None: ...
def f2(arg0: Annotated[npt.ArrayLike, np.float64[3, 1]]) -> None: ... Right now I would tend to How to insert ArrayLike annotations?I am not sure, however, how to get there, so that only Eigen Arguments and not Return values are using ArrayLike.
|
I have opened a pull request at pybind/pybind11#5358 to add a feature for adding different type hints for args and return types. |
Just a quick update: Some notes on what to do next: With specialized arg+return type hints most mypy errors should be easy to fix and generates more precise documentation on what types are actually valid for function parameters. |
Type
Motivation and Context
Currently, the Open3D python package does not come with typing stubs.
Stubs can be generated manually using pybind11-stubgen (with currently wip fixes in #6896).
This pull request tries to integrate the generated typing stubs into the python package.
In this way, Open3D can ship with typing support out of the box.
Checklist:
python util/check_style.py --apply
to apply Open3D code styleto my code.
updated accordingly.
results (e.g. screenshots or numbers) here.
Description
This adds the following steps to the build process:
py.typed
file to mark typing support (see PEP 561TODO:
open3d.camera
instead ofopen3d.cpu.pybind.camera
in stubs are not resolved correctly. Further investigation requiered...