taichi-dev / taichi

Productive, portable, and performant GPU programming in Python.
https://taichi-lang.org
Apache License 2.0
25.51k stars 2.28k forks source link

Feature request: mypy type-checking #794

Open kazimuth opened 4 years ago

kazimuth commented 4 years ago

Concisely describe the proposed feature I use the mypy static type-checker in my python projects and I'd like to use it with my taichi code. It makes maintenance in particular much easier; refactoring is smoother, and also IDE suggestions are nicer because they include types.

Describe the solution you'd like (if any) There's a couple of ways to integrate mypy with a python package. You can either release stub files with your project, or add types throughout the codebase. Stub files describe the project's API, like so:

# in stubs/taichi/lang/impl.pyi

def var(dt: DataType,
        shape: Optional[Union[int, Sequence[int]]] = None,
        needs_grad: bool = False) -> Expr:
    ...

Alternatively, you can include such annotations inline in your code, and configure your package so that other packages will know it has types. Alone these types do nothing. However, when you run the mypy typechecker on your codebase, it will report errors (calling a method that does not exist, etc.)

I would recommend including mypy in your project and running it with the rest of your tests. It makes maintenance easier, and ensures that your type stubs won't get out-of-date. However, not everybody likes type annotations, so I understand if this isn't a change you want to make.

If there is interest, I would be happy to make a PR to get this started. You don't have to annotate everything to get started -- mypy assumes non-annotated functions take and return the type Any. You can then add annotations as you go.

Additional comments Mypy doesn't do very well with numpy / etc, because nobody's written good type stubs for them yet. Similarly, mypy can't type-check pybind11 code because it doesn't generate stub files. However, mypy is still useful even if it can't check all of the codebase. For example, the xarray project uses mypy even though most of its dependencies don't.

yuanming-hu commented 4 years ago

Thanks for proposing this. I think having type annotation would be a great idea, especially for APIs such as var, Vector, Matrix.

You can either release stub files with your project, or add types throughout the codebase.

I feel like add types in-place would be easier. Maintaining a set of stub files sounds like extra work and some code will get repeated.

I would recommend including mypy in your project and running it with the rest of your tests. It makes maintenance easier, and ensures that your type stubs won't get out-of-date. However, not everybody likes type annotations, so I understand if this isn't a change you want to make.

I don't see a clear downside of type annotations, so this is probably worth trying. One question: will running mypy tests take a long time? I think it's unlikely, just in case. Now CI already takes ~30 minutes...

If there is interest, I would be happy to make a PR to get this started. You don't have to annotate everything to get started -- mypy assumes non-annotated functions take and return the type Any. You can then add annotations as you go.

That would be great! Thanks in advance.

Mypy doesn't do very well with numpy / etc, because nobody's written good type stubs for them yet. Similarly, mypy can't type-check pybind11 code because it doesn't generate stub files.

No worries about pybind11 - that's never exposed to the end-users in Taichi :-)

kazimuth commented 4 years ago

I don't see a clear downside of type annotations, so this is probably worth trying. One question: will running mypy tests take a long time? I think it's unlikely, just in case. Now CI already takes ~30 minutes...

Mypy's pretty fast, I don't think it should add much time. 10-20 seconds maybe?

Imo the only real downside is that occasionally type annotations can be a bit inflexible. Mypy's good, but it's not as expressive as something like typescript. So you generally want to keep your types simple and use runtime checks + unit tests to make sure complex invariants are maintained. Luckily that's how the code already works :)

yuanming-hu commented 4 years ago

Mypy's pretty fast, I don't think it should add much time. 10-20 seconds maybe?

10-20 seconds should be OK :-)

Imo the only real downside is that occasionally type annotations can be a bit inflexible. Mypy's good, but it's not as expressive as something like typescript. So you generally want to keep your types simple and use runtime checks + unit tests to make sure complex invariants are maintained. Luckily that's how the code already works :)

I see. I think we should just implement this gradually in a series of small PRs, so that if anyone complains we will have early feedback.