From 4b86f605a37b1fc6bac31df8f0e560da7d2b01f4 Mon Sep 17 00:00:00 2001 From: bosd Date: Mon, 14 Oct 2024 00:07:42 +0200 Subject: [PATCH] [IMP] Add conversion exception message to feedback [IMP] Ghostscriptbackend add exception message passtrough [IMP] Error tests and feedback message --- camelot/backends/ghostscript_backend.py | 2 +- camelot/backends/image_conversion.py | 4 ++-- tests/test_common.py | 16 ++++++++++------ tests/test_errors.py | 25 +++++++++++++++++++++++-- tests/test_image_conversion_backend.py | 2 +- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/camelot/backends/ghostscript_backend.py b/camelot/backends/ghostscript_backend.py index b8ffd1dd..f5741e99 100644 --- a/camelot/backends/ghostscript_backend.py +++ b/camelot/backends/ghostscript_backend.py @@ -25,7 +25,7 @@ def convert(self, pdf_path: str, png_path: str, resolution: int = 300) -> None: """ try: import ghostscript # type: ignore[import-untyped] - except RuntimeError: + except ModuleNotFoundError as ex: raise OSError( "Ghostscript is not installed. You can install it using the instructions" " here: https://pypdf-table-extraction.readthedocs.io/en/latest/user/install-deps.html" diff --git a/camelot/backends/image_conversion.py b/camelot/backends/image_conversion.py index 63b545e0..f0d95257 100644 --- a/camelot/backends/image_conversion.py +++ b/camelot/backends/image_conversion.py @@ -73,10 +73,10 @@ def convert(self, pdf_path: str, png_path: str) -> None: converter = BACKENDS[fallback]() converter.convert(pdf_path, png_path) except Exception as e: - msg = f"Image conversion failed with image conversion backend {fallback!r}" + msg = f"Image conversion failed with image conversion backend {fallback!r}\n error: {e}" raise ImageConversionError(msg) from e else: break else: - msg = f"Image conversion failed with image conversion backend {self.backend!r}" + msg = f"Image conversion failed with image conversion backend {self.backend!r}\n error: {f}" raise ImageConversionError(msg) from f diff --git a/tests/test_common.py b/tests/test_common.py index f4717668..3141a0b5 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -73,17 +73,17 @@ def test_url_ghostscript(testdir): @skip_pdftopng def test_pages_poppler(): url = "https://pypdf-table-extraction.readthedocs.io/en/latest/_static/pdf/foo.pdf" - tables = camelot.read_pdf(url, backend="poppler") + tables = camelot.read_pdf(url, backend="poppler", use_fallback=False) assert repr(tables) == "" assert repr(tables[0]) == "" assert repr(tables[0].cells[0][0]) == "" - tables = camelot.read_pdf(url, pages="1-end", backend="poppler") + tables = camelot.read_pdf(url, pages="1-end", backend="poppler", use_fallback=False) assert repr(tables) == "" assert repr(tables[0]) == "
" assert repr(tables[0].cells[0][0]) == "" - tables = camelot.read_pdf(url, pages="all", backend="poppler") + tables = camelot.read_pdf(url, pages="all", backend="poppler", use_fallback=False) assert repr(tables) == "" assert repr(tables[0]) == "
" assert repr(tables[0].cells[0][0]) == "" @@ -92,17 +92,21 @@ def test_pages_poppler(): @skip_on_windows def test_pages_ghostscript(): url = "https://pypdf-table-extraction.readthedocs.io/en/latest/_static/pdf/foo.pdf" - tables = camelot.read_pdf(url, backend="ghostscript") + tables = camelot.read_pdf(url, backend="ghostscript", use_fallback=False) assert repr(tables) == "" assert repr(tables[0]) == "
" assert repr(tables[0].cells[0][0]) == "" - tables = camelot.read_pdf(url, pages="1-end", backend="ghostscript") + tables = camelot.read_pdf( + url, pages="1-end", backend="ghostscript", use_fallback=False + ) assert repr(tables) == "" assert repr(tables[0]) == "
" assert repr(tables[0].cells[0][0]) == "" - tables = camelot.read_pdf(url, pages="all", backend="ghostscript") + tables = camelot.read_pdf( + url, pages="all", backend="ghostscript", use_fallback=False + ) assert repr(tables) == "" assert repr(tables[0]) == "
" assert repr(tables[0].cells[0][0]) == "" diff --git a/tests/test_errors.py b/tests/test_errors.py index a08fc630..19f7c212 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -1,9 +1,12 @@ import os +import sys import warnings +from unittest import mock import pytest import camelot +from camelot.backends.image_conversion import ImageConversionError from camelot.utils import is_url from tests.conftest import skip_on_windows @@ -122,7 +125,9 @@ def test_lattice_no_tables_on_page(testdir): def test_lattice_unknown_backend(foo_pdf): message = "Unknown backend 'mupdf' specified. Please use either 'poppler' or 'ghostscript'." with pytest.raises(NotImplementedError, match=message): - tables = camelot.read_pdf(foo_pdf, backend="mupdf") + tables = camelot.read_pdf( + foo_pdf, flavor="lattice", backend="mupdf", use_fallback=False + ) def test_lattice_no_convert_method(foo_pdf): @@ -131,7 +136,9 @@ class ConversionBackend: message = "must implement a 'convert' method" with pytest.raises(NotImplementedError, match=message): - camelot.read_pdf(foo_pdf, backend=ConversionBackend()) + camelot.read_pdf( + foo_pdf, flavor="lattice", backend=ConversionBackend(), use_fallback=False + ) def test_invalid_url(): @@ -140,3 +147,17 @@ def test_invalid_url(): with pytest.raises(Exception, match=message): url = camelot.read_pdf(url) assert is_url(url) == False + + +def test_ghostscript_backend_import_error(testdir): + filename = os.path.join(testdir, "table_region.pdf") + with mock.patch.dict(sys.modules, {"ghostscript": None}): + message = "Ghostscript is not installed" + with pytest.raises(ImageConversionError) as e: + tables = camelot.read_pdf( + filename, + flavor="lattice", + backend="ghostscript", + use_fallback=False, + ) + assert message in str(e.value) diff --git a/tests/test_image_conversion_backend.py b/tests/test_image_conversion_backend.py index 7130daae..0a4320a8 100644 --- a/tests/test_image_conversion_backend.py +++ b/tests/test_image_conversion_backend.py @@ -54,6 +54,6 @@ def test_ghostscript_backend_error_when_use_fallback(monkeypatch): ) backend = ImageConversionBackend(backend="ghostscript") - message = "Image conversion failed with image conversion backend 'ghostscript'" + message = "Image conversion failed with image conversion backend 'poppler'\n error: Image conversion failed" with pytest.raises(ValueError, match=message): backend.convert("foo", "bar")