Skip to content
Closed
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
110 changes: 81 additions & 29 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,7 @@ dev = [
"tox>=4.30.3",
]

docs = [
"Sphinx>=6.2",
"sphinx-copybutton>=0.5.2",
"sphinx-rtd-theme>=3.1.0",
]
docs = ["Sphinx>=6.2", "sphinx-copybutton>=0.5.2", "sphinx-rtd-theme>=3.1.0"]

## 2) Feature sets #######################################

Expand Down Expand Up @@ -217,10 +213,7 @@ noauto-torch = [
]

# TensorFlow-based dependencies - for tests.noauto_tensorflow
noauto-tensorflow = [
"deepcut>=0.7.0",
"numpy>=1.26.0",
]
noauto-tensorflow = ["deepcut>=0.7.0", "numpy>=1.26.0"]

# ONNX Runtime-based dependencies - for tests.noauto_onnx
noauto-onnx = [
Expand All @@ -231,15 +224,11 @@ noauto-onnx = [
]

# Cython-based dependencies - for tests.noauto_cython
noauto-cython = [
"phunspell>=0.1.6",
]
noauto-cython = ["phunspell>=0.1.6"]

# Network-dependent tests - for tests.noauto_network
# These tests require network access but minimal dependencies
noauto-network = [
"huggingface-hub>=0.16.0",
]
noauto-network = ["huggingface-hub>=0.16.0"]

# Full dependencies - pinned where available
full = [
Expand Down Expand Up @@ -304,12 +293,7 @@ thainlp = "pythainlp.__main__:main"
packages = ["pythainlp"]

[tool.hatch.build.targets.sdist]
include = [
"pythainlp/",
"tests/",
"LICENSE",
"README.md",
]
include = ["pythainlp/", "tests/", "LICENSE", "README.md"]

# Bumpversion configuration
[tool.bumpversion]
Expand Down Expand Up @@ -399,7 +383,17 @@ select = [
extend-ignore = ["E402", "E501", "E722", "S101", "S202", "S301", "S310"]

[tool.tox]
env_list = ["py39", "py310", "py311", "py312", "py313", "py314", "pypy310", "pypy311", "ruff"]
env_list = [
"py39",
"py310",
"py311",
"py312",
"py313",
"py314",
"pypy310",
"pypy311",
"ruff",
]
skip_missing_interpreters = true

[tool.tox.env_run_base]
Expand All @@ -414,8 +408,20 @@ basepython = "pypy3.11"

[tool.tox.env.ruff]
basepython = "python"
deps = ["ruff"]
commands = [["ruff", "check", "pythainlp"], ["ruff", "format", "--check", "pythainlp"]]
deps = "ruff"
commands = [
[
"ruff",
"check",
"pythainlp",
],
[
"ruff",
"format",
"--check",
"pythainlp",
],
]
skip_install = true

# Mypy configuration
Expand All @@ -429,8 +435,11 @@ python_version = "3.9"
show_column_numbers = true
show_error_code_links = true
show_error_context = true
strict_optional = true
strict = true
strict_equality = true
strict_equality_for_none = true
strict_optional = true

warn_no_return = true
Comment on lines +441 to 443

Copilot AI Mar 20, 2026

Copy link

Choose a reason for hiding this comment

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

Enabling global mypy strict = true can introduce many new type-checking failures across the project and CI (the repo runs mypy pythainlp in PRs). If this PR isn’t also updating the codebase to be strict-clean, consider scoping strictness via per-module overrides or enabling the stricter flags incrementally.

Copilot uses AI. Check for mistakes.
warn_redundant_casts = true
warn_return_any = true
Expand All @@ -440,64 +449,107 @@ warn_unreachable = true

# Per-module options for stricter checking on foundation modules
[[tool.mypy.overrides]]
module = [
"pythainlp.tools.*",
"pythainlp.cli.*",
]
module = ["pythainlp.tools.*", "pythainlp.cli.*"]
disallow_untyped_defs = true
disallow_incomplete_defs = true

# Ignore missing imports for optional dependencies
[[tool.mypy.overrides]]
module = [
"attacut",
"attacut.*",
"attaparse",
"attaparse.*",
"bpemb",
"bpemb.*",
"budoux",
"budoux.*",
"deepcut",
"deepcut.*",
"emoji",
"emoji.*",
"epitran",
"epitran.*",
"esupar",
"esupar.*",
"fairseq",
"fairseq.*",
"fastai",
"fastai.*",
"fastcoref",
"fastcoref.*",
"gensim",
"gensim.*",
"huggingface_hub",
"huggingface_hub.*",
"icu",
"icu.*",
"importlib_resources",
"importlib_resources.*",
"khamyo",
"khamyo.*",
"khanaa",
"khanaa.*",
"multiel",
"multiel.*",
"nltk",
"nltk.*",
"nlpo3",
"nlpo3.*",
"numpy",
"numpy.*",
"onnxruntime",
"onnxruntime.*",
"oskut",
"oskut.*",
"pandas",
"pandas.*",
"panphon",
"panphon.*",
"phunspell",
"phunspell.*",
"pycrfsuite",
"pycrfsuite.*",
"pyicu",
"pyicu.*",
"sacremoses",
"sacremoses.*",
"sefr_cut",
"sefr_cut.*",
"sentencepiece",
"sentencepiece.*",
"sentence_transformers",
"sentence_transformers.*",
"spacy",
"spacy.*",
"spacy_thai",
"spacy_thai.*",
"ssg",
"ssg.*",
"stanza",
"stanza.*",
"symspellpy",
"symspellpy.*",
"thai_nner",
"thai_nner.*",
"tltk",
"tltk.*",
"torch",
"torch.*",
"tqdm",
"tqdm.*",
"transformers",
"transformers.*",
"ufal",
"ufal.*",
"ufal.chu_liu_edmonds.*",
"word2word",
"word2word.*",
"wtpsplit",
"wtpsplit.*",
"wunsen",
"wunsen.*",
"yaml",
"yaml.*",
]
ignore_missing_imports = true
Expand Down
8 changes: 4 additions & 4 deletions pythainlp/ancient/currency.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from __future__ import annotations


def convert_currency(value: float, from_unit: str) -> dict:
def convert_currency(value: float, from_unit: str) -> dict[str, float]:
"""Convert ancient Thai currency to other units

* เบี้ย (Bia)
Expand All @@ -23,7 +23,7 @@ def convert_currency(value: float, from_unit: str) -> dict:
:param str from_unit: currency unit \
('เบี้ย', 'อัฐ', 'ไพ', 'เฟื้อง', 'สลึง', 'บาท', 'ตำลึง', 'ชั่ง')
:return: Thai currency
:rtype: dict
:rtype: dict[str, float]

:Example:
::
Expand Down Expand Up @@ -63,8 +63,8 @@ def convert_currency(value: float, from_unit: str) -> dict:
# start from 'อัฐ'
value_in_att = value * conversion_factors_to_att[from_unit]

# Calculate values ​​in other units
results = {}
# Calculate values in other units
results: dict[str, float] = {}
for unit, factor in conversion_factors_to_att.items():
results[unit] = value_in_att / factor

Expand Down
4 changes: 2 additions & 2 deletions pythainlp/augment/word2vec/bpemb_wv.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations

from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, cast

from pythainlp.augment.word2vec.core import Word2VecAug

Expand Down Expand Up @@ -40,7 +40,7 @@ def tokenizer(self, text: str) -> list[str]:
""":param str text: Thai text
:rtype: List[str]
"""
return self.bpemb_temp.encode(text) # type: ignore[no-any-return]
return cast(list[str], self.bpemb_temp.encode(text))

def load_w2v(self) -> None:
"""Load BPEmb model"""
Expand Down
4 changes: 3 additions & 1 deletion pythainlp/augment/word2vec/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def __init__(
_gensim_kv_logger.addFilter(_filter)
try:
if type == "file":
self.model = word2vec.KeyedVectors.load_word2vec_format(model)
self.model = word2vec.KeyedVectors.load_word2vec_format(
model
)
else:
self.model = word2vec.KeyedVectors.load_word2vec_format(
model, binary=True, unicode_errors="ignore"
Expand Down
12 changes: 6 additions & 6 deletions pythainlp/augment/wordnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ class WordNetAug:
"""Text Augment using wordnet"""

synonyms: list[str]
list_synsets: list
list_synsets: list[Synset]
p2w_pos: Optional[str]
synset: Synset
syn: str
synonyms_without_duplicates: list[str]
list_words: list[str]
list_synonym: list
list_synonym: list[list[str]]
p_all: int
list_pos: list[tuple[str, str]]
temp: list[str]
Expand All @@ -152,15 +152,15 @@ def find_synonyms(
"""
self.synonyms: list[str] = []
if pos is None:
self.list_synsets: list = wordnet.synsets(word)
self.list_synsets: list[Synset] = wordnet.synsets(word)
else:
self.p2w_pos: Optional[str] = postype2wordnet(pos, postag_corpus)
if self.p2w_pos != "":
self.list_synsets: list = wordnet.synsets(
self.list_synsets: list[Synset] = wordnet.synsets(
word, pos=self.p2w_pos
)
else:
self.list_synsets: list = wordnet.synsets(word)
self.list_synsets: list[Synset] = wordnet.synsets(word)

for self.synset in wordnet.synsets(word):
for self.syn in self.synset.lemma_names(lang="tha"):
Expand Down Expand Up @@ -206,7 +206,7 @@ def augment(
"""
new_sentences = []
self.list_words: list[str] = tokenize(sentence)
self.list_synonym: list = []
self.list_synonym: list[list[str]] = []
self.p_all: int = 1
if postag:
self.list_pos: list[tuple[str, str]] = pos_tag(
Expand Down
Loading
Loading