From 656cbeac1cb62d025adfc1c124f38465d1d4af11 Mon Sep 17 00:00:00 2001 From: jipeng6036-del Date: Tue, 6 Oct 2026 01:51:39 -0700 Subject: [PATCH] fix: keep overlap category names from element 100 on --- CHANGELOG.md | 4 ++++ test_unstructured/test_utils.py | 39 ++++++++++++++++++++++++++++++++- unstructured/utils.py | 5 +++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 873d7e4c50..d429435219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.27.19-dev0 +### Fixes + +- **Keep overlap category names intact from element 100 on.** `identify_overlapping_or_nesting_case()` split `{ix}. {category}` labels with a 3-character slice, so from index 100 the leftover digits leaked into `overlapping_elements` and `overlapping_case`. It now splits on the first `". "`. + ### Maintenance - **Start CI tests without waiting for setup and lint.** Lint installs only its own dependency group, extras jobs install only the system packages their tests use, and a new push cancels the pull request's previous CI run. diff --git a/test_unstructured/test_utils.py b/test_unstructured/test_utils.py index abde59e22c..a74fc09a3e 100644 --- a/test_unstructured/test_utils.py +++ b/test_unstructured/test_utils.py @@ -7,7 +7,7 @@ from unstructured import utils from unstructured.documents.coordinates import PixelSpace -from unstructured.documents.elements import ElementMetadata, NarrativeText, Title +from unstructured.documents.elements import ElementMetadata, NarrativeText, Table, Title @pytest.fixture() @@ -312,6 +312,43 @@ def test_catch_overlapping_and_nested_bboxes_non_overlapping_case(): assert overlapping_cases == [] +@pytest.mark.parametrize("n_filler", [0, 100, 1000]) +def test_catch_overlapping_and_nested_bboxes_keeps_category_past_element_99(n_filler): + coordinate_system = PixelSpace(width=1000, height=1000) + fillers = [ + NarrativeText( + text=f"filler {i}", + coordinates=((0, i), (0, i + 1), (5, i + 1), (5, i)), + coordinate_system=coordinate_system, + metadata=ElementMetadata(page_number=1), + ) + for i in range(n_filler) + ] + elements = fillers + [ + Table( + text="cell a cell b", + coordinates=((0, 0), (0, 500), (500, 500), (500, 0)), + coordinate_system=coordinate_system, + metadata=ElementMetadata(page_number=2), + ), + Title( + text="cell a", + coordinates=((10, 10), (10, 50), (100, 50), (100, 10)), + coordinate_system=coordinate_system, + metadata=ElementMetadata(page_number=2), + ), + ] + + overlapping_flag, overlapping_cases = utils.catch_overlapping_and_nested_bboxes(elements) + + assert overlapping_flag is True + assert overlapping_cases[0]["overlapping_elements"] == [ + f"Table(ix={n_filler})", + f"Title(ix={n_filler + 1})", + ] + assert overlapping_cases[0]["overlapping_case"] == "nested Title in Table" + + def test_only_returns_singleton_iterable(): singleton_iterable = [42] result = utils.only(singleton_iterable) diff --git a/unstructured/utils.py b/unstructured/utils.py index ba87f63c01..39b9bf1d01 100644 --- a/unstructured/utils.py +++ b/unstructured/utils.py @@ -500,8 +500,9 @@ def identify_overlapping_or_nesting_case( type1, type2 = label_pair ix_element1 = "".join([ch for ch in type1 if ch.isnumeric()]) ix_element2 = "".join([ch for ch in type2 if ch.isnumeric()]) - type1 = type1[3:].strip() - type2 = type2[3:].strip() + # Labels are "{ix}. {category}". type1[3:] only strips a one-digit index. + type1 = type1.split(". ", 1)[-1] + type2 = type2.split(". ", 1)[-1] box1_corners = _convert_coordinates_to_box(box1) box2_corners = _convert_coordinates_to_box(box2) x_bottom_left_1, y_bottom_left_1, x_top_right_1, y_top_right_1 = box1_corners