رفعِ چند باگِ لبهای و بهبودِ استحکام، کارایی و پوششِ تست#369
Open
Milomilo777 wants to merge 4 commits into
Open
رفعِ چند باگِ لبهای و بهبودِ استحکام، کارایی و پوششِ تست#369Milomilo777 wants to merge 4 commits into
Milomilo777 wants to merge 4 commits into
Conversation
- Stemmer: stop stripping a multi-character suffix when it would leave an empty or single-character stem (e.g. stem('ها') returned '', stem('رها') returned 'ر'); suffix-only tokens are now returned unchanged.
- WordTokenizer.join_verb_parts: keep a trailing 'before verb' (e.g. 'خواهد') that was silently dropped when it was the last token, and only treat truly blank lines as empty when loading the verbs file.
- Lemmatizer: skip the empty/single-character conjugations produced by the empty past-root entry '#هست', so '' and clitics like 'م' are no longer mapped to a verb lemma; lemmatize('') now returns ''.
- POSTagger.features: use safe slicing (word[:1] / word[-1:]) so an empty-string token no longer raises IndexError (this also fixes Chunker, which reuses it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- ArmanReader, NaabReader, NerReader and PnSummaryReader stored a one-shot Path.glob() iterator, so a second call to sents()/docs() yielded nothing; the file list is now materialized with sorted(...) for deterministic, repeatable iteration. - ArmanReader: tolerate runs of whitespace between token and tag via line.split(). - DegarbayanReader: raise FileNotFoundError for a missing corpus file instead of crashing with NameError on an undefined variable. - TreebankReader.trees: call traverse() once; the duplicate call did dead work and mutated the live DOM twice. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Normalizer: build the character translation tables once at import time instead of rebuilding them on every normalize()/persian_number() call. - constants: the decimal-separator rule used the character class [\d+], which also matched a literal '+'; it now matches only digits ((\d)\.(\d)). - utils: past_roots()/present_roots() no longer raise IndexError on a verb entry that lacks '#'. - Fix the unicodes_replacement docstring (it demonstrated remove_specials_chars) and clarify the replace_numbers parameter docstring. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Move filterwarnings and the test-id escaping option out of the stray [tool.black] table into a real [tool.pytest.ini_options] section (they were silently ignored), and set testpaths. - Add tests/test_regression_fixes.py and tests/corpus_readers/test_reader_reiteration.py covering every fix above plus previously untested paths (stemmer edge cases, empty-input tokenization, email/hashtag replacement, lemmatizer POS branches, utils helpers, reader re-iteration and missing-file handling). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
خلاصه
این درخواستِ ادغام مجموعهای از باگهای لبهای (edge case)، بهبودهای استحکام و کارایی، و افزودنِ تستهای رگرسیون را در یک شاخه گرد آورده است. همهی تغییرات برای ورودیهای معمول رفتارحفظکننده و کمریسکاند و فقط رفتارِ نادرست در حالتهای مرزی را اصلاح میکنند.
هر اصلاح با تستِ واقعی پوشش داده شده است. کلِ مجموعهی تست سبز است (۲۶۰ تست قبول، ۴ مورد
xfailمطابقِ قبل) و اجرایruffروی کلِ مخزن بدونِ خطاست. تنها ماژولِ تعبیهسازی بهدلیلِ توضیحِ بخشِ «یادداشتِ سازگاری» در محیطِ توسعه اجرا نشد و آگاهانه دستنخورده ماند.باگهای منطقی و لبهای رفعشده
۱. تهیشدنِ خروجیِ ریشهیاب —
hazm/stemmer.pystem('ها')⟵''وstem('رها')⟵'ر').۲. حذفِ خاموشِ جزءِ پایانیِ فعل —
hazm/word_tokenizer.pyjoin_verb_parts، اگر یک «فعلِ کمکیِ پیشین» مانندِخواهدواپسین توکن میبود، در نشانگرِ خالیِ انباشتگر ادغام و سپس دور انداخته میشد؛ پس['کتاب', 'خواهد']به['کتاب']تبدیل میشد (ازدسترفتنِ داده).۳. تزریقِ کلیدهای تهی و تکنویسه در واژگانِ افعال —
hazm/lemmatizer.py#هستصورتهای صرفیِ تهی و تکنویسه میساخت و کلیدهایی مانندِ''و'م'را به یک لِمِ فعل نگاشت میکرد؛ پسlemmatize('')وlemmatize('م')خروجیِ نادرست میدادند.۴. خطای اندیس در استخراجِ ویژگیِ برچسبزن —
hazm/pos_tagger.pyfeaturesباword[0]وword[-1]روی توکنِ رشتهی تهی خطایIndexErrorمیداد و کلِ فراخوانیِtagرا میشکست. همین متد درChunkerنیز بازاستفاده میشود، پس تکهبندی هم آسیب میدید.word[:1]وword[-1:]که برای توکنهای معمول خروجیِ یکسان و برای توکنِ تهی رشتهی تهی میدهند.۵. تکرارناپذیریِ خوانندگانِ پیکره —
arman/naab/ner/pn_summaryPath.glob()را ذخیره میکردند؛ پس فراخوانیِ دومِsents()/docs()هیچ خروجیای نمیداد.sorted(...)برای تکرارپذیری و ترتیبِ قطعی.۶. خطای نادرست هنگامِ نبودِ فایلِ پیکره —
hazm/corpus_readers/degarbayan_reader.pyeاشاره میکرد و بهجایFileNotFoundError، خطایNameErrorمیداد.FileNotFoundErrorصادر شود.۷. فراخوانیِ دوباره و ناایمنِ پیمایشِ درخت —
hazm/corpus_readers/treebank_reader.pytreesتابعِtraverseرا دو بار صدا میزد؛ بارِ نخست دور ریخته میشد ولی درختِ زنده را تغییر میداد و بارِ دوم روی دادهی دستخورده اجرا میشد.استحکام، کارایی و مستندات
hazm/constants.pyاز ردهٔ نویسهی[\d+](که علامتِ+را هم میپذیرفت) به(\d)\.(\d)اصلاح شد تا فقط میانِ ارقام عمل کند.hazm/normalizer.pyیکبار در زمانِ بارگذاریِ ماژول ساخته میشوند، نه در هر فراخوانیِnormalizeوpersian_number(مسیرِ پرتکرارِ کتابخانه).past_rootsوpresent_rootsدرhazm/utils.pyدیگر روی مدخلِ بدونِ#خطای اندیس نمیدهند.unicodes_replacementکه متدِ دیگری را نشان میداد، و توضیحِ پارامترِreplace_numbers.تست و راستیآزمایی
دو فایلِ تستِ جدید افزوده شد:
tests/test_regression_fixes.pytests/corpus_readers/test_reader_reiteration.pyاین تستها هر یک از اصلاحاتِ بالا را قفل میکنند و چند مسیرِ پیشتر بدونِتست را نیز پوشش میدهند: حالتهای مرزیِ ریشهیاب، توکنایزِ ورودیِ تهی، جایگزینیِ ایمیل و هشتگ، شاخههای نقشِ دستوریِ لماتایزر، توابعِ کمکی، و تکرارپذیریِ خوانندگانِ پیکره.
همچنین پیکربندیِ pytest اصلاح شد: کلیدهای
filterwarningsو گزینهی نمایشِ شناسهی تست که اشتباهاً زیرِ بخشِ[tool.black]قرار داشتند و خاموش بودند، به بخشِ درستِ[tool.pytest.ini_options]منتقل شدند.یادداشتِ سازگاری
ماژولِ تعبیهسازی (
embedding) بهgensimوابسته است که در محیطِ توسعه (پایتونِ ۳٫۱۴)wheelسازگار نداشت؛ پس برای آنکه فقط تغییراتِ آزمودهشده ارائه شوند، هیچ تغییری در آن ماژول داده نشد.موارد شناساییشده برای پیگیریِ بعدی (خارج از دامنهی این درخواست)
این موارد طیِ تحلیل یافت شدند ولی برای محدودنگهداشتنِ ریسک و چون آزمونشان به منابعِ سنگین نیاز دارد در این درخواست نیامدهاند:
embedding.py، متدِWordEmbedding.trainیک generator یکبارمصرف را دو بار مصرف میکند (یکبارbuild_vocabو یکبارtrain)، پس آموزش روی پیکرهی تهی اجرا میشود.similarity.Conjugationفاقدِ خطِ مقداردهیِ اولیهاند).در صورتِ تمایلِ نگهدارندگان، این موارد را با خوشحالی در درخواستهای جداگانه پیگیری میکنم.
🤖 Generated with Claude Code