Skip to content

Refactor type: ignore suppressions to proper type fixes#1235

Merged
bact merged 7 commits intodevfrom
copilot/fix-mypy-issues
Jan 30, 2026
Merged

Refactor type: ignore suppressions to proper type fixes#1235
bact merged 7 commits intodevfrom
copilot/fix-mypy-issues

Conversation

Copy link
Contributor

Copilot AI commented Jan 30, 2026

What does this changes

Replaces type suppression comments with proper type-safe solutions where feasible. Eliminates 11 of 12 type: ignore comments across morse encoding, tokenization, and soundex modules.

What was wrong

Previous fixes added type: ignore comments to suppress mypy errors rather than addressing root causes:

  • Lambda functions with default parameter capture couldn't infer types (morse.py)
  • Union type narrowing required manual assertions (han_solo.py)
  • List mutation with None values needed suppression (soundex.py)

How this fixes it

morse.py: Replace map(lambda x, g=dict.get: g(x, " "), text) with generator expressions (dict.get(x, " ") for x in text). Removes 4 suppressions.

han_solo.py: Use typing.cast() for explicit type narrowing on Union types. Add proper Union[int, str] annotation for mutable variable. Removes 7 suppressions.

soundex.py: Retain single type: ignore[call-overload] - changing to list[str | None] cascades 13 downstream errors. Current approach is minimal.

Example:

# Before
features[key] = 1  # type: ignore[call-overload]

# After  
cast(dict[str, int], features)[key] = 1

Your checklist for this pull request

  • Passed code styles and structures
  • Passed code linting checks and unit test
Original prompt

Run mypy and try to fix safe or less controversial issues.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 3 commits January 30, 2026 00:34
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copilot AI changed the title [WIP] Run mypy and resolve safe type issues Fix safe mypy type issues across 8 files Jan 30, 2026
Copilot AI requested a review from bact January 30, 2026 00:46
Refactor _find_month function to return 0 instead of None when not found. Update type hinting and adjust month variable assignment in date parsing.
@coveralls
Copy link

coveralls commented Jan 30, 2026

Coverage Status

coverage: 53.521% (-0.04%) from 53.561%
when pulling c1afb66 on copilot/fix-mypy-issues
into bb14ad5 on dev.

Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copilot AI changed the title Fix safe mypy type issues across 8 files Refactor type: ignore suppressions to proper type fixes Jan 30, 2026
@sonarqubecloud
Copy link

@bact bact marked this pull request as ready for review January 30, 2026 01:10
@bact bact merged commit 03b92ab into dev Jan 30, 2026
30 checks passed
@bact bact requested a review from Copilot January 30, 2026 01:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors type suppression comments (type: ignore) to use proper type-safe solutions. It successfully eliminates 11 of 12 type ignore comments by replacing lambda functions with generator expressions in morse.py, adding explicit type annotations in multiple tokenization modules, and using typing.cast() for Union type narrowing in han_solo.py.

Changes:

  • Replaced lambda functions with default parameter capture with cleaner generator expressions in morse encoding/decoding
  • Added explicit type annotations for defaultdict and list variables across tokenization and summarization modules
  • Changed _find_month return type from Optional[int] to int with 0 sentinel value
  • Used typing.cast() to handle Union[dict, list] type narrowing in han_solo.py
  • Improved type annotation specificity (e.g., Optional[object] to Optional[ThapSap])

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pythainlp/util/morse.py Refactored lambda functions with default parameters to generator expressions for morse encoding/decoding
pythainlp/util/date.py Changed _find_month return type from Optional[int] to int, removed unused variable declarations
pythainlp/transliterate/wunsen.py Improved type annotation from Optional[object] to Optional[ThapSap]
pythainlp/tokenize/multi_cut.py Added explicit type annotation for defaultdict[int, list[str]]
pythainlp/tokenize/longest.py Added explicit type annotations for list[str] and list[int] variables
pythainlp/tokenize/han_solo.py Used typing.cast() for Union type narrowing instead of type: ignore comments
pythainlp/summarize/freq.py Added explicit type annotations for defaultdict instances
pythainlp/soundex/prayut_and_somchaip.py Retained single type: ignore comment with justification

if j in text:
return i + 1
return None
return 0 # Not found in list
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the return type from Optional[int] to int and returning 0 for "not found" is problematic. The value 0 is ambiguous because it could be confused with a valid index (though months are 1-indexed, making this slightly safer). However, this breaks the API contract - the function previously could distinguish between "month found" and "month not found" via None, which is now lost.

This change could cause silent failures: if a month is not found in the input text, the function will now return 0, which will be passed to datetime() constructor at line 314. The datetime constructor expects month values 1-12, and passing 0 will raise a ValueError at runtime rather than handling the case gracefully.

A better approach would be to either:

  1. Keep the Optional[int] return type and handle None appropriately in the caller
  2. Raise an exception when month is not found rather than returning a sentinel value
Suggested change
return 0 # Not found in list
raise ValueError(f"Month not found in text: {text!r}")

Copilot uses AI. Check for mistakes.
Comment on lines 103 to +106
if return_type == "dict":
features[left_key] = 1
cast(dict[str, int], features)[left_key] = 1
else:
features.append(left_key)
cast(list[str], features).append(left_key)
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using cast() to work around Union type narrowing defeats the purpose of static type checking and can lead to runtime errors. The cast() function tells the type checker to trust that the value is of a certain type without actually performing any runtime validation.

A more type-safe approach would be to properly narrow the Union type through control flow. Instead of using cast(), you could check the type after initialization:

if return_type == "dict":
    assert isinstance(features, dict)
    features[left_key] = 1
else:
    assert isinstance(features, list)
    features.append(left_key)

Or refactor the code to avoid the Union type altogether by using separate variables or a more structured approach. The repeated casting throughout the method (lines 104, 106, 122, 124, 133, 135) suggests the control flow could be simplified.

Copilot uses AI. Check for mistakes.
Comment on lines 121 to +124
if return_type == "dict":
features[right_key] = 1
cast(dict[str, int], features)[right_key] = 1
else:
features.append(right_key)
cast(list[str], features).append(right_key)
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using cast() to work around Union type narrowing defeats the purpose of static type checking and can lead to runtime errors. The cast() function tells the type checker to trust that the value is of a certain type without actually performing any runtime validation.

A more type-safe approach would be to properly narrow the Union type through control flow. Instead of using cast(), you could check the type after initialization or refactor the code to avoid the Union type altogether by using separate variables or a more structured approach.

Copilot uses AI. Check for mistakes.
Comment on lines 132 to +135
if return_type == "dict":
features[ngram_key] = 1
cast(dict[str, int], features)[ngram_key] = 1
else:
features.append(ngram_key)
cast(list[str], features).append(ngram_key)
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using cast() to work around Union type narrowing defeats the purpose of static type checking and can lead to runtime errors. The cast() function tells the type checker to trust that the value is of a certain type without actually performing any runtime validation.

A more type-safe approach would be to properly narrow the Union type through control flow. Instead of using cast(), you could check the type after initialization or refactor the code to avoid the Union type altogether by using separate variables or a more structured approach.

Copilot uses AI. Check for mistakes.
@bact
Copy link
Member

bact commented Jan 30, 2026

@copilot apply changes based on the comments in this thread

@bact bact added the refactoring a technical improvement which does not add any new features or change existing features. label Jan 30, 2026
@bact bact added this to the 5.3 milestone Jan 30, 2026
@bact bact deleted the copilot/fix-mypy-issues branch January 30, 2026 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoring a technical improvement which does not add any new features or change existing features.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants