-
Notifications
You must be signed in to change notification settings - Fork 793
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 return type hints to improve code completion suggestions #2846
Conversation
Impressive work @binste! I'm not very familiar with type hinting. I was wondering what your opinion is on using https://github.com/python/typing_extensions as dependency for Python < 3.11. It contains a back-port for the I know it only needs to be defined a few times in the |
Thanks @mattijn! :) Regarding |
I understand that adding another dependency just to reduce 5 lines of code is probably not worth it. I also agree that there may be other recent type-related changes in the core of Python that makes it something to consider if we look a bit broader than this PR alone. We previously had two types of discussions about types in Altair.
Especially the result of the second bullet has set the type However, with your impressive PRs regarding jsonschema and types, I was wondering, since types are included in the vega-lite jsonschema, if these types can also be inferred for each argument? Maybe recent type-related changes in the core of Python can make this easier? It is merely an open question from which I don't know enough if it is worthwhile to consider. |
Thanks for writing this down! This is very helpful. It should be possible to create Python type hints based on the vl schema, especially given that this parsing is already done for the docstrings, see e.g. https://github.com/altair-viz/altair/blob/master/altair/vegalite/v5/schema/channels.py#L12509 where the
There are probably also synergies with replacing the vega-lite types with Python types in all error messages (suggested by you in #2842 (comment)) and docstrings. As more type hints shouldn't break anyones code, I don't think we would need to necessarily include it in the release candidate but I'm definitely intrigued in giving this a try. I really like the development experience you get for a library with well-defined type hints such as better autocompletion as well as early warnings if you pass a wrong value to an argument before even executing the code, for example if you'd pass an integer to I'll try to get a draft PR going in the coming weeks so we can further explore how well it works. |
This is looking very useful, thank you @binste ! Do you know if jupyterlab autocompletion would benefit from this change as well, or are they not using the same approach as VScode here? |
Just tested it and JupyterLab can already provide good autocompletion without this PR: I haven't kept up with the JupyterLab developments but I think it uses some autocomplete engine (maybe jedi?) which relies on inspection of objects instead of type hints. For example the above auto completion only works once you executed the first cell. VS Code can provide it without execution based on type hints alone. Maybe some language servers, see https://github.com/jupyter-lsp/jupyterlab-lsp, could benefit as well or other IDEs such as PyCharm but I haven't tested that. |
Ah ok so this PR brings VS Code up to the same level as JupyterLab is already at, got it. And you're correct, IPython uses Jedi. I have tested the lsp extension and I think there was talk about integrating it in to core in a future version of jupyterlab so maybe it will be there soon. |
I've the feeling that with the last commit something got mixed up. Currently the following definitions are defined two times. MARK_METHOD = ...
CONFIG_METHOD = ...
CONFIG_PROP_METHOD = ... |
Thanks for spotting it! Indeed, there was a merge conflict as I modified those variables in this PR and they were also moved around in the PR which removed vega 5. I made a mistake when resolving that conflict. It's fixed now and I ran Need to wait for #2869 before black test passes. |
With #2814 we check for top level variables in the FAILED tests/test_toplevel.py::test_completeness_of__all__ - AssertionError: assert ['Aggregate',...tString', ...] == ['Aggregate',...tString', ...]
[699](https://github.com/altair-viz/altair/actions/runs/4152594080/jobs/7183718320#step:6:700)
At index 410 diff: 'TOPLEVEL_ONLY_KEYS' != 'TChart'
[700](https://github.com/altair-viz/altair/actions/runs/4152594080/jobs/7183718320#step:6:701)
Right contains 10 more items, The new elements added to the - 'TChart',
- 'TConcatChart',
- 'TEncodingMixin',
- 'TFacetChart',
- 'THConcatChart',
- 'TLayerChart',
- 'TRepeatChart',
- 'TTopLevelMixin',
- 'TVConcatChart',
- 'TypeVar', If this is expected than I think the |
Can these type hints also be defined in hidden modus? E.g. as such: _TChart = TypeVar("_TChart", bound="Chart") |
…TypeVar itself in __all__
I like the approach of marking them as private with the "_" prefix so they don't even get imported all the way to the top-level. Could give us also more flexibility when doing #2854 as no-one should rely on the current naming and that these typevars are defined like this. Pushed this change. |
Tests pass, looks better now👍 |
Current behaviour
Some autocomplete engines such as the one used by VS Code heavily use type hints. Without this PR, after using a method on a chart once, VS Code no longer knows that it is still a
Chart
(orFacetChart
, etc.) object:Autocompletion still works for the first method:
But is lost afterwards:
VS Code states that the return type of
mark_bar
isAny
, meaning that it does not know what it returns.New behaviour introduced in this PR
This PR adds return type hints to all top-level chart methods I could find. These are usually "self" type hints which tell a static type checker that an object is returned which has the same type as the object on which the method was called. The approach is explained in the "Motivation" section in PEP 673 - Self Type which introduces a new way of doing this but that was only introduced in Python 3.11 so I still use the backwards compatible approach here with bound
TypeVar
.The return type now correctly displays as "Chart":
This also works if a method such as
repeat
changes the chart to aRepeatChart
. Callingconfigure
afterwards gives the correct return type hint: