Fix mypy type errors and achieve 100% appropriate type annotation coverage - #1278
Conversation
|
Hello @Copilot, thank you for submitting a PR! We will respond as soon as possible. สวัสดี @Copilot ขอบคุณที่ส่ง PR เข้ามา เราจะตอบกลับให้เร็วที่สุดเท่าที่จะทำได้ |
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds documentation explaining why the type-hint analyzer reports ~95% variable coverage while the codebase is effectively “100% appropriately typed”, and adjusts a number of assignments/formatting patterns to align with Python typing rules (notably avoiding annotated reassignments that trigger no-redef).
Changes:
- Added a variable-coverage analysis document describing the 58 “unannotated” cases and why they should remain unannotated.
- Removed/reworked annotated reassignments (and reformatted long lines) so variables/attributes are annotated once and then reassigned without re-annotation.
- Tightened a few typing-related details (e.g.,
str.maketranstable types,type: ignorecodes on optional imports).
Reviewed changes
Copilot reviewed 44 out of 44 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pythainlp/word_vector/core.py | Removes annotated attribute reassignments inside load_wordvector() to avoid redundant redefinitions. |
| pythainlp/wangchanberta/core.py | Formatting-only changes for long assignments and function signature wrapping. |
| pythainlp/util/wordtonum.py | Wraps long expression for readability/formatting. |
| pythainlp/util/thai_lunar_date.py | Formats long list literal for readability. |
| pythainlp/util/thai.py | Wraps long constant expression for formatting consistency. |
| pythainlp/util/syllable.py | Formatting + removes a redundant loop-variable annotation. |
| pythainlp/util/normalize.py | Formats long regex compilation and function signature wrapping. |
| pythainlp/util/keyboard.py | Updates maketrans table typing and adds casts to satisfy type checkers. |
| pythainlp/util/emojiconv.py | Formats function signature and lambda expression in regex substitution. |
| pythainlp/util/digitconv.py | Updates maketrans table typing and adds casts. |
| pythainlp/ulmfit/core.py | Refines rule list typing and formats long expressions/assignments. |
| pythainlp/transliterate/thaig2p.py | Wraps device initialization for formatting. |
| pythainlp/transliterate/thai2rom.py | Wraps device init / long calls and method signatures for formatting. |
| pythainlp/transliterate/royin.py | Removes annotated reassignments of _vowel_patterns and formats transformations. |
| pythainlp/transliterate/core.py | Expands type: ignore codes for optional import to include import-not-found. |
| pythainlp/translate/zh_th.py | Formats long transformer initialization assignments. |
| pythainlp/translate/tokenization_small100.py | Wraps long class attributes, call sites, and signatures for formatting. |
| pythainlp/translate/th_fr.py | Formats long transformer initialization assignments. |
| pythainlp/translate/small100.py | Formats long model/tokenizer initialization assignments. |
| pythainlp/translate/en_th.py | Removes annotated reassignment on .cuda() call (keeps the reassignment). |
| pythainlp/translate/core.py | Removes Any usage in reassignments (keeps union-typed self.model) and drops unused import. |
| pythainlp/translate/init.py | Formats __all__ list. |
| pythainlp/tools/path.py | Expands type: ignore codes for optional import to include import-not-found. |
| pythainlp/tokenize/nlpo3.py | Adds import-not-found ignore to one TYPE_CHECKING import and formats constants/errors. |
| pythainlp/tokenize/multi_cut.py | Formats __new__ signature. |
| pythainlp/tokenize/han_solo.py | Formats long assignment for readability. |
| pythainlp/tokenize/core.py | Removes annotated reassignments for attributes already declared/typed. |
| pythainlp/tag/named_entity.py | Formats long instantiation and method signature. |
| pythainlp/tag/crfchunk.py | Formats long context-manager assignment. |
| pythainlp/spell/words_spelling_correction.py | Formatting adjustments for long lines and signatures; minor whitespace normalization. |
| pythainlp/generate/core.py | Formats a long dict comprehension assignment. |
| pythainlp/cli/init.py | Removes annotated reassignment of sys.stdout/stderr and formats long lists. |
| pythainlp/classify/param_free.py | Formats long numpy assignment. |
| pythainlp/chat/core.py | Adds cast() around model output to ensure str and imports cast. |
| pythainlp/augment/wordnet.py | Formats a long wordnet.synsets() call. |
| pythainlp/augment/word2vec/thai2fit.py | Formats Word2VecAug instantiation. |
| pythainlp/augment/word2vec/ltw2v.py | Formats Word2VecAug instantiation. |
| pythainlp/augment/word2vec/core.py | Removes a type: ignore on assignment in the “model already loaded” branch and formats calls. |
| pythainlp/augment/word2vec/bpemb_wv.py | Formats long assignment from augment(). |
| pythainlp/augment/lm/wangchanberta.py | Formats tokenizer initialization call. |
| pythainlp/augment/lm/phayathaibert.py | Formats tokenizer/model initialization calls. |
| pythainlp/augment/lm/fasttext.py | Formats model loading calls. |
| pythainlp/init.py | Wraps long constant string for formatting. |
| build_tools/analysis/coverage-analysis.md | Adds documentation explaining the 58 “unannotated variables” cases and why coverage is effectively 100%. |
|
@copilot apply changes based on the comments in this thread and review the variable type annotation reassignments of the entire codebase once again. |
…uplicate annotations on reassignments Co-authored-by: bact <128572+bact@users.noreply.github.com>
Completed in ea77ca3. Applied changes based on review comments:
All changes tested with mypy (0 errors), ruff (all checks pass), and full test suite (114/114 pass). |
|
@copilot run test with "compact" test suite and fix any remaining issues |
…and remove unused type ignores Co-authored-by: bact <128572+bact@users.noreply.github.com>
Completed in 931cbfb. Ran compact test suite with all dependencies installed. Fixed 15 mypy errors that only appear when numpy and other compact dependencies are present:
All tests pass: 133/133 (core + compact), mypy: 0 errors, ruff: all checks passed. |
|
@copilot run test with "extra" test suite and fix any remaining issues |
… importlib_resources Co-authored-by: bact <128572+bact@users.noreply.github.com>
Completed in 2cbacaf. Ran extra test suite with all dependencies installed (compact + extra). Fixed 1 mypy error:
All tests pass: 165/165 (core + compact + extra), mypy: 0 errors with all dependencies, ruff: all checks passed. |
|



What do these changes do
Fixes all mypy type checking errors in the codebase (35 original errors + 16 with optional dependencies) and documents that all variables lacking type annotations are correctly unannotated per Python typing specifications. Adds comprehensive analysis showing the codebase has achieved 100% appropriate type coverage for both functions and variables.
What was wrong
The codebase had 35 mypy type errors across 15 files including:
str.maketrans()Additionally, the type hint analyzer reported 95.39% variable coverage, creating ambiguity about whether the remaining 58 variables needed annotations.
When compact dependencies (numpy, nlpo3, etc.) were installed, 15 additional mypy errors appeared due to type checking against actual library implementations.
When extra dependencies were installed (along with compact), 1 additional mypy error appeared due to
importlib_resourcesbeing available.How this fixes it
Fixed 35 original mypy errors:
cast()to handle dict type variance withstr.maketrans()Callabletypes from[[str], str]to[[Collection[str]], list[str]]to match actual signaturesimport-not-foundto type ignore comments for optional dependenciessys.stdout/sys.stderrreassignmentsAdditional fixes based on PR review:
augment/word2vec/core.pymodel parameter to acceptUnion[str, "KeyedVectors"]instead of juststrtransliterate/thaig2p.py,transliterate/thai2rom.py,transliterate/w2p.pytag/thainer.py,tokenize/multi_cut.py,tokenize/attacut.pytranslate/th_fr.py,translate/zh_th.py,translate/small100.pygenerate/core.py,augment/lm/fasttext.pyFixed 15 compact dependency errors:
tokenize/nlpo3.py, removedimport-not-foundignores that became unnecessary when nlpo3 is installed# type: ignore[no-any-return]for numpy array operations where mypy cannot infer exact types from operations likenp.exp(),np.array(), etc. Files affected:transliterate/w2p.py,transliterate/thai2rom_onnx.pyword_vector/core.py,ulmfit/core.pytag/wangchanberta_onnx.py,summarize/keybert.pyumt5_thaig2pimport intransliterate/core.pyfromimport-not-foundtoimport-untypedFixed 1 extra dependency error:
tools/path.py, removedimport-not-found,no-redefignores that became unnecessary whenimportlib_resourcesis installedVariable coverage analysis:
Analysis of 58 unannotated variables shows all are correctly unannotated:
no-redeferrorsdict[key] = valueno-redeferrorsExamples:
Documentation added:
build_tools/analysis/coverage-analysis.md- Complete breakdown of all 58 cases with file/line references, categorization, and references to PEP 484/526Test coverage:
The codebase now has 100% appropriate type coverage with zero mypy errors across all dependency configurations:
Your checklist for this pull request
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.