Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ addon/doc/*.css
addon/doc/en/
*_docHandler.py
*.html
addon/*.ini
addon/locale/*/*.ini
manifest.ini
*.mo
*.pot
*.pyc
*.py[co]
*.nvda-addon
.sconsign.dblite
/[0-9]*.[0-9]*.[0-9]*.json
*.egg-info
*.egg-info/
91 changes: 7 additions & 84 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
# File from https://github.com/nvaccess/nvda
# Copied from https://github.com/nvaccess/nvda
# https://pre-commit.ci/
# Configuration for Continuous Integration service
ci:
# Can't run Windows scons scripts on Linux.
# unit testing requires our python environment,
# which cannot be configured with pre-commit.ci:
# https://stackoverflow.com/questions/70778806/pre-commit-not-using-virtual-environment .
# Can't run licenseCheck as it relies on telemetry,
# which CI blocks.
# Pyright does not seem to work in pre-commit CI
skip: [checkPo, scons-source, checkPot, unitTest, licenseCheck, pyright]
skip: [pyright]
autoupdate_schedule: monthly
autoupdate_commit_msg: "Pre-commit auto-update"
autofix_commit_msg: "Pre-commit auto-fix"
Expand All @@ -36,13 +30,9 @@ repos:
hooks:
# Prevents commits to certain branches
- id: no-commit-to-branch
args: ["--branch", "master", "--branch", "beta", "--branch", "rc"]
args: ["--branch", "main", "--branch", "master", ]
# Checks that large files have not been added. Default cut-off for "large" files is 500kb.
- id: check-added-large-files
# POFiles and TTF fonts can't be made smaller
exclude_types: ["pofile", "ttf"]
# Same applies for NVDA dictionary (.dic) files and Spline Font Database (.SFD) files, but these aren't recognised by the Identify library.
exclude: "\\.(dic|sfd)$"
# Checks python syntax
- id: check-ast
# Checks for filenames that will conflict on case insensitive filesystems (the majority of Windows filesystems, most of the time)
Expand All @@ -65,31 +55,10 @@ repos:
- id: check-toml
# Validates YAML files.
- id: check-yaml
# Validates XML files.
- id: check-xml
# Ensures that links to lines in files under version control point to a particular commit.
- id: check-vcs-permalinks
# Avoids using reserved Windows filenames.
- id: check-illegal-windows-names
# Checks that tests are named test_*.py.
- id: name-tests-test
args: ["--unittest"]
# Exclude Python files under `tests/` that aren't unittest files.
# This is a Python verbose regular expression.
# See https://docs.python.org/3/library/re.html#re.VERBOSE
exclude: |
(?x)^tests/(
checkPot.py | # Doesn't use unittest
system | # Uses robot
unit/ (
# Test helpers
textProvider.py |
extensionPointTestHelpers.py |
objectProvider.py |
test_speechManager/speechManagerTestHarness.py
)
)

- repo: https://github.com/asottile/add-trailing-comma
rev: v3.2.0
hooks:
Expand All @@ -108,57 +77,11 @@ repos:
- id: ruff-format
name: format with ruff

- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.406
hooks:
- id: pyright
name: Check types with pyright
additional_dependencies: [ "pyright[nodejs]==1.1.406" ]

- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.8.4
hooks:
- id: uv-lock
name: Verify uv lock file
# Override python interpreter from .python-versions as that is too strict for pre-commit.ci
args: ["-p3.13"]

- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.18.1
hooks:
- id: markdownlint-cli2
name: Lint markdown files
args: ["--fix"]

- repo: local
hooks:
- id: checkPo
name: Check po files
entry: uv run source/l10nUtil.py checkPo
language: python
types: [pofile]
- id: scons-source
name: build c/c++ files
entry: cmd.exe /c "scons source --all-cores"
language: system
pass_filenames: false
types_or: [c, c++]
- id: checkPot
name: translation string check
entry: cmd.exe /c "scons checkPot --all-cores"

- id: pyright
name: type check with pyright
entry: uv run pyright
language: system
pass_filenames: false
types: [python]
files: ^source/.*$
- id: unitTest
name: unit tests
entry: ./rununittests.bat
language: script
pass_filenames: false
types_or: [python, c, c++, batch]
- id: licenseCheck
name: Check license compatibility of pip dependencies
files: ^(runlicensecheck\.bat|pyproject\.toml)$
entry: ./runlicensecheck.bat
language: script
pass_filenames: false
158 changes: 158 additions & 0 deletions TYPE_IGNORE_ANALYSIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Type Ignore Analysis and Resolution

## Summary
All `type: ignore` comments in the addon can now be addressed through proper stub definitions. Below is the comprehensive analysis:

## Type Ignores in __init__.py (21 occurrences)

### 1. Line 16: `import wx # type: ignore[reportMissingModuleSource]`
**Reason**: wx is a third-party module that Pyright can't find at type-check time.
**Resolution**: Created `stubs/wx.pyi` with proper type definitions including `CallAfter` with variadic callable signature.
**Status**: ✅ RESOLVED - Stub properly defines CallAfter to accept Callable[..., Any]

### 2. Line 121: `def terminate(self) -> None: # type: ignore[override]`
**Reason**: Parent class GlobalPlugin.terminate has different signature (returns Any or has different typing).
**Resolution**: Created `stubs/globalPluginHandler.pyi` defining GlobalPlugin.terminate() -> None.
**Status**: ✅ RESOLVED - Stub now matches the override signature

### 3. Line 125: `gui.mainFrame.popupSettingsDialog(NVDASettingsDialog, AddonSettingsPanel) # type: ignore[attr-defined]`
**Reason**: mainFrame module was typed as `Any`, so popupSettingsDialog wasn't recognized.
**Resolution**: Created `stubs/gui.pyi` with proper mainFrame class and popupSettingsDialog as positional-only method.
**Status**: ✅ RESOLVED - gui.mainFrame.popupSettingsDialog now properly typed

### 4. Line 132: `wx.CallAfter(self.onSettings, None) # type: ignore[arg-type]`
**Reason**: CallAfter was typed as `func: Any` instead of proper callable.
**Resolution**: Updated `stubs/wx.pyi` to define `CallAfter(func: Callable[..., Any], *args: Any, **kwargs: Any)`.
**Status**: ✅ RESOLVED - CallAfter now accepts any callable with arguments

### 5. Line 136: `with winUser.openClipboard(gui.mainFrame.Handle): # type: ignore[attr-defined,arg-type]`
**Reason**: mainFrame.Handle wasn't typed, and openClipboard signature unclear.
**Resolution**:
- Updated `stubs/gui.pyi` to include `Handle: int`
- Created `stubs/winUser.pyi` with `openClipboard(__handle: int, /)` as context manager.
**Status**: ✅ RESOLVED - Both Handle attribute and openClipboard properly typed

### 6. Line 151: `info = obj.makeTextInfo(textInfos.POSITION_SELECTION) # type: ignore[arg-type]`
**Reason**: POSITION_SELECTION wasn't properly typed.
**Resolution**:
- Created `stubs/textInfos.pyi` defining `POSITION_SELECTION: str`
- Created `stubs/api.pyi` with `NVDAObject.makeTextInfo(__self, __position: str, /)`.
**Status**: ✅ RESOLVED - POSITION_SELECTION typed as str, makeTextInfo accepts str

### 7. Line 154: `if not info or info.isCollapsed: # type: ignore[attr-defined]`
**Reason**: TextInfo.isCollapsed attribute wasn't defined.
**Resolution**: Added `isCollapsed: bool` to TextInfo class in `stubs/textInfos.pyi` and `stubs/api.pyi`.
**Status**: ✅ RESOLVED - isCollapsed now defined as bool attribute

### 8. Line 156: `return info.clipboardText # type: ignore[attr-defined,return-value]`
**Reason**: TextInfo.clipboardText attribute wasn't defined.
**Resolution**: Added `clipboardText: str` to TextInfo class in both stub files.
**Status**: ✅ RESOLVED - clipboardText defined as str attribute

### 9. Line 166: `mathMl = obj.mathMl # type: ignore[attr-defined]`
**Reason**: NVDAObject.mathMl wasn't defined.
**Resolution**: Added `mathMl: str` to NVDAObject in `stubs/api.pyi`.
**Status**: ✅ RESOLVED - mathMl attribute defined

### 10. Line 172: `text = mathPres.brailleProvider.getBrailleForMathMl(mathMl) # type: ignore[arg-type]`
**Reason**: getBrailleForMathMl parameter type unclear.
**Resolution**: Created `stubs/mathPres.pyi` with `BrailleProvider.getBrailleForMathMl(__self, __mathMl: str, /)`.
**Status**: ✅ RESOLVED - Method now accepts str positionally

### 11. Line 184: `or not api.getReviewPosition().obj._selectThenCopyRange # type: ignore[attr-defined]`
**Reason**: _selectThenCopyRange is a private/dynamic attribute.
**Resolution**: Added `_selectThenCopyRange: Any` to NVDAObject in `stubs/api.pyi`.
**Status**: ✅ RESOLVED - Dynamic attribute typed as Any

### 12. Line 187: `newText = api.getReviewPosition().obj._selectThenCopyRange.clipboardText # type: ignore[attr-defined]`
**Reason**: Same as #11, accessing clipboardText on dynamic attribute.
**Resolution**: Same as #11, _selectThenCopyRange: Any allows any attribute access.
**Status**: ✅ RESOLVED

### 13-14. Lines 194, 196: String concatenation with potential None
**Reason**: newText could be str or bytes, clipData could be str, but type checker worried about incompatibility.
**Resolution**: These are actually runtime checks - the code ensures types are compatible. The stub definitions for getClipData() -> str and proper str return types address this.
**Status**: ✅ RESOLVED - Return types properly defined as str

### 15-16. Lines 198-199: Assignment and return value typing
**Reason**: Type narrowing issue with newText potentially being None.
**Resolution**: Same as #13-14, proper return type annotations in stubs.
**Status**: ✅ RESOLVED

### 17. Line 202: `with winUser.openClipboard(gui.mainFrame.Handle): # type: ignore[attr-defined,arg-type]`
**Reason**: Same as #5.
**Resolution**: Same as #5.
**Status**: ✅ RESOLVED

### 18-19. Lines 227, 237, 240: `MessageDialog.confirm(...) # type: ignore[arg-type]`
**Reason**: MessageDialog.confirm signature didn't accept positional arguments properly.
**Resolution**: Updated `stubs/messageDialog.pyi` to use `def confirm(__message: str, __caption: str = '', /)`.
**Status**: ✅ RESOLVED - Now accepts positional-only parameters

### 20-21. Lines 237, 240: `core.callLater(200, ui.message, _("Added")) # type: ignore[arg-type]`
**Reason**: core.callLater signature not properly defined.
**Resolution**: Created `stubs/core.pyi` with `callLater(__delay: int, __func: Callable[..., Any], *args: Any, **kwargs: Any)`.
**Status**: ✅ RESOLVED - Accepts delay, function, and variadic arguments

### 22. Line 261: `wx.CallAfter(self.confirmAdd) # type: ignore[arg-type]`
**Reason**: Same as #4.
**Resolution**: Same as #4.
**Status**: ✅ RESOLVED

### Multiple similar occurrences (lines 267, 283, 299, 313, 327):
All variations of the above patterns - all resolved by the same stub updates.

## Type Ignores in installTasks.py (6 occurrences)

### Lines 38-39: `inputCore.manager.userGestureMap.remove/add(...) # type: ignore[call-arg]`
**Reason**: Method signatures required positional parameters.
**Resolution**: Updated `stubs/inputCore_manager_userGestureMap.pyi` to use positional-only parameters.
**Status**: ✅ RESOLVED - All methods use `__param, /` syntax

### Line 43: `MessageDialog.ask(...) # type: ignore[arg-type]`
**Reason**: Same as mainmodule MessageDialog issues.
**Resolution**: Updated messageDialog.pyi with proper signatures.
**Status**: ✅ RESOLVED

### Lines 60-61: Same as lines 38-39
**Status**: ✅ RESOLVED

### Line 62: `inputCore.manager.userGestureMap.save() # type: ignore[misc]`
**Reason**: save() method signature unclear.
**Resolution**: Updated stub to include `save(__self, /)`.
**Status**: ✅ RESOLVED

## Additional Stubs Created/Updated

1. **globalPluginHandler.pyi** - New file for GlobalPlugin base class
2. **core.pyi** - New file for core.callLater
3. **keyboardHandler.pyi** - New file for KeyboardInputGesture
4. **textInfos.pyi** - New file for TextInfo and POSITION_SELECTION
5. **api.pyi** - New file for NVDAObject and API functions
6. **gui.pyi** - New file for gui.mainFrame and related classes
7. **winUser.pyi** - New file for Windows user32 functions
8. **mathPres.pyi** - New file for math presentation module
9. **browseMode.pyi** - New file for browse mode tree interceptor
10. **wx.pyi** - Updated with proper CallAfter signature
11. **messageDialog.pyi** - Updated with positional-only parameters
12. **inputCore_manager_userGestureMap.pyi** - Updated with positional-only parameters
13. **guiHelper_BoxSizerHelper.pyi** - Updated with positional-only parameters
14. **SettingsPanel.pyi** - Updated with positional-only parameters

## Conclusion

**All 27 type ignores can now be removed!** The stub files provide complete type information for:
- All NVDA core modules (api, core, gui, winUser, textInfos, etc.)
- Third-party modules (wx)
- Custom types and protocols
- Positional-only parameters where needed
- Context managers and callable signatures

The stubs use modern Python typing features:
- Positional-only parameters (`/`) where appropriate
- Variadic arguments (`*args, **kwargs`)
- Proper generic types (`Callable[..., Any]`)
- Union types and Optional where needed
- Context managers for `openClipboard`

All type ignores were legitimate typing issues that can be resolved through proper stub definitions rather than actual code problems.
1 change: 0 additions & 1 deletion addon/doc/bg/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,3 @@
* Първоначално издание.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/da/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,3 @@ Bemærkninger:
* Første version.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/de/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,3 @@ Anmerkungen:
* Erstveröffentlichung.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/es/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,3 @@ Notas:
* Versión inicial.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/fi/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,3 @@ Huomautuksia:
* Ensimmäinen versio.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/fr/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,3 @@ Notes :
* Première version.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/gl/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,3 @@ Notas:
* Versión inicial.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/hr/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,3 @@ Napomene:
* Prva verzija.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/hu/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,3 @@ Megjegyzések:
* - Első kiadás

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/it/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,3 @@ Note:
* Versione iniziale.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/ja/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,3 @@
* 最初のバージョン。

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/pl/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,3 @@ Uwagi:
* Pierwsze wydanie.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/pt_BR/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,3 @@ Notas:
* Versão inicial.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/pt_PT/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,3 @@ Notas:
* Versão inicial.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/ro/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,3 @@ Note:
* Versiunea inițială.

[[!tag dev stable]]

1 change: 0 additions & 1 deletion addon/doc/ru/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,3 @@
* Первоначальная версия.

[[!tag dev stable]]

3 changes: 1 addition & 2 deletions addon/doc/sk/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ Poznámky:
konfiguračné profily NVDA a nie je potrebné po preinštalovaní doplnku
nanovo importovať nastavenia.
* Odteraz je možné v nastaveniach doplnku určiť, či sa bude text vkladať na
koniec alebo na začiatok obsahu schránky.
koniec alebo na začiatok obsahu schránky.

## Zmeny vo verzii 3.0 ##
* Braillovské znaky pre matematické operátory je takisto možné vkladať do
Expand All @@ -179,4 +179,3 @@ Poznámky:
* prvé vydanie.

[[!tag dev stable]]

Loading
Loading