diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f1d11f8f6..cfcaad1c00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Fixes - **Update README.md**: readme-only changes; added a link to Unstructured Pipelines to the README. No library behavior changes. +- **`_get_indexed_match` raises `ValueError` instead of `UnboundLocalError` on zero matches**: `extract_text_before()`/`extract_text_after()`'s underlying helper looped `for i, result in enumerate(re.finditer(pattern, text))` and referenced `i` in its "not found" error message; when the pattern matched zero times, the loop body never ran, so `i` was never bound, raising `UnboundLocalError` instead of the intended `ValueError`. `i` is now initialized to `-1` before the loop. ## 0.25.0 diff --git a/test_unstructured/cleaners/test_extract.py b/test_unstructured/cleaners/test_extract.py index 86ac0e8487..7e29ba5e3c 100644 --- a/test_unstructured/cleaners/test_extract.py +++ b/test_unstructured/cleaners/test_extract.py @@ -19,6 +19,16 @@ def test_get_indexed_match_raises_with_index_too_high(): extract._get_indexed_match("BLAH BLAH BLAH", "BLAH", 4) +def test_get_indexed_match_raises_value_error_with_zero_matches(): + """Regression test: when the pattern has zero matches at all (not just an + out-of-range index on an otherwise-matching pattern), the "not found" branch + referenced the loop variable `i`, which Python never binds when a for-loop's + iterable is empty -- raising UnboundLocalError instead of the intended + ValueError.""" + with pytest.raises(ValueError): + extract._get_indexed_match("no digits here", r"[0-9]+") + + def test_extract_text_before(): text = "Teacher: BLAH BLAH BLAH; Student: BLAH BLAH BLAH!" assert extract.extract_text_before(text, "BLAH", 1) == "Teacher: BLAH" diff --git a/unstructured/cleaners/extract.py b/unstructured/cleaners/extract.py index b576f9ccc6..30f9a9d050 100644 --- a/unstructured/cleaners/extract.py +++ b/unstructured/cleaners/extract.py @@ -18,6 +18,7 @@ def _get_indexed_match(text: str, pattern: str, index: int = 0) -> re.Match: raise ValueError(f"The index is {index}. Index must be a non-negative integer.") regex_match = None + i = -1 for i, result in enumerate(re.finditer(pattern, text)): if i == index: regex_match = result