From 49d764cc85b17bca7e8b0863b9806f2080e525c3 Mon Sep 17 00:00:00 2001 From: Chris Grady <17553614+CGFixIT@users.noreply.github.com> Date: Sun, 6 Sep 2026 11:22:20 -0400 Subject: [PATCH] perf: avoid copying chunked matches before sorting --- src/insight_extractor/stemmer.py | 3 ++- tests/unit/test_stemmer.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/insight_extractor/stemmer.py b/src/insight_extractor/stemmer.py index c99d889..19a69a1 100644 --- a/src/insight_extractor/stemmer.py +++ b/src/insight_extractor/stemmer.py @@ -35,7 +35,8 @@ def finditer(self, text: str) -> Iterator[re.Match[str]]: matches: list[re.Match[str]] = [] for pattern in self.patterns: matches.extend(pattern.finditer(text)) - yield from sorted(matches, key=lambda match: (match.start(), match.end())) + matches.sort(key=lambda match: (match.start(), match.end())) + yield from matches type KeywordPattern = re.Pattern[str] | ChunkedKeywordPattern diff --git a/tests/unit/test_stemmer.py b/tests/unit/test_stemmer.py index aefc94b..03c22c7 100644 --- a/tests/unit/test_stemmer.py +++ b/tests/unit/test_stemmer.py @@ -7,11 +7,38 @@ import pytest from insight_extractor.config import StemMode -from insight_extractor.stemmer import DynamicKeywordStemmer, KeywordPatternRegistry +from insight_extractor.stemmer import ( + ChunkedKeywordPattern, + DynamicKeywordStemmer, + KeywordPatternRegistry, +) # ── DynamicKeywordStemmer tests ────────────────────────────────────────────── +@pytest.mark.parametrize("text", ["", "no matches", "alpha beta alpha"]) +def test_chunked_finditer_preserves_span_order_and_tie_priority(text: str) -> None: + patterns = [ + re.compile(pattern) for pattern in ("alpha beta", "alpha", "(?:alpha)", "(?=alpha)") + ] + matches = list(ChunkedKeywordPattern(patterns).finditer(text)) + + expected = ( + [ + ((0, 0), "", "(?=alpha)"), + ((0, 5), "alpha", "alpha"), + ((0, 5), "alpha", "(?:alpha)"), + ((0, 10), "alpha beta", "alpha beta"), + ((11, 11), "", "(?=alpha)"), + ((11, 16), "alpha", "alpha"), + ((11, 16), "alpha", "(?:alpha)"), + ] + if text == "alpha beta alpha" + else [] + ) + assert [(match.span(), match.group(), match.re.pattern) for match in matches] == expected + + class TestInit: """Construction and default attributes."""