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

Fixes to stubtest's new check for missing stdlib modules #15960

Merged
merged 5 commits into from
Aug 27, 2023

Conversation

AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Aug 25, 2023

I did a trial run with my typeshed fork using GitHub Actions to see what the results of running stubtest on typeshed's stdlib stubs were with mypy's master branch. It's a good job that I did, as it revealed that there were a few flaws in the logic I introduced in #15729:

  • It's not easy to predict where stdlib modules are going to be located. (It varies between platforms, and between venvs and conda envs; on some platforms it's in a completely different directory to the Python executable.)
  • Some modules appear to raise SystemExit when stubtest tries to import them in CI, leading stubtest to instantly exit without logging a message to the terminal.
  • Importing some test.* submodules leads to unraisable exceptions being printed to the terminal at the end of the stubtest run, which is somewhat annoying.

This PR fixes the bugs. This logic has now been tested locally using venv, locally using conda environments, on GitHub Actions, on py311, py38, Ubuntu, Windows and macOS.

mypy/stubtest.py Outdated
for finder, module_group in modules_by_finder.items():
if (
"site-packages" not in Path(finder.path).parents
and {"json", "_json", "_queue"} & module_group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these modules special?

Copy link
Member Author

@AlexWaygood AlexWaygood Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment in bf9fdad. If there was a sure-fire way of finding out where the pure-Python and extension stdlib modules are located on any Python build, we could filter according to the .path attribute of the finder, which would be more principled. There might be a sure-fire way of doing so using sysconfig, not sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these?

>>> sysconfig.get_path("stdlib")
'/Users/jelle/.pyenv/versions/3.11.1/lib/python3.11'
>>> sysconfig.get_path("platstdlib")
'/Users/jelle/py/venvs/py311/lib/python3.11'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these?

They don't do the right thing on Windows, unfortunately:

>>> import sysconfig, pkgutil
>>> sysconfig.get_path("stdlib")
'C:\\Users\\alexw\\AppData\\Local\\Programs\\Python\\Python311\\Lib'
>>> sysconfig.get_path("platstdlib")
'C:\\Users\\alexw\\AppData\\Local\\Programs\\Python\\Python311\\Lib'
>>> m = next(m for m in pkgutil.iter_modules() if m.name == "_queue")
>>> m.module_finder.path
'C:\\Users\\alexw\\AppData\\Local\\Programs\\Python\\Python311\\DLLs'

Copy link
Member Author

@AlexWaygood AlexWaygood Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.path.join(sysconfig.get_config_var("BINDIR"), sysconfig.get_config_var("platlibdir")) might be the incantation I'm looking for...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.path.join(sysconfig.get_config_var("BINDIR"), sysconfig.get_config_var("platlibdir")) might be the incantation I'm looking for...

no, that doesn't work on linux.

There's a StackOverflow answer here using distutils.sysconfig.get_python_lib, but it's nontrivial, and distutils is all deprecated anyway: https://stackoverflow.com/a/8992937/13990016. Not sure if it's worth it.

mypy/stubtest.py Show resolved Hide resolved
Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hauntsaninja would you like to take another look?

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I concluded something similar when I wrote #15729 (review) . I think it's fine and I'm not aware of a better solution.

I think you still need sys.builtin_module_names the way that snippet does though

@@ -1679,16 +1680,22 @@ def get_importable_stdlib_modules() -> set[str]:
all_stdlib_modules = sys.stdlib_module_names
else:
all_stdlib_modules = set(sys.builtin_module_names)
Copy link
Member Author

@AlexWaygood AlexWaygood Aug 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you still need sys.builtin_module_names the way that snippet does though

@hauntsaninja we start off with the sys.builtin_module_names modules being in the set

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh oops, I missed that. Thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries — thanks for the review! :D

@hauntsaninja hauntsaninja merged commit d7b2451 into python:master Aug 27, 2023
@AlexWaygood AlexWaygood deleted the fix-stubtest branch August 27, 2023 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants