Skip to content

Enable all ty rules with fewer than 100 diagnostics#20542

Draft
LeonarddeR wants to merge 14 commits into
nvaccess:masterfrom
LeonarddeR:tyCleanupTake1
Draft

Enable all ty rules with fewer than 100 diagnostics#20542
LeonarddeR wants to merge 14 commits into
nvaccess:masterfrom
LeonarddeR:tyCleanupTake1

Conversation

@LeonarddeR

@LeonarddeR LeonarddeR commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Link to issue number:

Part of #19393. Follow-up of #20474.

Summary of the issue:

When ty was introduced in #20474, every rule that fired on the existing codebase
was set to "ignore" in [tool.ty.rules] to reach a clean check without code
changes. This leaves those diagnostic categories unprotected against new
violations.

Description of user facing changes:

None in normal operation, though several latent bugs on rarely-hit paths are
fixed (e.g. IAccessible.isPointInObject raised TypeError whenever reached,
and MathCAT's "unable to copy math" error message raised instead of being
spoken).

Description of developer facing changes:

  • All 23 ty rule exclusions with fewer than 100 diagnostics are removed;
    only the seven rules with 100+ pre-existing errors remain ignored.
  • ty now enforces these rules on new code; remaining false positives are
    suppressed with line-scoped # ty: ignore[<rule>] comments.
  • lxml-stubs added to the lint dependency group so ty can resolve lxml.etree.

Description of development approach:

The 278 diagnostics behind the removed exclusions were classified site by site
into real fixes (~155), latent bugs (7) and false positives to suppress (~120).
Commits are ordered so ty check passes at every commit: real fixes first,
then one commit per rule removing its exclusion and adding its inline
suppressions atomically. Commit overview:

  • 40efc02: Add explicit submodule imports flagged by ty's
    possibly-missing-submodule rule (48 sites).
  • ff763db: Add missing | None to parameter annotations with None
    defaults (invalid-parameter-default, 11 sites).
  • e50fd1f: Replace deprecated abstractproperty (stacked
    @property/@abstractmethod, with baseObject's dynamic
    abstractproperty(fget=...) calls marking the accessor functions abstract
    instead), Logger.warn and datetime.utcnow usages.
  • 70c3423: Import OrderedDict from collections rather than typing
    where instantiated.
  • aabbd5a: Correct wrong annotations (~45 sites): bare Optional,
    functions/values used as types, type[...] for class-valued parameters,
    generator yield types, wrong return types, Optional-flow guards, and
    scalar/tuple overloads for gui.dpiScalingHelper.scaleSize.
  • 8d421ed: Fix latent bugs surfaced by ty: IAccessible.isPointInObject
    passed a surplus argument to accHitTest; powerpnt passed a bogus
    stack_info keyword to ValueError; log.exception was given %-style
    arguments NVDA's override does not accept; MathCAT called pgettext without
    its message argument; the albatross driver called the log instance
    directly; handyTech constructed its model via MODELS.get despite the
    preceding membership guard; _wtsApi32.WTS_LockState was annotated as an
    enum instance while holding the class.
  • f139cc6: Enforce unresolved-import; add lxml-stubs and suppress
    runtime-generated or optional native modules (comtypes.gen, brlapi,
    libmathcat_py, _buildVersion, fast_diff_match_patch).
  • 1aaec13: Enforce missing-argument; suppress instance-reassigned methods
    and wx stub gaps (ShowModal, PersistenceManager, GetTopLevelWindows,
    IsMainThread) and metaclass construction.
  • 3112c00: Enforce call-non-callable, not-iterable and call-top-callable;
    suppress init-time callback invariants, hasattr-guarded handlers,
    FlagValueEnum's EnumMeta-derived base and scalar-or-tuple returns.
  • 6414a2e: Enforce no-matching-overload; suppress str.join/replace
    element-type widening and wx/comtypes stub gaps.
  • fb538e3: Enforce invalid-type-form; suppress ctypes values in type
    positions and the stub-less regex package's Pattern.
  • 2903edf: Enforce deprecated (keeping codecs.open: builtin open
    differs in newline handling and line splitting), unknown-argument,
    invalid-super-argument, too-many-positional-arguments, invalid-yield,
    invalid-attribute-access, shadowed-type-variable and unsupported-base.
  • 9c10011: Remove the exclusions whose diagnostics are all fixed
    (possibly-missing-submodule, invalid-parameter-default,
    invalid-enum-member-annotation, mismatched-type-name, redundant-cast,
    invalid-attribute-override, empty-body, unused-type-ignore-comment).
  • 5d5bcf2: Complete IUIAutomationTextRangeT.findText's signature (dropping
    its too-many-positional-arguments suppression) and use modern annotation
    syntax (builtin generics, PEP 604 unions, collections.abc) on lines this PR
    already modified.

Testing strategy:

  • uv run ty check exits 0; re-running with all 23 removed rules explicitly
    forced on reports zero diagnostics.
  • uv run pyright still exits 0.
  • All pre-commit hooks pass.
  • Full unit test suite passes.
  • Manually smoke tested NVDA from source.

Known issues with pull request:

  • The seven high-volume rules (unresolved-attribute, not-subscriptable,
    invalid-argument-type, invalid-assignment, unsupported-operator,
    invalid-method-override, invalid-return-type) remain ignored; re-enabling
    them is left for follow-ups.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

🤖 Generated with Claude Code

LeonarddeR and others added 13 commits July 21, 2026 16:57
…dule rule

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lid-parameter-default)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…usages (ty deprecated)

abstractproperty becomes property stacked on abstractmethod; baseObject's dynamic
abstractproperty(fget=...) calls now mark the accessor functions abstract instead,
which property propagates via __isabstractmethod__.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ated (ty call-non-callable)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eld and friends)

Also adds scalar/tuple overloads to gui.dpiScalingHelper.scaleSize so callers get
precise result types, and corrects the return annotations of
review.getPositionForCurrentMode, UIATextInfo._getFormatFieldAtRange and
_asyncioEventLoop.utils.runCoroutine to match what they actually return.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- IAccessible.isPointInObject passed a surplus IAccessibleChildID argument to
  IAccessibleHandler.accHitTest, raising TypeError whenever reached.
- powerpnt passed a bogus stack_info keyword to ValueError.
- speechDictHandler's SpeechDict.sub passed %-style arguments to NVDA's
  Logger.exception override, which takes none.
- MathCAT called pgettext without the message argument, raising TypeError.
- The albatross driver called the log instance directly instead of log.debug.
- handyTech constructed the model via MODELS.get despite the preceding membership
  guard; use subscription so the result is never None.
- _wtsApi32 annotated WTS_LockState as an enum instance while it holds the class.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lxml-stubs makes lxml.etree resolvable; the remaining sites (runtime-generated
comtypes.gen stubs, optional native modules, build-generated _buildVersion and
the system test synth driver moved at runtime) get line-scoped suppressions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All sites are runtime-correct patterns ty cannot model: methods reassigned on
the instance (MessageDialog.ShowModal, NonReEntrantTimer.run), wx stubs with a
spurious self on module functions and old-style classmethods
(GetTopLevelWindows, IsMainThread, PersistenceManager), and dynamic metaclass
construction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All sites are runtime-correct invariants ty cannot model: callbacks assigned
during initialize/init, hasattr-guarded dynamic handlers, FlagValueEnum's
EnumMeta-derived annotation-only base, scalar-or-tuple conditional returns and
bdDetect's heterogeneous per-communication-type dict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The str.join/replace sites pass element types ty infers wider than str but that
are str at runtime; the rest are wx and comtypes stub gaps (Literal-typed
GetActiveObject, malformed GetLabelText overload set, constrained-TypeVar
dispatch handled via isinstance) and a hasattr-synthesized pattern attribute.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The remaining sites use ctypes values (POINTER results, WINFUNCTYPE prototypes
and array types) in type positions, the stub-less regex package's Pattern, or a
Robot Framework module-as-library annotation, none of which ty can express.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o-many-positional-arguments, invalid-yield, invalid-attribute-access, shadowed-type-variable and unsupported-base rules

The suppressed sites are codecs.open (kept: builtin open differs in newline
handling and line splitting), NVDA's Logger kwargs passed through inherited
methods, cooperative-MRO and dataclass-via-ClassVar constructors, same-name
overlay class super() calls, comtypes findText, class-level caching, dynamic
wx base classes and ctypes buffer slicing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
possibly-missing-submodule, invalid-parameter-default,
invalid-enum-member-annotation, mismatched-type-name, redundant-cast,
invalid-attribute-override, empty-body and unused-type-ignore-comment now have
zero diagnostics; only the seven rules with 100+ pre-existing errors stay
ignored.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@LeonarddeR

Copy link
Copy Markdown
Collaborator Author

@seanbudd I prototyped this pr with Claude to get rid of the exclusions.
As you can see, we basically use one commit per fix.
That said, may be you'd like another approach? For example, we can also add exclusions in code first and then fix them in a follow up.

…tions on touched lines

findText in NVDA's own protocol stub lacked its text/backward/ignoreCase
parameters, which is what the too-many-positional-arguments suppression was
hiding; complete the signature and drop the suppression. Also replace legacy
typing generics (List, Dict, Tuple, Union, Optional, typing.Callable,
typing.Generator) with builtin generics, PEP 604 unions and collections.abc
imports on lines this branch already modified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 21, 2026 16:13

Copilot AI 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.

Pull request overview

This PR tightens NVDA’s type-checking posture under ty by re-enabling previously-ignored rules (those with <100 diagnostics), fixing a set of real type issues/latent bugs, and suppressing remaining false positives with line-scoped # ty: ignore[...] comments. It also adds lxml-stubs to support ty’s import/type resolution for lxml.etree.

Changes:

  • Re-enable 23 ty rules (keeping only the highest-volume rules ignored) and add targeted inline suppressions where needed.
  • Apply a large set of typing/annotation corrections and a handful of runtime bug fixes uncovered by ty.
  • Add lxml-stubs to the lint dependency group to improve ty’s resolution of lxml types.

Reviewed changes

Copilot reviewed 117 out of 118 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
uv.lock Add lxml-stubs lock entries
pyproject.toml Re-enable ty rules; add lxml-stubs to lint deps
tests/unit/textProvider.py Inline ty suppression for offsets tuple
tests/unit/test_speechManager/speechManagerTestHarness.py Inline ty suppression for iterability
tests/unit/test_speechManager/init.py Inline ty suppression for tuple unpack
tests/unit/test_remote/test_remoteClient.py Narrow type-check ignore to pyright rule
tests/unit/test_remote/test_bridge.py Inline ty suppression for iterability
tests/unit/test_messageDialog.py Inline ty suppression for wx stub mismatch
tests/unit/test_hwIo_ble.py Inline ty suppression for mock .close()
tests/unit/test_braille/test_brailleDisplayDrivers.py Suppress optional-module import for ty
tests/system/robot/startupShutdownNVDA.py Use local datetime.now() for crash timing
tests/system/libraries/VSCodeLib.py Suppress invalid type form for Robot libs
tests/system/libraries/SystemTestSpy/speechSpyGlobalPlugin.py Modernize typing; suppress unresolved import
tests/system/libraries/NvdaLib.py Return-type tightening; use local datetime.now()
tests/system/libraries/NotepadLib.py Suppress invalid type form for Robot libs
tests/system/libraries/ChromeLib.py Suppress invalid type form for Robot libs
source/winKernel.py Suppress ty invalid type form for callback type
source/winConsoleHandler.py Add explicit submodule import for ty
source/winAPI/sessionTracking.py Use collections.abc typing; suppress ty type-form gaps
source/winAPI/_wtsApi32.py Fix enum-class typing; suppress ctypes typing gaps
source/virtualBuffers/gecko_ia2.py Suppress generated COM import for ty
source/utils/displayString.py Replace deprecated abstractproperty usage
source/utils/_deprecate.py Replace deprecated abstractproperty usage
source/updateCheck.py Suppress ty for timer-executed callback typing
source/UIAHandler/types.py Fix findText signature to match usage
source/UIAHandler/_remoteOps/remoteTypes/textRange.py Suppress ty invalid type form for POINTER generic
source/UIAHandler/_remoteOps/remoteTypes/element.py Suppress ty invalid type form for POINTER generic
source/UIAHandler/_remoteOps/remoteTypes/init.py Remove redundant cast; suppress ty arg-name mismatches
source/UIAHandler/_remoteOps/remoteAPI.py Suppress ty invalid-yield for remote builder DSL
source/UIAHandler/_remoteOps/builder.py Replace deprecated abstractproperty; adjust opcode typing
source/touchHandler.py Suppress overload mismatch for join
source/textUtils/uniscribe.py Suppress ty invalid-yield false positive
source/textUtils/_wordSeg/wordSegStrategy.py Suppress ctypes typing gaps; suppress overload mismatch
source/textUtils/init.py Replace deprecated abstractproperty usage
source/textInfos/offsets.py Prefer local Offsets; suppress tuple typing issue
source/synthDrivers/oneCore.py Modernize typing; suppress ty invalid type form
source/synthDrivers/espeak.py Suppress ty super() typing false positive
source/synthDrivers/_espeak.py Suppress ty callable false positives
source/speechXml.py Suppress ty callable false positive for callback
source/speechDictHandler/types.py Suppress ty invalid type form for regex Pattern; fix log formatting
source/speech/speechWithoutPauses.py Fix incorrect type name (SpeechSequence)
source/speech/speech.py Modernize annotations; suppress overload mismatch for join
source/speech/sayAll.py Tighten callable types; suppress ty callable false positive
source/scriptHandler.py Tighten generator yield typing
source/review.py Adjust return typing for review-position helper
source/nvwave.py Remove redundant annotation assignment
source/NVDAObjects/window/excel.py Add explicit comtypes submodules; suppress arg-name mismatch
source/NVDAObjects/window/edit.py Add explicit ctypes.wintypes import for ty
source/NVDAObjects/UIA/init.py Fix format field return type; widen generator yields
source/NVDAObjects/JAB/init.py Fix typing for re.Match
source/NVDAObjects/IAccessible/sysListView32.py Add explicit ctypes.wintypes import; suppress super() typing
source/NVDAObjects/IAccessible/ia2Web.py Suppress generated COM import for ty
source/NVDAObjects/IAccessible/adobeAcrobat.py Suppress generated COM import for ty
source/NVDAObjects/IAccessible/init.py Fix accHitTest call signature; tighten event arg typing
source/NVDAObjects/behaviors.py Tighten diff-algo return typing
source/NVDAObjects/init.py Add explicit submodule import; suppress ty constructor typing
source/monkeyPatches/comtypesMonkeyPatches.py Suppress ty callable false positive
source/mathPres/MathCAT/preferences.py Suppress optional native module; remove Enum const annotations
source/mathPres/MathCAT/MathCAT.py Suppress optional native module; fix pgettext call
source/mathPres/MathCAT/localization.py Suppress optional native module
source/logHandler.py Tighten optional typing; suppress overload mismatch on replace
source/locationHelper.py Suppress ty positional-args mismatch
source/l10nUtil.py Suppress ty deprecated for codecs.open
source/keyboardHandler.py Fix modifiers type to set[_ModifierT]
source/inputCore.py Suppress ty callable/overload false positives
source/IAccessibleHandler/internalWinEventHandler.py Suppress ty callable false positive
source/hwPortUtils.py Suppress ty invalid type form for ctypes tuple typing
source/hwIo/ioThread.py Modernize typing; suppress ctypes typing gaps; suppress callable false positive
source/hwIo/base.py Add explicit submodule imports; suppress callable false positive
source/gui/settingsDialogs.py Suppress wx stub mismatch on ShowModal
source/gui/nvdaControls.py Suppress ty callable/iterability/type-form false positives
source/gui/message.py Suppress wx stub mismatches around ShowModal / main-thread checks
source/gui/installerGui.py Suppress wx stub mismatch on ShowModal
source/gui/guiHelper.py Suppress wx stub mismatches; suppress ty base-class typing warnings
source/gui/exit.py Fix singleton __new__; handle missing pending update safely
source/gui/dpiScalingHelper.py Add overloads for scaleSize; update license header
source/gui/addonStoreGui/controls/details.py Fix wx.Size construction for tuple return
source/gui/addonStoreGui/controls/actions.py Use wx.Point for menu position typing
source/gui/init.py Avoid assuming pending update always present; suppress wx stub gaps
source/globalCommands.py Tighten enumClass typing; suppress ty iterable/callable false positives
source/eventHandler.py Add explicit submodule import; suppress callable false positives
source/documentNavigation/paragraphHelper.py Modernize optional typing
source/diffHandler.py Suppress optional native module import for ty
source/core.py Add explicit submodule imports; suppress wx stub gap
source/config/profileUpgradeSteps.py Guard missing profile filename
source/config/configFlags.py Add explicit submodule import for ty
source/config/init.py Tighten typing; suppress ty unknown-argument on logging kwargs
source/comHelper.py Suppress overload mismatch for comtypes helper
source/characterProcessing.py Suppress ty deprecated for codecs.open; simplify tuple typing
source/buildVersion.py Suppress build-generated module import for ty
source/browseMode.py Simplify tuple construction; suppress join overload mismatch
source/brailleDisplayDrivers/handyTech.py Avoid .get() after membership check
source/brailleDisplayDrivers/freedomScientific.py Suppress join overload mismatch
source/brailleDisplayDrivers/eurobraille/constants.py Fix OrderedDict import source
source/brailleDisplayDrivers/brltty.py Suppress optional module import for ty
source/brailleDisplayDrivers/brailleNote.py Suppress join overload mismatch
source/brailleDisplayDrivers/albatross/driver.py Fix license header; use log.debug correctly
source/bdDetect.py Suppress ty iterability/callable false positives; modernize optional typing
source/baseObject.py Replace deprecated abstractproperty; fix dynamic abstract property handling
source/appModules/utorrent.py Suppress ty iterability false positive
source/appModules/tween.py Suppress ty iterability false positive
source/appModules/powerpnt.py Remove invalid stack_info kwarg for ValueError
source/appModules/devenv.py Add explicit comtypes submodule import
source/appModuleHandler.py Suppress callable false positive
source/api.py Add explicit submodule import
source/addonStore/models/status.py Fix OrderedDict import source
source/addonStore/models/channel.py Fix OrderedDict import source
source/addonHandler/init.py Use explicit importlib submodules for ty
source/_synthDrivers32/sapi4.py Rename NamedTuple type for ty rule compliance
source/_remoteClient/transport.py Replace deprecated warn with warning
source/_remoteClient/localMachine.py Adjust enum nonmember constants typing
source/_remoteClient/dialogs.py Suppress wx PersistenceManager stub gaps
source/_remoteClient/client.py Suppress wx stub gap; modernize optional typing
source/_magnifier/magnifier.py Tighten timer callback typing
source/_bridge/base.py Modernize optional typing
source/_asyncioEventLoop/utils.py Correct Future return type from thread-safe scheduling
site_scons/site_tools/listModules.py Add explicit SCons submodule imports
runtime-builders/synthDriverHost32/setup-runtime.py Use explicit importlib machinery import

Comment thread source/review.py


def getPositionForCurrentMode(obj: NVDAObject) -> Union[textInfos.TextInfo, ScriptableObject]:
def getPositionForCurrentMode(obj: NVDAObject) -> tuple[textInfos.TextInfo, ScriptableObject]:
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.

2 participants