Skip to content

Warn when python-version is older than the bundled typeshed stubs support - #5612

Closed
ImBinarry wants to merge 5 commits into
meta:mainfrom
ImBinarry:warn-outdated-python-version
Closed

ImBinarry wants to merge 5 commits into
meta:mainfrom
ImBinarry:warn-outdated-python-version

Conversation

@ImBinarry

Copy link
Copy Markdown
Contributor

Pyrefly now warns when the resolved Python version is older than the oldest version typeshed supports (currently 3.10). Older than that, the standard library isn't checked accurately, and that's what the warning is for.

It's emitted from ConfigFile::configure_at, prints to the terminal, and leaves the exit code alone.

Fixes #4357

  • I am a human, and I fully understand the code I am submitting.

Test Plan

  • cargo test -p pyrefly_config: 337 passed, including 2 new tests for the warning (3.9 warns; 3.10, 3.11 and 3.13 don't).
  • cargo fmt --all -- --check and cargo clippy -p pyrefly_config --all-targets -- -D warnings: both clean.
  • Manual CLI check: with python-version = "3.9" in pyrefly.toml, the warning prints once, with the config path, and the exit code stays 0. With python-version = "3.13" nothing prints.
  • Didn't run the full CI suite locally (release clippy, bench-profile tests, conformance/Scrut); CI covers that. mypy_primer doesn't cover crates/ anyway, and nothing here changes type-checking behavior.

Typeshed removes stubs for Python versions it no longer supports, so a resolved version below the oldest supported one is checked against incomplete stubs. Warn at config resolution instead of failing, since the user's own code may still support an older version.
@meta-codesync

meta-codesync Bot commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D131218584. (Because this pull request was imported automatically, there will not be any future comments.)

@stroxler stroxler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the PR!

It looks pretty good, but I think there are a few issues we should clean up:

  • Gate the bundled-stub warning on typeshed_path.is_none(). A custom typeshed replaces the bundled stdlib, but the head warns anyway. Add a negative regression test.
  • Improve the message: do not instruct a project legitimately targeting 3.9 to merely set its target to 3.10. That changes the semantics being checked. Explain the limitation and, if offering remediation, distinguish upgrading the supported target from supplying compatible custom stubs. Also reword “Typeshed drops stubs” to describe removal of older-version branches/guards. These wording issues are secondary to the two functional findings.
  • Look into whether we can deliver the warning in cases where Pyrefly synthesizes a config; it appears the current implementation can drop the warning in some situations.

Just to explain the third point: it looks like CLI arguments are used, the warning appears to never reach the user. For example:

# File mode
pyrefly check main.py --python-version 3.9 --skip-interpreter-query
# Project mode
pyrefly check --python-version 3.9 --skip-interpreter-query

A custom typeshed replaces the bundled stdlib and may support older
versions, so only warn when `typeshed-path` is unset. Re-work the message
to describe the removed version-specific branches and guards, and to offer
custom stubs or raising the target instead of just telling users to change
`python-version`.
Synthesized configs debug-logged their config warnings, so
`pyrefly check --python-version 3.9 --skip-interpreter-query` printed
nothing. Fallback callbacks now return the warnings, ConfigFinder
accumulates them (deduped), and project mode returns them, so the CLI
prints them like config-file warnings.
@github-actions github-actions Bot added size/l and removed size/s labels Nov 11, 2026
@ImBinarry

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I pushed fixes for all three in the new commits.

  1. The warning now only fires when typeshed-path is unset, so custom typesheds stay quiet. Added a regression test for that: custom typeshed + python-version = "3.9" produces no warning.

  2. Reworked the message. It now explains that the bundled stubs no longer include the version-specific branches and guards for older versions, and gives two options instead of just telling users to change the target: keep the target and supply compatible custom stubs via typeshed-path, or raise python-version if the project actually targets a newer version.

  3. Root cause for the synthesized-config gap: the file-mode and project-mode fallbacks only logged their config errors at debug level, so warnings never reached the terminal. The fallback callbacks now return the warnings and ConfigFinder accumulates them (deduped, since a single run can synthesize several configs), so both modes print them. Your two example commands now each print the warning once, and --typeshed-path suppresses it.

Tests: cargo test -p pyrefly_config (338 passed), plus a new config-finder test covering the synthesized-config path. cargo fmt --all -- --check and clippy on the touched crate are clean. I didn't run the full suite locally, CI will cover it.

One design note: the delivery fix surfaces config warnings from synthesized configs in general, not just this warning. If you'd prefer a narrower mechanism, I can special-case this one.

@github-actions

Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

============================================================
SUMMARY
============================================================
Total: +8 new errors, -0 fixed errors
By preset: +0/-0 (default), +0/-0 (strict)

Projects with changes (8):
  git-revise: +1 -0
  pybind11: +1 -0
  pyinstrument: +1 -0
  manticore: +1 -0
  antidote: +1 -0
  pywin32: +1 -0
  dragonchain: +1 -0
  discord.py: +1 -0
============================================================

FULL DIFF DETAILS
------------------------------------------------------------

git-revise (https://github.com/mystor/git-revise)
+  WARN .../projects/git-revise/pyrefly.toml: Python version 3.8.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.8.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

pybind11 (https://github.com/pybind/pybind11)
+  WARN .../projects/pybind11/pyrefly.toml: Python version 3.9.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.9.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

pyinstrument (https://github.com/joerick/pyinstrument)
+  WARN .../projects/pyinstrument/pyrefly.toml: Python version 3.8.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.8.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

manticore (https://github.com/trailofbits/manticore)
+  WARN .../projects/manticore/pyrefly.toml: Python version 3.7.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.7.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

antidote (https://github.com/Finistere/antidote)
+  WARN .../projects/antidote/pyrefly.toml: Python version 3.7.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.7.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

pywin32 (https://github.com/mhammond/pywin32)
+  WARN .../projects/pywin32/pyrefly.toml: Python version 3.9.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.9.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

dragonchain (https://github.com/dragonchain/dragonchain)
+  WARN .../projects/dragonchain/pyrefly.toml: Python version 3.8.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.8.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

discord.py (https://github.com/Rapptz/discord.py)
+  WARN .../projects/discord.py/pyrefly.toml: Python version 3.8.0 is older than the oldest version described by the bundled typeshed stubs (3.10.0). The bundled stubs no longer include the version-specific branches and guards for older versions, so the standard library may be modeled inaccurately for this target. If the project must keep targeting 3.8.0, provide compatible custom stubs with `typeshed-path`; otherwise raise `python-version` to 3.10.0 or newer.

@github-actions github-actions Bot added size/l and removed size/l labels Nov 11, 2026
@ImBinarry

ImBinarry commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor Author

@stroxler
The windows-latest failure came from the stale merge base: it predates main's
glob separator fix (#5615). I merged current main into the branch (00c94e1), and
the config tests pass locally (338).

The new CI runs are action_required and need approval since this is my first
contribution. I've also noted the mypy_primer differential in the PR description
(+8 warnings, no type errors).

@stroxler stroxler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

@github-actions github-actions Bot added size/l and removed size/l labels Nov 12, 2026
@meta-codesync meta-codesync Bot closed this in fc2194d Nov 12, 2026
@meta-codesync meta-codesync Bot added the Merged label Nov 12, 2026
@meta-codesync

meta-codesync Bot commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

This pull request has been merged in fc2194d.

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.

Warn about too old python-version

2 participants