Skip to content
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

Add support for manually generated stub files (*.pyi) #13900

Open
wants to merge 1 commit into
base: branch-3.5
Choose a base branch
from

Conversation

mattpap
Copy link
Contributor

@mattpap mattpap commented May 17, 2024

This PR is an experiment, based on discussion #13870 and other, to bring static types to models and properties. The main goal of this PR is to establish the correct patterns, what works for us and what doesn't. For example I marked all models as data classes, to solve the problem of repetition of properties and their types in __init__ and class members (and also from base classes in __init__).

Ultimately most of this will be automatically generated, but before that we need to figure out the correct types, structure, etc. We also can't simply generate the structure without types, because then we would lose all type information. This is because mypy doesn't support declaration merging, like TypeScript does, so it's an all or nothing type of situation.

Why this didn't happen earlier? It would be infinitely better to have types together with the source code in one place, as we attempted to do and what we achieved in bokehjs. However, due limitations of Python typing, mypy, etc., at this point having separate type declarations at least for models and properties, seems to be the only reasonable approach, short of redesigning our model/property system to better fit the typing ecosystem (which may not be the worst idea for bokeh 4.0 or beyond).

For the sake of convenience and code readability, this PR uses Python 3.12 syntax:

  • type TypeName = This | That for defining type aliases
  • type TypeName[A, B] = This[A] | That[B] for defining generic type aliases
  • class SomeClass[T]: ... for defining generic classes

This only relates to *.pyi files and affects type-checking. It doesn't require run-time support. I suppose we having mypy configured for 3.12 and ruff for 3.10, will be sufficient to use modern typing syntax and make sure it doesn't bleed into *.py files.

fixes #13870

@mattpap mattpap added this to the 3.x milestone May 17, 2024
@bryevdv
Copy link
Member

bryevdv commented May 17, 2024

We also can't simply generate the structure without types, because then we would lose all type information.

FWIW I was planning to do exactly that [1], although my initial thought was to auto generate explicit __init__ for everything, rather than relying on @dataclass to do that automagically. I think your idea here is a very clever approach, but I have some questions:

  • We have some custom __init__ to handle. I don't think we can get rid of them all, e.g. Range1d(start, end). How would to propose to incorporate cases with custom __init__?
  • I am just extremely skeptical that we would be able to actually define proper actual Python types corresponding to all of the Bokeh types. Assuming that is the case, is there a way to make things work that is not "all or nothing"?

[1] Remember, the actual ask is to support auto-completion in IDEs, and that does not require types to be present in order to function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants