Skip to content

Fix type errors flagged by ty 0.0.43#3952

Merged
gaborbernat merged 6 commits into
tox-dev:mainfrom
gaborbernat:fix-ty-0.0.43-type-errors
Jun 4, 2026
Merged

Fix type errors flagged by ty 0.0.43#3952
gaborbernat merged 6 commits into
tox-dev:mainfrom
gaborbernat:fix-ty-0.0.43-type-errors

Conversation

@gaborbernat
Copy link
Copy Markdown
Member

@gaborbernat gaborbernat commented Jun 4, 2026

The scheduled type / type-min checks broke once ty bumped to 0.0.43 (we pin ty>=0.0.19, so CI pulls the latest). This fixes the failures, removes the Windows-runner deprecation notice without churning required-check names, and cleans up every # ty: ignore that has a real fix.

1. ty 0.0.43 failures

Three new diagnostics from stricter type-variable handling:

  • src/tox/config/of_type.pyty now narrows the negative branch of callable() on a Callable[[], T] | T union to object. Instead of the old blanket # ty: ignore[call-top-callable] + cast("T", ...), each branch now casts the value to its precise factory signature before invoking it, so the call is type-checked against a known signature.
  • tests/config/loader/test_toml_loader.pyfactory_na returned NoReturn, so ty inferred Loader.load's type variable as Never, collapsing type[Never] | UnionType to UnionType. Made factory_na generic over the same V so the variable binds from of_type.

2. Windows runner notice + version-less check names

GitHub is redirecting windows-2025 to windows-2025-vs2026 by 2026-06-15. The job names embed ${{ matrix.os }}, and those strings are the repository ruleset's required-check contexts — so naively renaming the runner would have permanently blocked merges.

Instead the matrix os entry is split into a versioned runner image and a bare display name:

os:
  - { image: ubuntu-24.04, name: ubuntu }
  - { image: windows-2025-vs2026, name: windows }
  - { image: macos-15, name: macos }
# name:     test ${{ matrix.py }} on ${{ matrix.os.name }}
# runs-on:  ${{ matrix.os.image }}

Jobs now run on the new image but report stable, version-less check names (test 3.14 on windows, tox env type on ubuntu, …) that won't churn on future image bumps. The repository ruleset's required status checks were updated to the new names accordingly. Applied to check.yaml and weekly.yaml; the release/admin workflows are single ubuntu jobs with no OS in their names and were left unchanged.

3. # ty: ignore cleanup — 8 removed via real type fixes

Location Was suppressed Fix
execute/local_sub_process ov.WriteFile unresolved declared WriteFile in typestubs/_overlapped.pyi
pip/req/file.py dict-key invalid-argument-type annotated lookup as dict[type, int]
virtual_env/package/pyproject.py .value unresolved cast to ConfigConstantDefinition[str] (always registered via add_constant)
session/env_select.py ×2 group invalid-assignment + completer unresolved typed group as _ActionsContainer; declared completer on _CliEnvAction
config/loader/toml/__init__.py ×3 list[of_type] / dict[...] invalid-type-form built via types.GenericAlias (identical runtime object, plain value expression)
config/cli/parser.py ×2 list[action.type] invalid-type-form same GenericAlias construction

Left in place (no clean fix)

Verification

tox r -e type (ty 0.0.43) clean; ruff clean; targeted suites (config loader/CLI, env_select, req file, package pyproject, sets) all pass.

🤖 Generated with Claude Code

ty 0.0.43 narrows the negative branch of callable() on a Callable | T
union to object, breaking the constant/dynamic config definitions; wrap
the resolved value in the existing cast. It also infers the load type
variable as Never from factory_na's NoReturn return, collapsing
type[Never] | UnionType to UnionType; make factory_na generic so the
type variable binds from of_type instead.
GitHub is redirecting windows-2025 to windows-2025-vs2026 by 2026-06-15;
use the explicit label to drop the redirect notice.
Replace the blanket call-top-callable suppression with a precise cast to
the factory's call signature, so ty type-checks the lazy invocation
instead of ignoring it; the non-callable branch returns the value
directly.
Resolve the type errors directly instead of suppressing them:

- _overlapped stub: declare WriteFile so the Windows pipe write checks
- req/file.py: annotate the order lookup as dict[type, int]
- pyproject.py: cast the package definition to ConfigConstantDefinition
  (it is always registered via add_constant)
- env_select.py: type the mutually-exclusive group as _ActionsContainer
  and declare completer on _CliEnvAction

The remaining ignores are upstream ty bugs (linked issues), intentional
error-path tests, or genuine runtime monkeypatching.
to_list/to_set/to_dict and the argparse get_type helper built parametrized
generics with subscript syntax (list[of_type]), which ty reads as a type
expression and rejects. Construct them with types.GenericAlias instead -
an identical runtime object built as a plain value - dropping the
invalid-type-form suppressions.
Split the matrix os entry into a versioned runner image and a bare
display name (ubuntu/windows/macos), so required-check contexts no longer
churn when the runner image is bumped. The repository ruleset's required
status checks were updated to the new names. Runs on windows-2025-vs2026
while keeping the 'on windows' check label.
@gaborbernat gaborbernat enabled auto-merge (squash) June 4, 2026 19:19
@gaborbernat gaborbernat merged commit a20bd94 into tox-dev:main Jun 4, 2026
30 checks passed
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.

1 participant