From 18495ce9dab1addbd6e35f766839c50f7d6810ff Mon Sep 17 00:00:00 2001 From: Daniel Quinn Date: Sun, 27 Nov 2016 15:06:45 +0000 Subject: [PATCH] Fix for #154 * Added a test with a faked pyocr and tesseract * Added a catch for pyocr's *other* TesseractError --- src/documents/consumer.py | 36 ++++++++--------- src/documents/tests/samples/no-text.png | Bin 0 -> 32595 bytes src/documents/tests/test_consumer.py | 50 +++++++++++++++++++++++- 3 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 src/documents/tests/samples/no-text.png diff --git a/src/documents/consumer.py b/src/documents/consumer.py index 147b45edd..02397c118 100644 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -1,33 +1,31 @@ -import datetime -import hashlib -import logging -import tempfile -import uuid - -from multiprocessing.pool import Pool - -import itertools - -import langdetect import os import re +import uuid +import shutil +import hashlib +import logging +import datetime +import tempfile +import itertools import subprocess +from multiprocessing.pool import Pool import pyocr -import shutil - +import langdetect from PIL import Image - from django.conf import settings from django.utils import timezone -from pyocr.tesseract import TesseractError - from paperless.db import GnuPG +from pyocr.tesseract import TesseractError +from pyocr.libtesseract.tesseract_raw import \ + TesseractError as OtherTesseractError from .models import Tag, Document, FileInfo -from .languages import ISO639 from .signals import ( - document_consumption_started, document_consumption_finished) + document_consumption_started, + document_consumption_finished +) +from .languages import ISO639 class OCRError(Exception): @@ -381,7 +379,7 @@ def image_to_string(args): try: orientation = ocr.detect_orientation(f, lang=lang) f = f.rotate(orientation["angle"], expand=1) - except TesseractError: + except (TesseractError, OtherTesseractError): pass return ocr.image_to_string(f, lang=lang) diff --git a/src/documents/tests/samples/no-text.png b/src/documents/tests/samples/no-text.png new file mode 100644 index 0000000000000000000000000000000000000000..e78b22bfbe53be5a9046bbfb32fef7e98abb9be9 GIT binary patch literal 32595 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 LNkvXXu0mjfD4>h= literal 0 HcmV?d00001 diff --git a/src/documents/tests/test_consumer.py b/src/documents/tests/test_consumer.py index 18bbab50f..f4c7039a9 100644 --- a/src/documents/tests/test_consumer.py +++ b/src/documents/tests/test_consumer.py @@ -1,7 +1,13 @@ -from django.test import TestCase +import os +from unittest import mock, skipIf + +import pyocr +from django.test import TestCase +from pyocr.libtesseract.tesseract_raw import \ + TesseractError as OtherTesseractError -from ..consumer import strip_excess_whitespace from ..models import FileInfo +from ..consumer import image_to_string, strip_excess_whitespace class TestAttributes(TestCase): @@ -304,6 +310,28 @@ class TestFieldPermutations(TestCase): template.format(**spec), **spec) +class FakeTesseract(object): + + @staticmethod + def can_detect_orientation(): + return True + + @staticmethod + def detect_orientation(file_handle, lang): + raise OtherTesseractError("arbitrary status", "message") + + @staticmethod + def image_to_string(file_handle, lang): + return "This is test text" + + +class FakePyOcr(object): + + @staticmethod + def get_available_tools(): + return [FakeTesseract] + + class TestOCR(TestCase): text_cases = [ @@ -317,6 +345,9 @@ class TestOCR(TestCase): "utf-8 строка с пробелами в конце" ) ] + + SAMPLE_FILES = os.path.join(os.path.dirname(__file__), "samples") + TESSERACT_INSTALLED = bool(pyocr.get_available_tools()) def test_strip_excess_whitespace(self): for source, result in self.text_cases: @@ -330,3 +361,18 @@ class TestOCR(TestCase): actual_result ) ) + + @skipIf(not TESSERACT_INSTALLED, "Tesseract not installed. Skipping") + @mock.patch("documents.consumer.Consumer.SCRATCH", SAMPLE_FILES) + @mock.patch("documents.consumer.pyocr", FakePyOcr) + def test_image_to_string_with_text_free_page(self): + """ + This test is sort of silly, since it's really just reproducing an odd + exception thrown by pyocr when it encounters a page with no text. + Actually running this test against an installation of Tesseract results + in a segmentation fault rooted somewhere deep inside pyocr where I + don't care to dig. Regardless, if you run the consumer normally, + text-free pages are now handled correctly so long as we work around + this weird exception. + """ + image_to_string(["text.png", "en"])