robotpy / mostrobotpy

Official Repository of python implementation of WPILib components
https://robotpy.github.io
Other
10 stars 11 forks source link

[BUG]: add typealias for units to typestubs #21

Closed virtuald closed 10 months ago

virtuald commented 2 years ago

Problem description

As mentioned in robotpy/robotpy-wpimath#29 by @auscompgeek :

Ideally we'd have meters: TypeAlias = float somewhere. I don't think we have a way of injecting things into the type stub output yet.

This would be the right way to fix it... but sounds like work. IMO it's better to have the names in there (and have the type hints be invalid) than to not have the names, since the units aren't always obvious.

Would likely require a change in pybind11-stubgen and/or robotpy-build.

Operating System

Windows, MacOS, Linux

Installed Python Packages

No response

Reproducible example code

No response

auscompgeek commented 1 year ago

New since last year: Pyright/Pylance now spits out the following as the signature for Rotation2d.radians:

(method) radians() -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: ) -> )))))))))))))))))))))))))))))))

Attempting to type-check an expression that does a subtraction like rotation.radians() - other_angle results in the following error:

Operator "-" not supported for types "(self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: ) -> )))))))))))))))))))))))))))))))" and "float"
  Operator "-" not supported for types "(self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: Rotation2d) -> ((self: ) -> )))))))))))))))))))))))))))))))" and "float"

Needless to say this is rather painful.

Appending radians: typing.TypeAlias = float makes Pyright behave correctly.

Oddly enough, the same does not happen for other methods like Translation2d.norm.

Real code that exhibits this issue: https://github.com/thedropbears/pychargedup/blob/9cdc581dd20f11ce2e19872ede0f2ea02d1b6998/components/chassis.py#L142

virtuald commented 1 year ago

If you make the typecaster do this:

template <> struct handle_type_name<units::meter_t> {
  static constexpr auto name = _("wpimath.units.meters");
};

Then this:

    m.def("demo", [](units::meter_t m) {

    });

Turns into this in the .pyi file:

def demo(arg0: wpimath.units.meters) -> None:
    pass

However, pybind11-stubgen does not add a import wpimath.units to the .pyi file. Is that enough to make pylance happier?

OliverW10 commented 1 year ago

With Rotation2d.radians()'s return type as wpimath.units.radians pylance doesn't complain about the recursive type but still gives Unknown, with import wpimath.units and radians: typing.TypeAlias = float in units it correctly reports radians

auscompgeek commented 1 year ago

FWIW I think Pyright is also showing all the other types as Unknown rather than keeping the original unresolved type names, which isn't particularly great either.

sizmailov commented 1 year ago

The new version of pybind11-stubgen should handle imports properly with the code suggested by @virtuald. You only need to ensure that the type name ( wpimath.units.meters in the snippet above) is actually importable.

auscompgeek commented 1 year ago

Nice! Just need to figure out why these temp dirs are refusing to be cleaned up on Windows then. https://github.com/robotpy/robotpy-build/pull/211

virtuald commented 11 months ago

I believe this is fixed now in the 2024-beta.