fix(profile): avoid pinning dynamic language classes - #93
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 236f17b458
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| def replace_abbreviations(self, text: str) -> str: | ||
| return self.profile.abbreviation_replacer_cls(text, self.profile.language, split_mode=self.split_mode).replace() | ||
| return self.profile.abbreviation_replacer_cls(text, self.lang, split_mode=self.split_mode).replace() |
There was a problem hiding this comment.
Avoid pinning dynamic languages through abbreviation caching
When a dynamic language is actually used for segmentation, this still passes the language class into AbbreviationReplacer; on first classification, AbbreviationReplacer._period_classifier() caches a PeriodClassifier whose reference replacer is built with that same lang (abbreviation_replacer.py:257) and stores it on .lang, so _data._classifier_cache keeps the dynamic class alive after Processor(...).process() and the weak profile key cannot be reclaimed. The new GC test only calls LanguageProfile.from_language(), so it misses the long-running service scenario this fix is meant to cover.
Useful? React with 👍 / 👎.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthrough
ChangesLanguage cache ownership
Estimated code review effort: 2 (Simple) | ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Motivation
WeakKeyDictionarykeyed by language class but each cachedLanguageProfileheld a stronglanguagereference back to the key, defeating weak-key cleanup for dynamically generated language classes.Description
language: typefield fromLanguageProfileso cached values no longer strongly reference the language class stored as the weak-key in_PROFILE_CACHE(sentencesplit/language_profile.py).Processorinstance by storingself.lang = langinProcessor.__init__and passingself.langto the abbreviation replacer instead ofself.profile.language(sentencesplit/processor.py).test_language_profile_cache_does_not_pin_dynamic_language_classesthat builds a profile from a dynamically defined language class, drops local references, forces GC, and asserts the dynamic class is collectible (tests/unit/test_language_profile.py).Testing
uv run pytest tests/unit/test_language_profile.py -qand they passed.uv run pytest tests/unit/test_language_profile.py tests/contract/test_processor.py tests/lang/test_deutsch.py tests/lang/test_kazakh.py tests/regression/test_kazakh_multiperiod_sentinel.py tests/regression/test_german_standalone_i.py -qand the run succeeded (all tests in that selection passed).uv run pytest --cov=sentencesplit tests/ --color yeswhich completed successfully (test run reported all tests passed with expected skips/xfails:10508 passed, 14 skipped, 113 xfailed).uv run ruff check .anduv run ruff format --check .and both checks passed.Codex Task
Summary by CodeRabbit
Bug Fixes
Tests