Skip to content

🐛 fix(type): pass the latest ty and close Any gaps - #4075

Merged
gaborbernat merged 1 commit into
tox-dev:mainfrom
gaborbernat:fix-ty-name-collision
Sep 19, 2026
Merged

gaborbernat merged 1 commit into
tox-dev:mainfrom
gaborbernat:fix-ty-name-collision

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Sep 19, 2026 •

Copy link
Copy Markdown
Member

The type check jobs went red on main with no code change: the scheduled run passed on 17 September and failed a day later on the same commit, because CI picked up ty 0.0.82. Every open PR now inherits that failure, #4074 included. 🔴

The new release reports two things. Inside the ini loader package, the bare name replace means both the substitution function and the package's own replace submodule, since importing a submodule binds its name onto the parent package. The function is now imported under an unambiguous alias, and the tox.config.loader.ini.replace import path stays as it was. ty also rejects instantiating an abstract class. One test does that on purpose to prove the runtime rejects the call too, so its suppression gains the new diagnostic code, and every suppression that remains now states in place why it has to stay.

I then ran ty with its opt-in rules to see what the default run lets through, and fixed what had a real fix. Around sixty places read a configuration value as Any and annotated it with a type nothing verified; they now go through the type-checked accessor added in 4.59, and a new ConfigSet.get_optional covers values that may be unset. That exposed annotations that were wrong: min_version was declared as a version but is None when unset, and dependency groups were typed as a list of strings or a single include table instead of a list of either. Every method that overrides a parent now carries @override. The release task's ignores hid a version object compared against tag names and a commit passed where a ref string is expected. ✅

This is meant to change no behaviour. For each converted configuration key I checked its registration (declared type, default, post-processing) and all of them produce the type the accessor asks for, so its TypeError cannot fire for tox's own configuration. An independent review compared 54 command invocations between this branch and main across tox.ini and tox.toml projects, with and without tox-uv, tox-gh and tox-gh-actions, and found identical output; the tox-uv test suite fails the same tests on both. The opt-in rules that now come out clean are enabled so they stay that way. What remains needs separate decisions: command line options arrive as an untyped argparse namespace, and the platform-specific findings come from checking all platforms at once.

@gaborbernat gaborbernat added the type:internal should have no impact on the user (refactoring, infrastructure, tools, etc.) label Sep 19, 2026
@gaborbernat gaborbernat changed the title 🐛 fix(type): resolve ty regressions from a newer release 🐛 fix(type): pass type checks on the latest ty Sep 19, 2026
@gaborbernat
gaborbernat force-pushed the fix-ty-name-collision branch 2 times, most recently from bd8fdf3 to 4040136 Compare September 19, 2026 00:17
@gaborbernat gaborbernat changed the title 🐛 fix(type): pass type checks on the latest ty 🐛 fix(type): pass the latest ty and close Any gaps Sep 19, 2026
A ty release after main's last green run turned the type jobs red on
an unchanged commit. Inside the ini loader package the bare name
`replace` means both the substitution function imported there and the
package's own `replace` submodule, because importing a submodule
binds its name onto the parent package. ty now resolves the name to
the submodule and rejects the calls. The function is imported under
an unambiguous alias instead, which keeps the documented
`tox.config.loader.ini.replace` import path intact. ty also reports
instantiating an abstract class, which one test does on purpose, so
that suppression gains the new code and every remaining suppression
now says why it has to stay.

Running ty with its opt-in rules showed how much the default run
lets through. About sixty sites annotated a config lookup with a type
the checker could not verify, since `conf[...]` returns Any; they now
go through `ConfigSet.get`, and the new `ConfigSet.get_optional`
covers keys that may be unset. Each converted key was checked against
its registration: declared type, default and post-processing all
produce the type asked for, so the runtime check cannot fire for
tox's own configuration. The pass surfaced annotations that were
wrong: `min_version` was declared Version but is None when unset, and
dependency groups were typed as a list of strings or one include
table rather than a list of either.

Guards that could never be false are gone where the code right next
to them already dereferences the same value, and the release task's
ignores hid a Version compared against tag names and a Commit passed
as a ref string. Every overriding method in src and tests carries
`@override`, from typing on 3.12+ and typing_extensions before that.
The opt-in rules that now come out clean are enabled so they stay
clean.
@gaborbernat
gaborbernat enabled auto-merge (squash) September 19, 2026 00:54
@gaborbernat
gaborbernat merged commit e521d6e into tox-dev:main Sep 19, 2026
30 checks passed
@gaborbernat
gaborbernat deleted the fix-ty-name-collision branch October 3, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided type:internal should have no impact on the user (refactoring, infrastructure, tools, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant