astral-sh / ruff

An extremely fast Python linter and code formatter, written in Rust.
https://docs.astral.sh/ruff
MIT License
32.81k stars 1.1k forks source link

Feature request: support jaxtyping type hints (currently valid type hints flagged incorrectly) #9860

Open jaanli opened 9 months ago

jaanli commented 9 months ago
image

Minimal example that incorrectly flags a valid type hint using the jaxtyping type hint library (https://github.com/patrick-kidger/jaxtyping):

import numpy as np
from jaxtyping import Int
from beartype import beartype

@beartype
def predict_labels_for_encounter(
    encounter_index: np.int32,
    val_sentence_neighbor_idx: Int[np.ndarray, "num_nearest_neighbors"]):
    pass
crypdick commented 9 months ago

I found a work-around to this problem by changing Ruff's typing modules. However, it would be awesome if Ruff would ship this alias within the Ruff codebase. cc @charliermarsh @leycec

charliermarsh commented 9 months ago

We may be able to add some of these as first-class members. I need to look into the relationship between jaxtyping and beartype though.

leycec commented 9 months ago

@beartype lead @leycec is summoned. Thanks so much for the kind consideration, @charliermarsh. Likewise, thanks for pinging me here, @crypdick. Let's also ping jaxtyping lead @patrick-kidger. This is his baby.

I need to look into the relationship between jaxtyping and beartype though.

Tenuous at best. @patrick-kidger could probably fill us in on all the details. Briefly:

Honestly, this issue is probably just about @beartype. As awesome as jaxtyping and typeguard are, this really has nothing to do with either of those packages – I think, anyway. Let us know if @beartype can do anything to assist Ruff here.

patrick-kidger commented 9 months ago

Hey folks! jaxtyping is my package. This is a known issue, and I recommend just disabling the F722 check on this.

(@leycec - this issue is purely jaxtyping-specific, and unrelated to beartype, you'll be pleased to know!)

What's happening is that in type annotations, strings are either (a) just strings or (b) forward references. Ruff is assuming that only the second case is true, trying to resolve our strings as forward references, and failing. This is consistent with flake8.

To be fair, Python itself offers no clear way of distinguishing these cases either. Most static type checkers have to special-case Annotated so that Annotated[Foo, "bar"] is still valid. We actually use if TYPE_CHECKING: from typing import Annotated as Float to make things work with them, but it's not clear if tools like ruff should respect TYPE_CHECKING themselves.

If you'd like to special-case ruff support for jaxtyping that would be awesome. Conversely I recognise you may not wish to add special support to a third-party package, in which case I think no action is needed from ruff. :)