nutti / fake-bpy-module

Fake Blender Python API module collection for the code completion.
MIT License
1.32k stars 95 forks source link

Improve typing of Matrix Quaternion and Vector @ operation #156

Closed JonathanPlasse closed 2 months ago

JonathanPlasse commented 7 months ago

Matrix, Quaternion, and Vector @ operation is incompatible with Sequence[float]. Only __matmul__ is needed __rmatmul__ and __imatmul__ can be removed.

The following code is all the valid @ operations.

from mathutils import Matrix, Quaternion, Vector

v = Vector((1, 2, 3))
m = Matrix(((1, 2, 3), (4, 5, 6), (7, 8, 9)))
q = Quaternion((1, 2, 3, 4))

f1: float = v @ v
v1: Vector = m @ v
v2: Vector = v @ m
m1: Matrix = m @ m
q1: Quaternion = q @ q
q2: Vector = q @ v

m @= m
q @= q

The code above pass Mypy and Pyright with the changes below.

class Matrix:
    @typing.overload
    def __matmul__(self, other: "Matrix") -> "Matrix":
        ...

    @typing.overload
    def __matmul__(self, other: "Vector") -> "Vector":
        ...

    def __matmul__(
        self, other: typing.Union["Matrix", "Vector"]
    ) -> typing.Union["Matrix", "Vector"]:
        ...

class Quaternion:
    @typing.overload
    def __matmul__(self, other: "Quaternion") -> "Quaternion":
        ...

    @typing.overload
    def __matmul__(self, other: "Vector") -> "Vector":
        ...

    def __matmul__(
        self, other: typing.Union["Vector", "Quaternion"]
    ) -> typing.Union["Vector", "Quaternion"]:
        ...

class Vector:
    @typing.overload
    def __matmul__(self, other: "Vector") -> float:
        ...

    @typing.overload
    def __matmul__(self, other: "Matrix") -> "Vector":
        ...

    def __matmul__(self, other: typing.Union["Vector", "Matrix"]) -> typing.Union["Vector", float]:
        ...
nutti commented 2 months ago

About this issue, should we need to add @typing.overload?

JonathanPlasse commented 2 months ago

It only necessary only for Vector, as the argument type is different form the return type. Matrix and Quaternion could use TypeVar instead as they use the same type in argument and in the return type. I would prefer using overload everywhere as you would need to implement two different mechanisms (TypeVar and overload) where only one is needed (overload).

https://docs.python.org/3/library/typing.html#typing.overload

nutti commented 2 months ago

This issue is fixed now.