diff --git a/changes.txt b/changes.txt index 3ec8841a8..996c43f10 100644 --- a/changes.txt +++ b/changes.txt @@ -2,6 +2,26 @@ Change Log ========== +Fixed issues: + +* **Fixed** `4670 `_: scrub fails to remove hidden text after clean_contents stopped including line breaks (\u2265 1.24.0) +* **Fixed** `4943 `_: enh: applying redactions with image cropping for currently unsupported colorspaces +* **Fixed** `5030 `_: find_tables() with layout enabled can return a zero-cell Table, and Table.bbox then raises "ValueError: min() iterable argument is empty" +* **Fixed** `5044 `_: Outline (TOC) parsing bug +* **Fixed** `5049 `_: font subsetting segfaults in 1.28.0, regression from 1.27.2.2 #5049 +* **Fixed** `5042 `_: Page.get_texttrace() leaks None references \u2014 Fatal Python error (none_dealloc) in long-running processes (1.27.2.3 & 1.28.0) + + +Other: + +* Output warning when legacy `fitz` module is imported. +* Cope better with markdown containing illegal utf8 sequences. +* Fixed building with PYMUPDF_SETUP_MUPDF_VS_UPGRADE. +* pymupdf.Page.find_tables(): + * new args `use_layout: bool = True` `union: bool = False` `refine: bool = False`. + * Improved speed. + + **Changes in version 1.28.0** (2026-06-29) Fixed issues: @@ -21,6 +41,7 @@ Other: * Support Windows builds with free thread python. * pymupdf.Document.save() now saves non-PDF documents in PDF format. * New method pymupdf.Document.apply_css(). +* Pyodide wheel is available on pypi.org. **Changes in version 1.27.2.3** (2026-04-24) diff --git a/src/table.py b/src/table.py index 68a771966..7b8e2c19c 100644 --- a/src/table.py +++ b/src/table.py @@ -2983,7 +2983,8 @@ def find_tables( tp2 = page.get_textpage(flags=TABLE_DETECTOR_FLAGS) for rect in my_boxes: cells = make_table_from_bbox(tp2, word_rects, rect) # pylint: disable=E0606 - tbf.tables.append(Table(page, cells)) + if cells: + tbf.tables.append(Table(page, cells)) if refine: # Grid refinement + reconstruction. Runs while the page is still # derotated (before the finally block resets rotation) so word and diff --git a/tests/resources/test_4936.pdf b/tests/resources/test_4936.pdf new file mode 100644 index 000000000..f67cac7cf Binary files /dev/null and b/tests/resources/test_4936.pdf differ diff --git a/tests/resources/test_4943.pdf b/tests/resources/test_4943.pdf new file mode 100644 index 000000000..f142f5245 Binary files /dev/null and b/tests/resources/test_4943.pdf differ diff --git a/tests/test_annots.py b/tests/test_annots.py index e19c2efc9..86de33843 100644 --- a/tests/test_annots.py +++ b/tests/test_annots.py @@ -753,3 +753,40 @@ def test_5033(): annot.update() annot.set_rotation(0) annot.update() + + +def test_4943(): + if pymupdf.pymupdf_version_tuple == (1, 28, 0) and pymupdf.mupdf_version_tuple == (1, 29, 0): + print(f'test_4943():not running because pymupdf-1.28.0 has ambiguous mupdf version.') + return + path = os.path.normpath(f'{__file__}/../../tests/resources/test_4943.pdf') + with pymupdf.open(path) as document: + page = document[0] + page.add_redact_annot(page.rect) + expect_fail = pymupdf.mupdf_version_tuple <= (1, 28, 0) + print(f'{pymupdf.pymupdf_version_tuple=} {pymupdf.mupdf_version_tuple=} {expect_fail=}.') + try: + page.apply_redactions(images=pymupdf.PDF_REDACT_IMAGE_PIXELS) + except pymupdf.mupdf.FzErrorArgument as e: + print(f'Exception: {e}') + assert expect_fail, f'{pymupdf.mupdf_version_tuple=} {pymupdf.pymupdf_version_tuple=}' + else: + print(f'No exception.') + assert not expect_fail, f'{pymupdf.mupdf_version_tuple=} {pymupdf.pymupdf_version_tuple=}' + + +def test_4936(): + path = os.path.normpath(f'{__file__}/../../tests/resources/test_4936.pdf') + with pymupdf.open(path) as document: + page = document[0] + rect = pymupdf.Rect( + pymupdf.FZ_MIN_INF_RECT, + pymupdf.FZ_MIN_INF_RECT, + pymupdf.FZ_MAX_INF_RECT, + pymupdf.FZ_MAX_INF_RECT, + ) + page.add_redact_annot(rect, fill=False) + page.apply_redactions(graphics=2) + drawings = page.get_drawings() + print(f'{len(drawings)=}') + assert len(drawings) == 0 diff --git a/tests/test_tables.py b/tests/test_tables.py index 66ce4c761..9fbeec387 100644 --- a/tests/test_tables.py +++ b/tests/test_tables.py @@ -302,6 +302,9 @@ def test_find_tables_state_is_call_local_for_threads(): if platform.python_implementation() == "GraalVM": print("test_find_tables_state_is_call_local_for_threads(): not running because slow on GraalVM.") return + if os.environ.get('PYODIDE_ROOT'): + print('test_find_tables_state_is_call_local_for_threads(): not running on Pyodide - threads unsupported.') + return pdf_bytes = _make_find_tables_state_doc() expected = _find_tables_use_layout_false_signature(pdf_bytes)