mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-02-11 23:59:31 -06:00
Removes all pyzbar/libzbar
This commit is contained in:
@@ -64,8 +64,6 @@ ARG RUNTIME_PACKAGES="\
|
|||||||
libmagic1 \
|
libmagic1 \
|
||||||
media-types \
|
media-types \
|
||||||
zlib1g \
|
zlib1g \
|
||||||
# Barcode splitter
|
|
||||||
libzbar0 \
|
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
htop \
|
htop \
|
||||||
sudo"
|
sudo"
|
||||||
|
|||||||
1
.github/dependabot.yml
vendored
1
.github/dependabot.yml
vendored
@@ -69,7 +69,6 @@ updates:
|
|||||||
patterns:
|
patterns:
|
||||||
- "ocrmypdf"
|
- "ocrmypdf"
|
||||||
- "pdf2image"
|
- "pdf2image"
|
||||||
- "pyzbar"
|
|
||||||
- "zxing-cpp"
|
- "zxing-cpp"
|
||||||
- "tika-client"
|
- "tika-client"
|
||||||
- "gotenberg-client"
|
- "gotenberg-client"
|
||||||
|
|||||||
2
.github/workflows/ci-backend.yml
vendored
2
.github/workflows/ci-backend.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -qq --no-install-recommends \
|
sudo apt-get install -qq --no-install-recommends \
|
||||||
unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils
|
unpaper tesseract-ocr imagemagick ghostscript poppler-utils
|
||||||
- name: Configure ImageMagick
|
- name: Configure ImageMagick
|
||||||
run: |
|
run: |
|
||||||
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ src/documents/admin.py:0: error: Skipping analyzing "auditlog.models": module is
|
|||||||
src/documents/admin.py:0: error: Skipping analyzing "treenode.admin": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
src/documents/admin.py:0: error: Skipping analyzing "treenode.admin": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
||||||
src/documents/barcodes.py:0: error: "Image" has no attribute "filename" [attr-defined]
|
src/documents/barcodes.py:0: error: "Image" has no attribute "filename" [attr-defined]
|
||||||
src/documents/barcodes.py:0: error: Cannot find implementation or library stub for module named "zxingcpp" [import-not-found]
|
src/documents/barcodes.py:0: error: Cannot find implementation or library stub for module named "zxingcpp" [import-not-found]
|
||||||
src/documents/barcodes.py:0: error: Skipping analyzing "pyzbar": module is installed, but missing library stubs or py.typed marker [import-untyped]
|
|
||||||
src/documents/bulk_download.py:0: error: Return type "None" of "add_document" incompatible with return type "Never" in supertype "BulkArchiveStrategy" [override]
|
src/documents/bulk_download.py:0: error: Return type "None" of "add_document" incompatible with return type "Never" in supertype "BulkArchiveStrategy" [override]
|
||||||
src/documents/bulk_download.py:0: error: Return type "None" of "add_document" incompatible with return type "Never" in supertype "BulkArchiveStrategy" [override]
|
src/documents/bulk_download.py:0: error: Return type "None" of "add_document" incompatible with return type "Never" in supertype "BulkArchiveStrategy" [override]
|
||||||
src/documents/bulk_download.py:0: error: Return type "None" of "add_document" incompatible with return type "Never" in supertype "BulkArchiveStrategy" [override]
|
src/documents/bulk_download.py:0: error: Return type "None" of "add_document" incompatible with return type "Never" in supertype "BulkArchiveStrategy" [override]
|
||||||
|
|||||||
@@ -154,8 +154,6 @@ ARG RUNTIME_PACKAGES="\
|
|||||||
libmagic1 \
|
libmagic1 \
|
||||||
media-types \
|
media-types \
|
||||||
zlib1g \
|
zlib1g \
|
||||||
# Barcode splitter
|
|
||||||
libzbar0 \
|
|
||||||
poppler-utils"
|
poppler-utils"
|
||||||
|
|
||||||
# Install basic runtime packages.
|
# Install basic runtime packages.
|
||||||
|
|||||||
@@ -774,7 +774,6 @@ At this time, the library utilized for detection of barcodes supports the follow
|
|||||||
- QR Code
|
- QR Code
|
||||||
- SQ Code
|
- SQ Code
|
||||||
|
|
||||||
You may check for updates on the [zbar library homepage](https://github.com/mchehab/zbar).
|
|
||||||
For usage in Paperless, the type of barcode does not matter, only the contents of it.
|
For usage in Paperless, the type of barcode does not matter, only the contents of it.
|
||||||
|
|
||||||
For how to enable barcode usage, see [the configuration](configuration.md#barcodes).
|
For how to enable barcode usage, see [the configuration](configuration.md#barcodes).
|
||||||
|
|||||||
@@ -1222,14 +1222,6 @@ using Python's `re.match()`, which anchors at the start of the filename.
|
|||||||
|
|
||||||
The default ignores are `[.stfolder, .stversions, .localized, @eaDir, .Spotlight-V100, .Trashes, __MACOSX]` and cannot be overridden.
|
The default ignores are `[.stfolder, .stversions, .localized, @eaDir, .Spotlight-V100, .Trashes, __MACOSX]` and cannot be overridden.
|
||||||
|
|
||||||
#### [`PAPERLESS_CONSUMER_BARCODE_SCANNER=<string>`](#PAPERLESS_CONSUMER_BARCODE_SCANNER) {#PAPERLESS_CONSUMER_BARCODE_SCANNER}
|
|
||||||
|
|
||||||
: Sets the barcode scanner used for barcode functionality.
|
|
||||||
|
|
||||||
Currently, "PYZBAR" (the default) or "ZXING" might be selected.
|
|
||||||
If you have problems that your Barcodes/QR-Codes are not detected
|
|
||||||
(especially with bad scan quality and/or small codes), try the other one.
|
|
||||||
|
|
||||||
#### [`PAPERLESS_PRE_CONSUME_SCRIPT=<filename>`](#PAPERLESS_PRE_CONSUME_SCRIPT) {#PAPERLESS_PRE_CONSUME_SCRIPT}
|
#### [`PAPERLESS_PRE_CONSUME_SCRIPT=<filename>`](#PAPERLESS_PRE_CONSUME_SCRIPT) {#PAPERLESS_PRE_CONSUME_SCRIPT}
|
||||||
|
|
||||||
: After some initial validation, Paperless can trigger an arbitrary
|
: After some initial validation, Paperless can trigger an arbitrary
|
||||||
|
|||||||
@@ -207,13 +207,12 @@ are released, dependency support is confirmed, etc.
|
|||||||
- `libpq-dev` for PostgreSQL
|
- `libpq-dev` for PostgreSQL
|
||||||
- `libmagic-dev` for mime type detection
|
- `libmagic-dev` for mime type detection
|
||||||
- `mariadb-client` for MariaDB compile time
|
- `mariadb-client` for MariaDB compile time
|
||||||
- `libzbar0` for barcode detection
|
|
||||||
- `poppler-utils` for barcode detection
|
- `poppler-utils` for barcode detection
|
||||||
|
|
||||||
Use this list for your preferred package management:
|
Use this list for your preferred package management:
|
||||||
|
|
||||||
```
|
```
|
||||||
python3 python3-pip python3-dev imagemagick fonts-liberation gnupg libpq-dev default-libmysqlclient-dev pkg-config libmagic-dev libzbar0 poppler-utils
|
python3 python3-pip python3-dev imagemagick fonts-liberation gnupg libpq-dev default-libmysqlclient-dev pkg-config libmagic-dev poppler-utils
|
||||||
```
|
```
|
||||||
|
|
||||||
These dependencies are required for OCRmyPDF, which is used for text
|
These dependencies are required for OCRmyPDF, which is used for text
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ dependencies = [
|
|||||||
"python-gnupg~=0.5.4",
|
"python-gnupg~=0.5.4",
|
||||||
"python-ipware~=3.0.0",
|
"python-ipware~=3.0.0",
|
||||||
"python-magic~=0.4.27",
|
"python-magic~=0.4.27",
|
||||||
"pyzbar~=0.1.9",
|
|
||||||
"rapidfuzz~=3.14.0",
|
"rapidfuzz~=3.14.0",
|
||||||
"redis[hiredis]~=5.2.1",
|
"redis[hiredis]~=5.2.1",
|
||||||
"regex>=2025.9.18",
|
"regex>=2025.9.18",
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ from documents.utils import maybe_override_pixel_limit
|
|||||||
from paperless.config import BarcodeConfig
|
from paperless.config import BarcodeConfig
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from collections.abc import Callable
|
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
logger = logging.getLogger("paperless.barcodes")
|
logger = logging.getLogger("paperless.barcodes")
|
||||||
@@ -262,26 +260,6 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
|||||||
|
|
||||||
return barcodes
|
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:
|
def detect(self) -> None:
|
||||||
"""
|
"""
|
||||||
Scan all pages of the PDF as images, updating barcodes and the pages
|
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
|
# No op if not a TIFF
|
||||||
self.convert_from_tiff_to_pdf()
|
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:
|
try:
|
||||||
# Read number of pages from pdf
|
# Read number of pages from pdf
|
||||||
with Pdf.open(self.pdf_file) as pdf:
|
with Pdf.open(self.pdf_file) as pdf:
|
||||||
@@ -349,7 +319,7 @@ class BarcodePlugin(ConsumeTaskPlugin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Detect barcodes
|
# Detect barcodes
|
||||||
for barcode_value in reader(page):
|
for barcode_value in self.read_barcodes_zxing(page):
|
||||||
self.barcodes.append(
|
self.barcodes.append(
|
||||||
Barcode(current_page_number, barcode_value, self.settings),
|
Barcode(current_page_number, barcode_value, self.settings),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from contextlib import contextmanager
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
@@ -25,13 +24,6 @@ from documents.tests.utils import FileSystemAssertsMixin
|
|||||||
from documents.tests.utils import SampleDirMixin
|
from documents.tests.utils import SampleDirMixin
|
||||||
from paperless.models import ApplicationConfiguration
|
from paperless.models import ApplicationConfiguration
|
||||||
|
|
||||||
try:
|
|
||||||
import zxingcpp # noqa: F401
|
|
||||||
|
|
||||||
HAS_ZXING_LIB = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_ZXING_LIB = False
|
|
||||||
|
|
||||||
|
|
||||||
class GetReaderPluginMixin:
|
class GetReaderPluginMixin:
|
||||||
@contextmanager
|
@contextmanager
|
||||||
@@ -48,7 +40,6 @@ class GetReaderPluginMixin:
|
|||||||
reader.cleanup()
|
reader.cleanup()
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
|
||||||
class TestBarcode(
|
class TestBarcode(
|
||||||
DirectoriesMixin,
|
DirectoriesMixin,
|
||||||
FileSystemAssertsMixin,
|
FileSystemAssertsMixin,
|
||||||
@@ -606,7 +597,6 @@ class TestBarcode(
|
|||||||
self.assertDictEqual(separator_page_numbers, {0: False})
|
self.assertDictEqual(separator_page_numbers, {0: False})
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
|
||||||
class TestBarcodeNewConsume(
|
class TestBarcodeNewConsume(
|
||||||
DirectoriesMixin,
|
DirectoriesMixin,
|
||||||
FileSystemAssertsMixin,
|
FileSystemAssertsMixin,
|
||||||
@@ -784,14 +774,12 @@ class TestAsnBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
|
|||||||
|
|
||||||
self.assertEqual(document.archive_serial_number, 123)
|
self.assertEqual(document.archive_serial_number, 123)
|
||||||
|
|
||||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
|
||||||
def test_scan_file_for_qrcode_without_upscale(self) -> None:
|
def test_scan_file_for_qrcode_without_upscale(self) -> None:
|
||||||
"""
|
"""
|
||||||
GIVEN:
|
GIVEN:
|
||||||
- A printed and scanned PDF document with a rather small QR code
|
- A printed and scanned PDF document with a rather small QR code
|
||||||
WHEN:
|
WHEN:
|
||||||
- ASN barcode detection is run with default settings
|
- ASN barcode detection is run with default settings
|
||||||
- pyzbar is used for detection, as zxing would behave differently, and detect the QR code
|
|
||||||
THEN:
|
THEN:
|
||||||
- ASN is not detected
|
- ASN is not detected
|
||||||
"""
|
"""
|
||||||
@@ -802,7 +790,6 @@ class TestAsnBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
|
|||||||
reader.detect()
|
reader.detect()
|
||||||
self.assertEqual(len(reader.barcodes), 0)
|
self.assertEqual(len(reader.barcodes), 0)
|
||||||
|
|
||||||
@override_settings(CONSUMER_BARCODE_SCANNER="PYZBAR")
|
|
||||||
@override_settings(CONSUMER_BARCODE_DPI=600)
|
@override_settings(CONSUMER_BARCODE_DPI=600)
|
||||||
@override_settings(CONSUMER_BARCODE_UPSCALE=1.5)
|
@override_settings(CONSUMER_BARCODE_UPSCALE=1.5)
|
||||||
def test_scan_file_for_qrcode_with_upscale(self) -> None:
|
def test_scan_file_for_qrcode_with_upscale(self) -> None:
|
||||||
@@ -810,9 +797,7 @@ class TestAsnBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
|
|||||||
GIVEN:
|
GIVEN:
|
||||||
- A printed and scanned PDF document with a rather small QR code
|
- A printed and scanned PDF document with a rather small QR code
|
||||||
WHEN:
|
WHEN:
|
||||||
- ASN barcode detection is run with 600dpi and an upscale factor of 1.5 and pyzbar
|
- ASN barcode detection is run with 600dpi and an upscale factor of 1.5
|
||||||
- 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)
|
when you cannot switch to zxing (aarch64 build problems of zxing)
|
||||||
THEN:
|
THEN:
|
||||||
- ASN 123 is detected
|
- ASN 123 is detected
|
||||||
@@ -826,24 +811,6 @@ class TestAsnBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, Tes
|
|||||||
self.assertEqual(reader.asn, 123)
|
self.assertEqual(reader.asn, 123)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
|
||||||
not HAS_ZXING_LIB,
|
|
||||||
reason="No zxingcpp",
|
|
||||||
)
|
|
||||||
@override_settings(CONSUMER_BARCODE_SCANNER="ZXING")
|
|
||||||
class TestBarcodeZxing(TestBarcode):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(
|
|
||||||
not HAS_ZXING_LIB,
|
|
||||||
reason="No zxingcpp",
|
|
||||||
)
|
|
||||||
@override_settings(CONSUMER_BARCODE_SCANNER="ZXING")
|
|
||||||
class TestAsnBarcodesZxing(TestAsnBarcode):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TestTagBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, TestCase):
|
class TestTagBarcode(DirectoriesMixin, SampleDirMixin, GetReaderPluginMixin, TestCase):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def get_reader(self, filepath: Path) -> BarcodePlugin:
|
def get_reader(self, filepath: Path) -> BarcodePlugin:
|
||||||
|
|||||||
@@ -167,17 +167,6 @@ def settings_values_check(app_configs, **kwargs):
|
|||||||
)
|
)
|
||||||
return msgs
|
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():
|
def _email_certificate_validate():
|
||||||
msgs = []
|
msgs = []
|
||||||
# Existence checks
|
# Existence checks
|
||||||
@@ -195,7 +184,6 @@ def settings_values_check(app_configs, **kwargs):
|
|||||||
return (
|
return (
|
||||||
_ocrmypdf_settings_check()
|
_ocrmypdf_settings_check()
|
||||||
+ _timezone_validate()
|
+ _timezone_validate()
|
||||||
+ _barcode_scanner_validate()
|
|
||||||
+ _email_certificate_validate()
|
+ _email_certificate_validate()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1106,11 +1106,6 @@ CONSUMER_BARCODE_STRING: Final[str] = os.getenv(
|
|||||||
"PATCHT",
|
"PATCHT",
|
||||||
)
|
)
|
||||||
|
|
||||||
CONSUMER_BARCODE_SCANNER: Final[str] = os.getenv(
|
|
||||||
"PAPERLESS_CONSUMER_BARCODE_SCANNER",
|
|
||||||
"PYZBAR",
|
|
||||||
).upper()
|
|
||||||
|
|
||||||
CONSUMER_ENABLE_ASN_BARCODE: Final[bool] = __get_boolean(
|
CONSUMER_ENABLE_ASN_BARCODE: Final[bool] = __get_boolean(
|
||||||
"PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE",
|
"PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -206,11 +206,6 @@ class TestBarcodeSettingsChecks(DirectoriesMixin, TestCase):
|
|||||||
|
|
||||||
self.assertIn('Invalid Barcode Scanner ""', msg.msg)
|
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):
|
class TestEmailCertSettingsChecks(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||||
@override_settings(EMAIL_CERTIFICATE_FILE=Path("/tmp/not_actually_here.pem"))
|
@override_settings(EMAIL_CERTIFICATE_FILE=Path("/tmp/not_actually_here.pem"))
|
||||||
|
|||||||
10
uv.lock
generated
10
uv.lock
generated
@@ -3073,7 +3073,6 @@ dependencies = [
|
|||||||
{ name = "python-gnupg", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "python-gnupg", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "python-ipware", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "python-ipware", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "python-magic", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "python-magic", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "pyzbar", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
|
||||||
{ name = "rapidfuzz", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "rapidfuzz", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "redis", extra = ["hiredis"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "redis", extra = ["hiredis"], marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
{ name = "regex", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
{ name = "regex", marker = "sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||||
@@ -3226,7 +3225,6 @@ requires-dist = [
|
|||||||
{ name = "python-gnupg", specifier = "~=0.5.4" },
|
{ name = "python-gnupg", specifier = "~=0.5.4" },
|
||||||
{ name = "python-ipware", specifier = "~=3.0.0" },
|
{ name = "python-ipware", specifier = "~=3.0.0" },
|
||||||
{ name = "python-magic", specifier = "~=0.4.27" },
|
{ name = "python-magic", specifier = "~=0.4.27" },
|
||||||
{ name = "pyzbar", specifier = "~=0.1.9" },
|
|
||||||
{ name = "rapidfuzz", specifier = "~=3.14.0" },
|
{ name = "rapidfuzz", specifier = "~=3.14.0" },
|
||||||
{ name = "redis", extras = ["hiredis"], specifier = "~=5.2.1" },
|
{ name = "redis", extras = ["hiredis"], specifier = "~=5.2.1" },
|
||||||
{ name = "regex", specifier = ">=2025.9.18" },
|
{ name = "regex", specifier = ">=2025.9.18" },
|
||||||
@@ -4279,14 +4277,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
{ url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyzbar"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/6d/24/81ebe6a1c00760471a3028a23cbe0b94e5fa2926e5ba47adc895920887bc/pyzbar-0.1.9-py2.py3-none-any.whl", hash = "sha256:4559628b8192feb25766d954b36a3753baaf5c97c03135aec7e4a026036b475d", size = 32560, upload-time = "2022-03-15T14:53:40.637Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "qrcode"
|
name = "qrcode"
|
||||||
version = "8.2"
|
version = "8.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user