-
Notifications
You must be signed in to change notification settings - Fork 28.1k
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
Fix Pyright static type checking by replacing if-else imports with try-except #16578
Fix Pyright static type checking by replacing if-else imports with try-except #16578
Conversation
The documentation is not available anymore as the PR was closed or merged. |
There is another way to fix the "Go to Reference" in VsCode that has been shown here. I would like to avoid changing something as critical at the main init. |
Unfortunately that switches out the entire language server (Pyright/Pylance for Jedi) and is in effect equivalent to saying that Huggingface doesn’t support Pyright. Many people prefer Pyright as it’s significantly snappier than Jedi-based LSPs and it’s often recommended over Jedi in IDEs that support both (notably Vim and Emacs). |
I wouldn't say Hugging Face does not support Pyright when it's Pyright that doesn't support a simple if/then/else. Honestly, to me, this is an issue that should be fixed at that level instead of asking package maintainers to add some hacky workarounds like the one you are suggesting (not your fault, I understand it's the only thing supported as of now ;-) ). Pinging @LysandreJik and @patrickvonplaten for your advice, but I'd personally leave things as is and say that we don't support Pyright. |
I fully understand the hesitation to take a scalpel to something as important as the init system. (Which is, by the way, extremely pleasant to use from a user ergonomics perspective. I have learnt a lot from HF's design decisions - thank you!) If Pyright were a niche tool I'd drop it, but it's genuinely one of the best and most popular ways to interact with Python code inside VSCode, Vim and Emacs. Pyright has good reason for its current behaviour: as a static checker it has no way of knowing whether a given if cond:
from a import X # Pyright ignores this one...
else:
from b import X # ...and selects this one They could've chosen otherwise, but there's no obvious reason why they should have. The problem with There may be an alternative resolution that fixes Pyright and leaves your init system intact, by the way. Many libraries (including Pandas and Numpy) now produce "type stubs", which are essentially what |
I've given it a bit more thought and I agree that this would be a welcome change. My main issues are around the necessary workarounds in the scripts we use to check the repo consistency. I also think that syntax B is better in your suggestion. Would we need to do this for each of the model subfolders init as well? |
Yeah it needs to be done for model imports too. It’s probably best to automate it using something like awk or batch processing in vim. I had a stab at manual correction and there’s just too much. I agree that checking for consistency is tricky. Does someone on your side have capacity to work on this change, perhaps to guide modifications to |
I don't think anyone has the bandwidth to work on this presently, so if you have time to finish the PR, that would be best! |
That's fine, I'll finish the PR myself. :) So far I've made two non-trivial decisions that I'd like to check with you.
Are both fine with you? |
c8bfb73
to
0a8e936
Compare
Completely agree with both point! Thanks a lot for tackling this! |
6800bc5
to
60d27b1
Compare
Alright, I think the bulk of the work is done, but there are a few failing tests.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for rolling this out to all inits. I can help with the scripts once the PR is ready but you moved all imports in the submodules init before the copyright files, for some reason, which needs to be undone.
Once this is cleaned up what there is left to do is:
- adapt the file
to_replace.py
in the add new model template to use the same format as the new init. The "start lines" for all the imports in the TYPE_CHECKING section should be adapted, this one and the next. - adapt the add new model like command file, in particular the functions
clean_frameworks_in_init
andadd_model_to_main_init
- fix the test in
check_inits.py
which is currently not testing anything anymore.
src/transformers/file_utils.py
Outdated
@@ -59,6 +59,7 @@ | |||
EntryNotFoundError, | |||
ExplicitEnum, | |||
ModelOutput, | |||
OptionalDependencyNotAvailable, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to add it here as this file only exists for backward compatibility reasons and this is a new object.
from typing import TYPE_CHECKING | ||
|
||
from ...utils import ( | ||
OptionalDependencyNotAvailable, | ||
_LazyModule, | ||
is_flax_available, | ||
is_sentencepiece_available, | ||
is_tf_available, | ||
is_tokenizers_available, | ||
is_torch_available, | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why more the imports before the copyright? They should go below as before.
from typing import TYPE_CHECKING | ||
|
||
from ...utils import ( | ||
OptionalDependencyNotAvailable, | ||
_LazyModule, | ||
is_flax_available, | ||
is_sentencepiece_available, | ||
is_tf_available, | ||
is_tokenizers_available, | ||
is_torch_available, | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why more the imports before the copyright? They should go below as before.
|
||
class OptionalDependencyNotAvailable(BaseException): | ||
"""Internally used error class for signalling an optional dependency was not found.""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
class OptionalDependencyNotAvailable(BaseException): | ||
"""Internally used error class for signalling an optional dependency was not found.""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many thanks for the review and apologies for no update yet - this is very much on my mind, I've just been distracted by other priorities. Hope to look at it over one of the coming evenings. |
b534ce0
to
26e21d6
Compare
Fixed imports - sorry, that was an artefact of my automated init fixer. I haven't been able to do much about Will tackle "add new model like" command next. |
For the changes in |
957e850
to
1b5ef4c
Compare
Alright, I think we're done here! :) All tests pass and Pyright picks up the correct classes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Terrific work on this, thanks a lot! Since this touches a lot of files, pinging @LysandreJik for a second review before we merge.
src/transformers/file_utils.py
Outdated
@@ -59,6 +59,7 @@ | |||
EntryNotFoundError, | |||
ExplicitEnum, | |||
ModelOutput, | |||
OptionalDependencyNotAvailable, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to add it here as this file only exists for backward compatibility reasons and this is a new object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, super impressive work! LGTM, thanks for your work @d-miketa!
Thanks both! :) Happy to contribute back! |
…ith try-except (huggingface#16578) * rebase and isort * modify cookiecutter init * fix cookiecutter auto imports * fix clean_frameworks_in_init * fix add_model_to_main_init * blackify * replace unnecessary f-strings * update yolos imports * fix roberta import bug * fix yolos missing dependency * fix add_model_like and cookiecutter bug * fix repository consistency error * modify cookiecutter, fix add_new_model_like * remove stale line Co-authored-by: Dom Miketa <dmiketa@exscientia.co.uk>
What does this PR do?
Fixes #11642.
The Transformers library has a system for importing optional dependencies which replaces objects from missing libraries with "dummy" versions; this logic is implemented by a simple
if-else
statement intransformers/__init__.py
. Unfortunately Pyright/Pylance, the type-hinting software behind VSCode and widely used in other editors, always assumes that the dummy objects are the ones being imported. This breaks diverse useful functionalities such as "Go to reference" (you are always taken to the dummy implementation), documentation (empty dummy docstrings are shown) and type hinting (the dummy's properties are assumed to hold).This PR replaces the
if-else
import logic with slightly more verbosetry-except(-else)
- the form supported by Pyright/Pylance for this precise use case microsoft/pylance-release#2402.WIP Status
utils/check_inits.py
currently doesn't pass, but I've been able to modify it (locally, not in PR yet) to account for changes to the main__init__.py
. Unfortunately this surfaced the fact that there are hundreds of other small changes that need to be made across the entire library. I can do this work, but it'll be a longer process. In the meantime I'm asking for guidance on the form of import blocks. I can see two options. The difference is in the location of the "true" (i.e. non-dummy) imports:A
B
B is slightly more verbose but seems to be preferred by official Python guidelines: https://docs.python.org/3.9/tutorial/errors.html#handling-exceptions. I'm currently leaning towards B but perhaps I've missed a more elegant solution.
Before submitting
Pull Request section?
to it if that's the case.
documentation guidelines, and
here are tips on formatting docstrings.
Who can review?
Possibly @sgugger?