mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-02-14 00:09:35 -06:00
Breaking: Remove pybzar as a barcode reader (#12065)
This commit is contained in:
@@ -28,8 +28,6 @@ from documents.utils import maybe_override_pixel_limit
|
||||
from paperless.config import BarcodeConfig
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
from PIL import Image
|
||||
|
||||
logger = logging.getLogger("paperless.barcodes")
|
||||
@@ -262,26 +260,6 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
|
||||
return barcodes
|
||||
|
||||
@staticmethod
|
||||
def read_barcodes_pyzbar(image: Image.Image) -> list[str]:
|
||||
barcodes = []
|
||||
|
||||
from pyzbar import pyzbar
|
||||
|
||||
# Decode the barcode image
|
||||
detected_barcodes = pyzbar.decode(image)
|
||||
|
||||
# Traverse through all the detected barcodes in image
|
||||
for barcode in detected_barcodes:
|
||||
if barcode.data:
|
||||
decoded_barcode = barcode.data.decode("utf-8")
|
||||
barcodes.append(decoded_barcode)
|
||||
logger.debug(
|
||||
f"Barcode of type {barcode.type} found: {decoded_barcode}",
|
||||
)
|
||||
|
||||
return barcodes
|
||||
|
||||
def detect(self) -> None:
|
||||
"""
|
||||
Scan all pages of the PDF as images, updating barcodes and the pages
|
||||
@@ -294,14 +272,6 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
# No op if not a TIFF
|
||||
self.convert_from_tiff_to_pdf()
|
||||
|
||||
# Choose the library for reading
|
||||
if settings.CONSUMER_BARCODE_SCANNER == "PYZBAR":
|
||||
reader: Callable[[Image.Image], list[str]] = self.read_barcodes_pyzbar
|
||||
logger.debug("Scanning for barcodes using PYZBAR")
|
||||
else:
|
||||
reader = self.read_barcodes_zxing
|
||||
logger.debug("Scanning for barcodes using ZXING")
|
||||
|
||||
try:
|
||||
# Read number of pages from pdf
|
||||
with Pdf.open(self.pdf_file) as pdf:
|
||||
@@ -349,7 +319,7 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
||||
)
|
||||
|
||||
# Detect barcodes
|
||||
for barcode_value in reader(page):
|
||||
for barcode_value in self.read_barcodes_zxing(page):
|
||||
self.barcodes.append(
|
||||
Barcode(current_page_number, barcode_value, self.settings),
|
||||
)
|
||||
|
||||
@@ -4,7 +4,6 @@ from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.test import override_settings
|
||||
@@ -25,13 +24,6 @@ from documents.tests.utils import FileSystemAssertsMixin
|
||||
from documents.tests.utils import SampleDirMixin
|
||||
from paperless.models import ApplicationConfiguration
|
||||
|
||||
try:
|
||||
import zxingcpp # noqa: F401
|
||||
|
||||
HAS_ZXING_LIB = True
|
||||
except ImportError:
|
||||
HAS_ZXING_LIB = False
|
||||
|
||||
|
||||
class GetReaderPluginMixin:
|
||||
@contextmanager
|
||||
@@ -48,7 +40,6 @@ class GetReaderPluginMixin:
|
||||
reader.cleanup()
|
||||
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
class TestBarcode(
|
||||
DirectoriesMixin,
|
||||
FileSystemAssertsMixin,
|
||||
@@ -606,7 +597,6 @@ class TestBarcode(
|
||||
self.assertDictEqual(separator_page_numbers, {0: False})
|
||||
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
class TestBarcodeNewConsume(
|
||||
DirectoriesMixin,
|
||||
FileSystemAssertsMixin,
|
||||
@@ -784,36 +774,12 @@ class TestAsnBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
|
||||
|
||||
self.assertEqual(document.archive_serial_number, 123)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
def test_scan_file_for_qrcode_without_upscale(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A printed and scanned PDF document with a rather small QR code
|
||||
WHEN:
|
||||
- ASN barcode detection is run with default settings
|
||||
- pyzbar is used for detection, as zxing would behave differently, and detect the QR code
|
||||
THEN:
|
||||
- ASN is not detected
|
||||
"""
|
||||
|
||||
test_file = self.BARCODE_SAMPLE_DIR / "barcode-qr-asn-000123-upscale-dpi.pdf"
|
||||
|
||||
with self.get_reader(test_file) as reader:
|
||||
reader.detect()
|
||||
self.assertEqual(len(reader.barcodes), 0)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
@override_settings(CONSUMER_BARCODE_DPI=600)
|
||||
@override_settings(CONSUMER_BARCODE_UPSCALE=1.5)
|
||||
def test_scan_file_for_qrcode_with_upscale(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A printed and scanned PDF document with a rather small QR code
|
||||
WHEN:
|
||||
- ASN barcode detection is run with 600dpi and an upscale factor of 1.5 and pyzbar
|
||||
- pyzbar is used for detection, as zxing would behave differently.
|
||||
Upscaling is a workaround for detection problems with pyzbar,
|
||||
when you cannot switch to zxing (aarch64 build problems of zxing)
|
||||
THEN:
|
||||
- ASN 123 is detected
|
||||
"""
|
||||
@@ -825,23 +791,24 @@ class TestAsnBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
|
||||
self.assertEqual(len(reader.barcodes), 1)
|
||||
self.assertEqual(reader.asn, 123)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_DPI=600)
|
||||
@override_settings(CONSUMER_BARCODE_UPSCALE=1.5)
|
||||
def test_scan_file_for_qrcode_with_upscale(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A printed and scanned PDF document with a rather small QR code
|
||||
WHEN:
|
||||
- ASN barcode detection is run with 600dpi and an upscale factor of 1.5
|
||||
THEN:
|
||||
- ASN 123 is detected
|
||||
"""
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not HAS_ZXING_LIB,
|
||||
reason="No zxingcpp",
|
||||
)
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="ZXING")
|
||||
class TestBarcodeZxing(TestBarcode):
|
||||
pass
|
||||
test_file = self.BARCODE_SAMPLE_DIR / "barcode-qr-asn-000123-upscale-dpi.pdf"
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not HAS_ZXING_LIB,
|
||||
reason="No zxingcpp",
|
||||
)
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="ZXING")
|
||||
class TestAsnBarcodesZxing(TestAsnBarcode):
|
||||
pass
|
||||
with self.get_reader(test_file) as reader:
|
||||
reader.detect()
|
||||
self.assertEqual(len(reader.barcodes), 1)
|
||||
self.assertEqual(reader.asn, 123)
|
||||
|
||||
|
||||
class TestTagBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, TestCase):
|
||||
|
||||
@@ -167,17 +167,6 @@ def settings_values_check(app_configs, **kwargs):
|
||||
)
|
||||
return msgs
|
||||
|
||||
def _barcode_scanner_validate():
|
||||
"""
|
||||
Validates the barcode scanner type
|
||||
"""
|
||||
msgs = []
|
||||
if settings.CONSUMER_BARCODE_SCANNER not in ["PYZBAR", "ZXING"]:
|
||||
msgs.append(
|
||||
Error(f'Invalid Barcode Scanner "{settings.CONSUMER_BARCODE_SCANNER}"'),
|
||||
)
|
||||
return msgs
|
||||
|
||||
def _email_certificate_validate():
|
||||
msgs = []
|
||||
# Existence checks
|
||||
@@ -195,7 +184,6 @@ def settings_values_check(app_configs, **kwargs):
|
||||
return (
|
||||
_ocrmypdf_settings_check()
|
||||
+ _timezone_validate()
|
||||
+ _barcode_scanner_validate()
|
||||
+ _email_certificate_validate()
|
||||
)
|
||||
|
||||
|
||||
@@ -1106,11 +1106,6 @@ CONSUMER_BARCODE_STRING: Final[str] = os.getenv(
|
||||
"PATCHT",
|
||||
)
|
||||
|
||||
CONSUMER_BARCODE_SCANNER: Final[str] = os.getenv(
|
||||
"PAPERLESS_CONSUMER_BARCODE_SCANNER",
|
||||
"PYZBAR",
|
||||
).upper()
|
||||
|
||||
CONSUMER_ENABLE_ASN_BARCODE: Final[bool] = __get_boolean(
|
||||
"PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE",
|
||||
)
|
||||
|
||||
@@ -187,31 +187,6 @@ class TestTimezoneSettingsChecks(DirectoriesMixin, TestCase):
|
||||
self.assertIn('Timezone "TheMoon\\MyCrater"', msg.msg)
|
||||
|
||||
|
||||
class TestBarcodeSettingsChecks(DirectoriesMixin, TestCase):
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="Invalid")
|
||||
def test_barcode_scanner_invalid(self) -> None:
|
||||
msgs = settings_values_check(None)
|
||||
self.assertEqual(len(msgs), 1)
|
||||
|
||||
msg = msgs[0]
|
||||
|
||||
self.assertIn('Invalid Barcode Scanner "Invalid"', msg.msg)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="")
|
||||
def test_barcode_scanner_empty(self) -> None:
|
||||
msgs = settings_values_check(None)
|
||||
self.assertEqual(len(msgs), 1)
|
||||
|
||||
msg = msgs[0]
|
||||
|
||||
self.assertIn('Invalid Barcode Scanner ""', msg.msg)
|
||||
|
||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
||||
def test_barcode_scanner_valid(self) -> None:
|
||||
msgs = settings_values_check(None)
|
||||
self.assertEqual(len(msgs), 0)
|
||||
|
||||
|
||||
class TestEmailCertSettingsChecks(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
@override_settings(EMAIL_CERTIFICATE_FILE=Path("/tmp/not_actually_here.pem"))
|
||||
def test_not_valid_file(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user