From 8377f2cd8ea7d2a969b9940f6bf891924a830a59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 22:36:22 +0000 Subject: [PATCH 1/2] Initial plan From a8235084244787ec34a6124b5a40a56236e36d46 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Mar 2026 22:41:26 +0000 Subject: [PATCH 2/2] refactor(tests): reorganize noauto test cases by function; fix too-broad except MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move misplaced test classes out of tokenize test files: ONNX tests (tests/noauto_onnx/): - TransliterateONNXTestCaseN → testn_transliterate_onnx.py - TagONNXTestCaseN → testn_tag_onnx.py - SpellONNXTestCaseN → testn_spell_onnx.py Torch tests (tests/noauto_torch/): - TransliterateTestCaseN → testn_transliterate_torch.py - ParseTestCaseN → testn_parse_torch.py - SummarizeTestCaseN → testn_summarize_torch.py - AugmentTestCaseN → testn_augment_torch.py Each new file adds edge-case tests: model-loaded checks, empty inputs, result structure (tuple pairs, string items), length constraints, and ValueError on out-of-range arguments. Update noauto_onnx/__init__.py and noauto_torch/__init__.py to register the new modules. Fix: remove dead try/except Exception wrapping list.append(2) in pythainlp/spell/wanchanberta_thai_grammarly.py (too-broad catch, unreachable except branch). Co-authored-by: bact <128572+bact@users.noreply.github.com> Agent-Logs-Url: https://github.com/PyThaiNLP/pythainlp/sessions/dbbd3773-7bc2-4463-a049-e17a95e2651f --- .../spell/wanchanberta_thai_grammarly.py | 5 +- tests/noauto_onnx/__init__.py | 3 + tests/noauto_onnx/testn_spell_onnx.py | 41 +++++++++ tests/noauto_onnx/testn_tag_onnx.py | 53 ++++++++++++ tests/noauto_onnx/testn_tokenize_onnx.py | 37 --------- tests/noauto_onnx/testn_transliterate_onnx.py | 41 +++++++++ tests/noauto_torch/__init__.py | 4 + tests/noauto_torch/testn_augment_torch.py | 75 +++++++++++++++++ tests/noauto_torch/testn_parse_torch.py | 34 ++++++++ tests/noauto_torch/testn_summarize_torch.py | 47 +++++++++++ tests/noauto_torch/testn_tokenize_torch.py | 83 ------------------- .../noauto_torch/testn_transliterate_torch.py | 68 +++++++++++++++ 12 files changed, 367 insertions(+), 124 deletions(-) create mode 100644 tests/noauto_onnx/testn_spell_onnx.py create mode 100644 tests/noauto_onnx/testn_tag_onnx.py create mode 100644 tests/noauto_onnx/testn_transliterate_onnx.py create mode 100644 tests/noauto_torch/testn_augment_torch.py create mode 100644 tests/noauto_torch/testn_parse_torch.py create mode 100644 tests/noauto_torch/testn_summarize_torch.py create mode 100644 tests/noauto_torch/testn_transliterate_torch.py diff --git a/pythainlp/spell/wanchanberta_thai_grammarly.py b/pythainlp/spell/wanchanberta_thai_grammarly.py index d020bfc5b..2846df4e2 100644 --- a/pythainlp/spell/wanchanberta_thai_grammarly.py +++ b/pythainlp/spell/wanchanberta_thai_grammarly.py @@ -71,10 +71,7 @@ def align_word_ids(texts: str) -> list[int]: if word_idx is None: label_ids.append(-100) else: - try: - label_ids.append(2) - except Exception: - label_ids.append(-100) + label_ids.append(2) return label_ids diff --git a/tests/noauto_onnx/__init__.py b/tests/noauto_onnx/__init__.py index 5f27180ca..0bc3325a5 100644 --- a/tests/noauto_onnx/__init__.py +++ b/tests/noauto_onnx/__init__.py @@ -21,7 +21,10 @@ # Names of module to be tested test_packages: list[str] = [ + "tests.noauto_onnx.testn_spell_onnx", + "tests.noauto_onnx.testn_tag_onnx", "tests.noauto_onnx.testn_tokenize_onnx", + "tests.noauto_onnx.testn_transliterate_onnx", ] diff --git a/tests/noauto_onnx/testn_spell_onnx.py b/tests/noauto_onnx/testn_spell_onnx.py new file mode 100644 index 000000000..674bb61ab --- /dev/null +++ b/tests/noauto_onnx/testn_spell_onnx.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for spell correction functions that require ONNX Runtime +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (onnxruntime) +# - Platform-specific compatibility issues +# - Version constraints + +import unittest + + +class SpellONNXTestCaseN(unittest.TestCase): + """Tests for ONNX-based spell correction (requires onnxruntime)""" + + def test_words_spelling_correction_returns_list(self): + from pythainlp.spell.words_spelling_correction import ( + get_words_spell_suggestion, + ) + + result = get_words_spell_suggestion("สวัสดี") + self.assertIsInstance(result, list) + + def test_words_spelling_correction_nonempty_input(self): + from pythainlp.spell.words_spelling_correction import ( + get_words_spell_suggestion, + ) + + result = get_words_spell_suggestion("กาารเขียน") + self.assertIsInstance(result, list) + self.assertGreater(len(result), 0) + + def test_words_spelling_correction_items_are_strings(self): + from pythainlp.spell.words_spelling_correction import ( + get_words_spell_suggestion, + ) + + result = get_words_spell_suggestion("กาารเขียน") + for item in result: + self.assertIsInstance(item, str) diff --git a/tests/noauto_onnx/testn_tag_onnx.py b/tests/noauto_onnx/testn_tag_onnx.py new file mode 100644 index 000000000..378d7c964 --- /dev/null +++ b/tests/noauto_onnx/testn_tag_onnx.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for POS tagging functions that require ONNX Runtime +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (onnxruntime) +# - Platform-specific compatibility issues +# - Version constraints + +import unittest + + +class TagONNXTestCaseN(unittest.TestCase): + """Tests for ONNX-based POS tagging (requires onnxruntime)""" + + def test_pos_tag_wangchanberta_onnx_returns_list(self): + from pythainlp.tag import pos_tag + + result = pos_tag( + ["แมว", "กิน", "ปลา"], + engine="wangchanberta_onnx", + ) + self.assertIsInstance(result, list) + self.assertGreater(len(result), 0) + + def test_pos_tag_wangchanberta_onnx_length_matches(self): + from pythainlp.tag import pos_tag + + tokens = ["แมว", "กิน", "ปลา"] + result = pos_tag(tokens, engine="wangchanberta_onnx") + self.assertEqual(len(result), len(tokens)) + + def test_pos_tag_wangchanberta_onnx_tuple_pairs(self): + from pythainlp.tag import pos_tag + + result = pos_tag( + ["แมว", "กิน", "ปลา"], + engine="wangchanberta_onnx", + ) + for item in result: + self.assertIsInstance(item, tuple) + self.assertEqual(len(item), 2) + word, tag = item + self.assertIsInstance(word, str) + self.assertIsInstance(tag, str) + + def test_pos_tag_wangchanberta_onnx_empty_list(self): + from pythainlp.tag import pos_tag + + result = pos_tag([], engine="wangchanberta_onnx") + self.assertIsInstance(result, list) + self.assertEqual(len(result), 0) diff --git a/tests/noauto_onnx/testn_tokenize_onnx.py b/tests/noauto_onnx/testn_tokenize_onnx.py index 046391be6..af92a2f3b 100644 --- a/tests/noauto_onnx/testn_tokenize_onnx.py +++ b/tests/noauto_onnx/testn_tokenize_onnx.py @@ -79,40 +79,3 @@ def test_sefr_cut(self): sefr_cut.segment("ฉันรักภาษาไทยเพราะฉันเป็นคนไทย", engine="tnhc"), ) - -class TransliterateONNXTestCaseN(unittest.TestCase): - """Tests for ONNX-based transliteration (requires onnxruntime)""" - - def test_thai2rom_onnx(self): - from pythainlp.transliterate.thai2rom_onnx import romanize - - result = romanize("สวัสดี") - self.assertIsInstance(result, str) - self.assertGreater(len(result), 0) - - -class TagONNXTestCaseN(unittest.TestCase): - """Tests for ONNX-based POS tagging (requires onnxruntime)""" - - def test_pos_tag_wangchanberta_onnx(self): - from pythainlp.tag import pos_tag - - result = pos_tag( - ["แมว", "กิน", "ปลา"], - engine="wangchanberta_onnx" - ) - self.assertIsInstance(result, list) - self.assertGreater(len(result), 0) - self.assertEqual(len(result), 3) - - -class SpellONNXTestCaseN(unittest.TestCase): - """Tests for ONNX-based spell correction (requires onnxruntime)""" - - def test_words_spelling_correction(self): - from pythainlp.spell.words_spelling_correction import ( - get_words_spell_suggestion, - ) - - result = get_words_spell_suggestion("สวัสดี") - self.assertIsInstance(result, list) diff --git a/tests/noauto_onnx/testn_transliterate_onnx.py b/tests/noauto_onnx/testn_transliterate_onnx.py new file mode 100644 index 000000000..0576e3f16 --- /dev/null +++ b/tests/noauto_onnx/testn_transliterate_onnx.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for transliteration functions that require ONNX Runtime +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (onnxruntime) +# - Platform-specific compatibility issues +# - Version constraints + +import unittest + + +class TransliterateONNXTestCaseN(unittest.TestCase): + """Tests for ONNX-based transliteration (requires onnxruntime)""" + + def test_thai2rom_onnx_returns_string(self): + from pythainlp.transliterate.thai2rom_onnx import romanize + + result = romanize("สวัสดี") + self.assertIsInstance(result, str) + self.assertGreater(len(result), 0) + + def test_thai2rom_onnx_empty_string(self): + from pythainlp.transliterate.thai2rom_onnx import romanize + + result = romanize("") + self.assertIsInstance(result, str) + + def test_thai2rom_onnx_ascii_passthrough(self): + from pythainlp.transliterate.thai2rom_onnx import romanize + + result = romanize("hello") + self.assertIsInstance(result, str) + + def test_thai2rom_onnx_mixed_text(self): + from pythainlp.transliterate.thai2rom_onnx import romanize + + result = romanize("ภาษาไทย") + self.assertIsInstance(result, str) + self.assertGreater(len(result), 0) diff --git a/tests/noauto_torch/__init__.py b/tests/noauto_torch/__init__.py index eba6b8584..1b97e04f6 100644 --- a/tests/noauto_torch/__init__.py +++ b/tests/noauto_torch/__init__.py @@ -23,10 +23,14 @@ # Names of module to be tested test_packages: list[str] = [ + "tests.noauto_torch.testn_augment_torch", "tests.noauto_torch.testn_lm_torch", + "tests.noauto_torch.testn_parse_torch", "tests.noauto_torch.testn_spell_torch", + "tests.noauto_torch.testn_summarize_torch", "tests.noauto_torch.testn_tag_torch", "tests.noauto_torch.testn_tokenize_torch", + "tests.noauto_torch.testn_transliterate_torch", ] diff --git a/tests/noauto_torch/testn_augment_torch.py b/tests/noauto_torch/testn_augment_torch.py new file mode 100644 index 000000000..07d7a1715 --- /dev/null +++ b/tests/noauto_torch/testn_augment_torch.py @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for augmentation functions that require transformers +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (torch, transformers) +# - Python 3.13+ compatibility issues + +import unittest + + +class AugmentTestCaseN(unittest.TestCase): + """Tests for augmentation functions (requires transformers)""" + + def test_augment_wangchanberta_returns_list(self): + from pythainlp.augment.lm import Thai2transformersAug + + augmenter = Thai2transformersAug() + result = augmenter.augment("แมวกิน") + self.assertIsInstance(result, list) + self.assertGreater(len(result), 0) + + def test_augment_wangchanberta_items_are_strings(self): + from pythainlp.augment.lm import Thai2transformersAug + + augmenter = Thai2transformersAug() + result = augmenter.augment("แมวกิน") + for item in result: + self.assertIsInstance(item, str) + + def test_augment_wangchanberta_generate_returns_list(self): + from pythainlp.augment.lm import Thai2transformersAug + + augmenter = Thai2transformersAug() + result = augmenter.generate("แมวกิน", num_replace_tokens=1) + self.assertIsInstance(result, list) + + def test_augment_phayathaibert_returns_list(self): + from pythainlp.augment.lm import ThaiTextAugmenter + + augmenter = ThaiTextAugmenter() + result = augmenter.augment("แมวกิน") + self.assertIsInstance(result, list) + self.assertGreater(len(result), 0) + + def test_augment_phayathaibert_items_are_strings(self): + from pythainlp.augment.lm import ThaiTextAugmenter + + augmenter = ThaiTextAugmenter() + result = augmenter.augment("แมวกิน") + for item in result: + self.assertIsInstance(item, str) + + def test_augment_phayathaibert_num_augs_respected(self): + from pythainlp.augment.lm import ThaiTextAugmenter + + augmenter = ThaiTextAugmenter() + result = augmenter.augment("แมวกิน", num_augs=2) + self.assertEqual(len(result), 2) + + def test_augment_phayathaibert_exceeds_limit_raises(self): + from pythainlp.augment.lm import ThaiTextAugmenter + + augmenter = ThaiTextAugmenter() + with self.assertRaises(ValueError): + augmenter.augment("แมวกิน", num_augs=10) + + def test_augment_phayathaibert_adds_mask_if_missing(self): + from pythainlp.augment.lm import ThaiTextAugmenter + + augmenter = ThaiTextAugmenter() + result = augmenter.augment("แมวกิน", num_augs=1) + self.assertIsInstance(result, list) + self.assertEqual(len(result), 1) diff --git a/tests/noauto_torch/testn_parse_torch.py b/tests/noauto_torch/testn_parse_torch.py new file mode 100644 index 000000000..8cfafeca3 --- /dev/null +++ b/tests/noauto_torch/testn_parse_torch.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for parsing functions that require torch and transformers +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (torch, transformers) +# - Python 3.13+ compatibility issues + +import unittest + + +class ParseTestCaseN(unittest.TestCase): + """Tests for parsing functions (requires torch and transformers)""" + + def test_dependency_parsing_returns_list(self): + from pythainlp.parse import dependency_parsing + + result = dependency_parsing("แมวกินปลา") + self.assertIsInstance(result, list) + self.assertGreater(len(result), 0) + + def test_dependency_parsing_result_structure(self): + from pythainlp.parse import dependency_parsing + + result = dependency_parsing("แมวกินปลา") + for item in result: + self.assertIsInstance(item, dict) + + def test_dependency_parsing_empty_string(self): + from pythainlp.parse import dependency_parsing + + result = dependency_parsing("") + self.assertIsInstance(result, list) diff --git a/tests/noauto_torch/testn_summarize_torch.py b/tests/noauto_torch/testn_summarize_torch.py new file mode 100644 index 000000000..98d5259f4 --- /dev/null +++ b/tests/noauto_torch/testn_summarize_torch.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for summarization functions that require transformers +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (torch, transformers) +# - Python 3.13+ compatibility issues + +import unittest + + +class SummarizeTestCaseN(unittest.TestCase): + """Tests for summarization functions (requires transformers)""" + + def test_summarize_keybert_returns_list(self): + from pythainlp.summarize.keybert import KeyBERT + + text = "แมวเป็นสัตว์เลี้ยงที่น่ารัก แมวชอบกินปลา แมวชอบนอนหลับ" + keybert = KeyBERT() + result = keybert.extract_keywords(text, max_keywords=2) + self.assertIsInstance(result, list) + + def test_summarize_keybert_max_keywords_respected(self): + from pythainlp.summarize.keybert import KeyBERT + + text = "แมวเป็นสัตว์เลี้ยงที่น่ารัก แมวชอบกินปลา แมวชอบนอนหลับ" + keybert = KeyBERT() + result = keybert.extract_keywords(text, max_keywords=2) + self.assertLessEqual(len(result), 2) + + def test_summarize_mt5_returns_list(self): + from pythainlp.summarize.mt5 import mT5Summarizer + + text = "แมวเป็นสัตว์เลี้ยงที่น่ารัก แมวชอบกินปลา แมวชอบนอนหลับ" + summarizer = mT5Summarizer() + result = summarizer.summarize(text) + self.assertIsInstance(result, list) + + def test_summarize_mt5_result_items_are_strings(self): + from pythainlp.summarize.mt5 import mT5Summarizer + + text = "แมวเป็นสัตว์เลี้ยงที่น่ารัก แมวชอบกินปลา แมวชอบนอนหลับ" + summarizer = mT5Summarizer() + result = summarizer.summarize(text) + for item in result: + self.assertIsInstance(item, str) diff --git a/tests/noauto_torch/testn_tokenize_torch.py b/tests/noauto_torch/testn_tokenize_torch.py index ae3591253..6273daad3 100644 --- a/tests/noauto_torch/testn_tokenize_torch.py +++ b/tests/noauto_torch/testn_tokenize_torch.py @@ -143,86 +143,3 @@ class SubwordTokenizeWangchanbertaTestCaseN(unittest.TestCase): def test_subword_tokenize_wangchanberta(self): assert_subword_tokenize_basic(self, "wangchanberta") - -class TransliterateTestCaseN(unittest.TestCase): - """Tests for transliteration functions (requires torch)""" - - def test_thai2rom(self): - from pythainlp.transliterate.thai2rom import romanize - - result = romanize("สวัสดี") - self.assertIsInstance(result, str) - self.assertGreater(len(result), 0) - - def test_thaig2p(self): - from pythainlp.transliterate.thaig2p import transliterate - - result = transliterate("สวัสดี") - self.assertIsInstance(result, str) - self.assertGreater(len(result), 0) - - def test_thaig2p_v2(self): - from pythainlp.transliterate.thaig2p_v2 import transliterate - - result = transliterate("สวัสดี") - self.assertIsInstance(result, str) - self.assertGreater(len(result), 0) - - def test_umt5_thaig2p(self): - from pythainlp.transliterate.umt5_thaig2p import transliterate - - result = transliterate("สวัสดี") - self.assertIsInstance(result, str) - self.assertGreater(len(result), 0) - - -class ParseTestCaseN(unittest.TestCase): - """Tests for parsing functions (requires torch and transformers)""" - - def test_dependency_parsing(self): - from pythainlp.parse import dependency_parsing - - result = dependency_parsing("แมวกินปลา") - self.assertIsInstance(result, list) - self.assertGreater(len(result), 0) - - -class SummarizeTestCaseN(unittest.TestCase): - """Tests for summarization functions (requires transformers)""" - - def test_summarize_keybert(self): - from pythainlp.summarize.keybert import KeyBERT - - text = "แมวเป็นสัตว์เลี้ยงที่น่ารัก แมวชอบกินปลา แมวชอบนอนหลับ" - keybert = KeyBERT() - result = keybert.extract_keywords(text, max_keywords=2) - self.assertIsInstance(result, list) - - def test_summarize_mt5(self): - from pythainlp.summarize.mt5 import mT5Summarizer - - text = "แมวเป็นสัตว์เลี้ยงที่น่ารัก แมวชอบกินปลา แมวชอบนอนหลับ" - summarizer = mT5Summarizer() - result = summarizer.summarize(text) - self.assertIsInstance(result, list) - - -class AugmentTestCaseN(unittest.TestCase): - """Tests for augmentation functions (requires transformers)""" - - def test_augment_wangchanberta(self): - from pythainlp.augment.lm import Thai2transformersAug - - augmenter = Thai2transformersAug() - result = augmenter.augment("แมวกิน") - self.assertIsInstance(result, list) - self.assertGreater(len(result), 0) - - def test_augment_phayathaibert(self): - from pythainlp.augment.lm import ThaiTextAugmenter - - augmenter = ThaiTextAugmenter() - result = augmenter.augment("แมวกิน") - self.assertIsInstance(result, list) - self.assertGreater(len(result), 0) - diff --git a/tests/noauto_torch/testn_transliterate_torch.py b/tests/noauto_torch/testn_transliterate_torch.py new file mode 100644 index 000000000..5d7268e35 --- /dev/null +++ b/tests/noauto_torch/testn_transliterate_torch.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project +# SPDX-FileType: SOURCE +# SPDX-License-Identifier: Apache-2.0 + +# Tests for transliteration functions that require torch +# These tests are NOT run in automated CI workflows due to: +# - Large dependencies (torch, transformers) +# - Python 3.13+ compatibility issues + +import unittest + + +class TransliterateTestCaseN(unittest.TestCase): + """Tests for transliteration functions (requires torch)""" + + def test_thai2rom_returns_string(self): + from pythainlp.transliterate.thai2rom import romanize + + result = romanize("สวัสดี") + self.assertIsInstance(result, str) + self.assertGreater(len(result), 0) + + def test_thai2rom_model_loaded(self): + from pythainlp.transliterate.thai2rom import ThaiTransliterator + + t = ThaiTransliterator() + self.assertIsNotNone(t._network) + self.assertIsNotNone(t._char_to_ix) + self.assertIsNotNone(t._target_char_to_ix) + self.assertIn("", t._target_char_to_ix) + self.assertIn("", t._target_char_to_ix) + + def test_thai2rom_empty_string(self): + from pythainlp.transliterate.thai2rom import romanize + + result = romanize("") + self.assertIsInstance(result, str) + + def test_thaig2p_returns_string(self): + from pythainlp.transliterate.thaig2p import transliterate + + result = transliterate("สวัสดี") + self.assertIsInstance(result, str) + self.assertGreater(len(result), 0) + + def test_thaig2p_model_loaded(self): + from pythainlp.transliterate.thaig2p import ThaiG2P + + g2p = ThaiG2P() + self.assertIsNotNone(g2p._network) + self.assertIsNotNone(g2p._char_to_ix) + self.assertIsNotNone(g2p._target_char_to_ix) + self.assertIn("", g2p._target_char_to_ix) + self.assertIn("", g2p._target_char_to_ix) + + def test_thaig2p_v2_returns_string(self): + from pythainlp.transliterate.thaig2p_v2 import transliterate + + result = transliterate("สวัสดี") + self.assertIsInstance(result, str) + self.assertGreater(len(result), 0) + + def test_umt5_thaig2p_returns_string(self): + from pythainlp.transliterate.umt5_thaig2p import transliterate + + result = transliterate("สวัสดี") + self.assertIsInstance(result, str) + self.assertGreater(len(result), 0)