mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-09-11 12:18:02 +00:00
* Chore(deps): Bump the utilities-minor group across 1 directory with 11 updates Bumps the utilities-minor group with 11 updates in the / directory: | Package | From | To | | --- | --- | --- | | [django-guardian](https://github.com/django-guardian/django-guardian) | `3.3.3` | `3.4.0` | | [django-treenode](https://github.com/fabiocaccamo/django-treenode) | `0.24.0` | `0.25.0` | | [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) | `2026.7.1` | `2026.8.1` | | [imap-tools](https://github.com/ikvk/imap_tools) | `1.14.0` | `1.15.0` | | [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) | `17.10.0` | `17.11.0` | | [prek](https://github.com/j178/prek) | `0.4.11` | `0.5.0` | | [faker](https://github.com/joke2k/faker) | `40.36.0` | `40.37.0` | | [pytest-django](https://github.com/pytest-dev/pytest-django) | `4.12.0` | `4.14.0` | | [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) | `16.4` | `16.6` | | [time-machine](https://github.com/adamchainz/time-machine) | `3.2.0` | `3.5.0` | | [types-pygments](https://github.com/python/typeshed) | `2.20.0.20260408` | `2.21.0.20260819` | Updates `django-guardian` from 3.3.3 to 3.4.0 - [Release notes](https://github.com/django-guardian/django-guardian/releases) - [Commits](https://github.com/django-guardian/django-guardian/compare/3.3.3...3.4.0) Updates `django-treenode` from 0.24.0 to 0.25.0 - [Release notes](https://github.com/fabiocaccamo/django-treenode/releases) - [Changelog](https://github.com/fabiocaccamo/django-treenode/blob/main/CHANGELOG.md) - [Commits](https://github.com/fabiocaccamo/django-treenode/compare/0.24.0...0.25.0) Updates `drf-spectacular-sidecar` from 2026.7.1 to 2026.8.1 - [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2026.7.1...2026.8.1) Updates `imap-tools` from 1.14.0 to 1.15.0 - [Release notes](https://github.com/ikvk/imap_tools/releases) - [Changelog](https://github.com/ikvk/imap_tools/blob/master/docs/release_notes.rst) - [Commits](https://github.com/ikvk/imap_tools/compare/v1.14.0...v1.15.0) Updates `ocrmypdf` from 17.10.0 to 17.11.0 - [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases) - [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v17.10.0...v17.11.0) Updates `prek` from 0.4.11 to 0.5.0 - [Release notes](https://github.com/j178/prek/releases) - [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md) - [Commits](https://github.com/j178/prek/compare/v0.4.11...v0.5.0) Updates `faker` from 40.36.0 to 40.37.0 - [Release notes](https://github.com/joke2k/faker/releases) - [Changelog](https://github.com/joke2k/faker/blob/master/CHANGELOG.md) - [Commits](https://github.com/joke2k/faker/compare/v40.36.0...v40.37.0) Updates `pytest-django` from 4.12.0 to 4.14.0 - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.12.0...v4.14.0) Updates `pytest-rerunfailures` from 16.4 to 16.6 - [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/16.4...16.6) Updates `time-machine` from 3.2.0 to 3.5.0 - [Changelog](https://github.com/adamchainz/time-machine/blob/main/docs/changelog.rst) - [Commits](https://github.com/adamchainz/time-machine/compare/3.2.0...3.5.0) Updates `types-pygments` from 2.20.0.20260408 to 2.21.0.20260819 - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: django-guardian dependency-version: 3.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: django-treenode dependency-version: 0.25.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: drf-spectacular-sidecar dependency-version: 2026.8.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: faker dependency-version: 40.37.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: imap-tools dependency-version: 1.15.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: ocrmypdf dependency-version: 17.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: prek dependency-version: 0.5.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: pytest-django dependency-version: 4.14.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: pytest-rerunfailures dependency-version: '16.6' dependency-type: direct:development update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: time-machine dependency-version: 3.5.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: utilities-minor - dependency-name: types-pygments dependency-version: 2.21.0.20260819 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: utilities-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Handles pytest-django * Formatting --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
794 lines
20 KiB
Python
794 lines
20 KiB
Python
"""
|
|
Parser fixtures that are used across multiple test modules in this package
|
|
are defined here. Format-specific sample-file fixtures are grouped by parser
|
|
so it is easy to see which files belong to which test module.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from contextlib import contextmanager
|
|
from typing import TYPE_CHECKING
|
|
|
|
import pytest
|
|
from django.test import override_settings
|
|
|
|
from paperless.parsers.mail import MailDocumentParser
|
|
from paperless.parsers.remote import RemoteDocumentParser
|
|
from paperless.parsers.tesseract import RasterisedDocumentParser
|
|
from paperless.parsers.text import TextDocumentParser
|
|
from paperless.parsers.tika import TikaDocumentParser
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable
|
|
from collections.abc import Generator
|
|
from pathlib import Path
|
|
from unittest.mock import MagicMock
|
|
|
|
from pytest_django.fixtures import Settings
|
|
from pytest_mock import MockerFixture
|
|
|
|
#: Type for the ``make_tesseract_parser`` fixture factory.
|
|
MakeTesseractParser = Callable[..., Generator[RasterisedDocumentParser, None, None]]
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Text parser sample files
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def text_samples_dir(samples_dir: Path) -> Path:
|
|
"""Absolute path to the text parser sample files directory.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
``<samples_dir>/text/``
|
|
"""
|
|
return samples_dir / "text"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def sample_txt_file(text_samples_dir: Path) -> Path:
|
|
"""Path to a valid UTF-8 plain-text sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``text/test.txt``.
|
|
"""
|
|
return text_samples_dir / "test.txt"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def malformed_txt_file(text_samples_dir: Path) -> Path:
|
|
"""Path to a text file containing invalid UTF-8 bytes.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``text/decode_error.txt``.
|
|
"""
|
|
return text_samples_dir / "decode_error.txt"
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Text parser instance
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture()
|
|
def text_parser() -> Generator[TextDocumentParser, None, None]:
|
|
"""Yield a TextDocumentParser and clean up its temporary directory afterwards.
|
|
|
|
Yields
|
|
------
|
|
TextDocumentParser
|
|
A ready-to-use parser instance.
|
|
"""
|
|
with TextDocumentParser() as parser:
|
|
yield parser
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Remote parser instance
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture()
|
|
def remote_parser() -> Generator[RemoteDocumentParser, None, None]:
|
|
"""Yield a RemoteDocumentParser and clean up its temporary directory afterwards.
|
|
|
|
Yields
|
|
------
|
|
RemoteDocumentParser
|
|
A ready-to-use parser instance.
|
|
"""
|
|
with RemoteDocumentParser() as parser:
|
|
yield parser
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Remote parser settings helpers
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture()
|
|
def empty_remote_ocr_app_config(mocker: MockerFixture) -> MagicMock:
|
|
# empty app config without accessing db
|
|
app_config = mocker.MagicMock(
|
|
remote_ocr_engine=None,
|
|
remote_ocr_api_key=None,
|
|
remote_ocr_endpoint=None,
|
|
remote_ocr_mode=None,
|
|
)
|
|
mocker.patch(
|
|
"paperless.config.BaseConfig._get_config_instance",
|
|
return_value=app_config,
|
|
)
|
|
return app_config
|
|
|
|
|
|
@pytest.fixture()
|
|
def azure_settings(
|
|
settings: Settings,
|
|
empty_remote_ocr_app_config: MagicMock,
|
|
) -> Settings:
|
|
"""Configure Django settings for a valid Azure AI OCR engine.
|
|
|
|
Sets ``REMOTE_OCR_ENGINE``, ``REMOTE_OCR_API_KEY``, and
|
|
``REMOTE_OCR_ENDPOINT`` to test values. Settings are restored
|
|
automatically after the test by pytest-django.
|
|
|
|
Returns
|
|
-------
|
|
Settings
|
|
The modified settings object (for chaining further overrides).
|
|
"""
|
|
settings.REMOTE_OCR_ENGINE = "azureai"
|
|
settings.REMOTE_OCR_API_KEY = "test-api-key"
|
|
settings.REMOTE_OCR_ENDPOINT = "https://test.cognitiveservices.azure.com"
|
|
return settings
|
|
|
|
|
|
@pytest.fixture()
|
|
def no_engine_settings(
|
|
settings: Settings,
|
|
empty_remote_ocr_app_config: MagicMock,
|
|
) -> Settings:
|
|
"""Configure Django settings with no remote engine configured.
|
|
|
|
Returns
|
|
-------
|
|
Settings
|
|
The modified settings object.
|
|
"""
|
|
settings.REMOTE_OCR_ENGINE = None
|
|
settings.REMOTE_OCR_API_KEY = None
|
|
settings.REMOTE_OCR_ENDPOINT = None
|
|
return settings
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Tika parser sample files
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def tika_samples_dir(samples_dir: Path) -> Path:
|
|
"""Absolute path to the Tika parser sample files directory.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
``<samples_dir>/tika/``
|
|
"""
|
|
return samples_dir / "tika"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def sample_odt_file(tika_samples_dir: Path) -> Path:
|
|
"""Path to a sample ODT file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tika/sample.odt``.
|
|
"""
|
|
return tika_samples_dir / "sample.odt"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def sample_docx_file(tika_samples_dir: Path) -> Path:
|
|
"""Path to a sample DOCX file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tika/sample.docx``.
|
|
"""
|
|
return tika_samples_dir / "sample.docx"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def sample_doc_file(tika_samples_dir: Path) -> Path:
|
|
"""Path to a sample DOC file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tika/sample.doc``.
|
|
"""
|
|
return tika_samples_dir / "sample.doc"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def sample_broken_odt(tika_samples_dir: Path) -> Path:
|
|
"""Path to a broken ODT file that triggers the multi-part fallback.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tika/multi-part-broken.odt``.
|
|
"""
|
|
return tika_samples_dir / "multi-part-broken.odt"
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Tika parser instance
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture()
|
|
def tika_parser() -> Generator[TikaDocumentParser, None, None]:
|
|
"""Yield a TikaDocumentParser and clean up its temporary directory afterwards.
|
|
|
|
Yields
|
|
------
|
|
TikaDocumentParser
|
|
A ready-to-use parser instance.
|
|
"""
|
|
with TikaDocumentParser() as parser:
|
|
yield parser
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Mail parser sample files
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def mail_samples_dir(samples_dir: Path) -> Path:
|
|
"""Absolute path to the mail parser sample files directory.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
``<samples_dir>/mail/``
|
|
"""
|
|
return samples_dir / "mail"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def broken_email_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to a broken/malformed EML sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/broken.eml``.
|
|
"""
|
|
return mail_samples_dir / "broken.eml"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_txt_email_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to a plain-text email sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/simple_text.eml``.
|
|
"""
|
|
return mail_samples_dir / "simple_text.eml"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_txt_email_pdf_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to the expected PDF rendition of the plain-text email.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/simple_text.eml.pdf``.
|
|
"""
|
|
return mail_samples_dir / "simple_text.eml.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_txt_email_thumbnail_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to the expected thumbnail for the plain-text email.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/simple_text.eml.pdf.webp``.
|
|
"""
|
|
return mail_samples_dir / "simple_text.eml.pdf.webp"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def html_email_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to an HTML email sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/html.eml``.
|
|
"""
|
|
return mail_samples_dir / "html.eml"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def html_email_pdf_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to the expected PDF rendition of the HTML email.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/html.eml.pdf``.
|
|
"""
|
|
return mail_samples_dir / "html.eml.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def html_email_thumbnail_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to the expected thumbnail for the HTML email.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/html.eml.pdf.webp``.
|
|
"""
|
|
return mail_samples_dir / "html.eml.pdf.webp"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def html_email_html_file(mail_samples_dir: Path) -> Path:
|
|
"""Path to the HTML body of the HTML email sample.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/html.eml.html``.
|
|
"""
|
|
return mail_samples_dir / "html.eml.html"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def merged_pdf_first(mail_samples_dir: Path) -> Path:
|
|
"""Path to the first PDF used in PDF-merge tests.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/first.pdf``.
|
|
"""
|
|
return mail_samples_dir / "first.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def merged_pdf_second(mail_samples_dir: Path) -> Path:
|
|
"""Path to the second PDF used in PDF-merge tests.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``mail/second.pdf``.
|
|
"""
|
|
return mail_samples_dir / "second.pdf"
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Mail parser instance
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture()
|
|
def mail_parser() -> Generator[MailDocumentParser, None, None]:
|
|
"""Yield a MailDocumentParser and clean up its temporary directory afterwards.
|
|
|
|
Yields
|
|
------
|
|
MailDocumentParser
|
|
A ready-to-use parser instance.
|
|
"""
|
|
with MailDocumentParser() as parser:
|
|
yield parser
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def nginx_base_url() -> Generator[str, None, None]:
|
|
"""
|
|
The base URL for the nginx HTTP server we expect to be alive
|
|
"""
|
|
yield "http://localhost:8080"
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Tesseract parser sample files
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def tesseract_samples_dir(samples_dir: Path) -> Path:
|
|
"""Absolute path to the tesseract parser sample files directory.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
``<samples_dir>/tesseract/``
|
|
"""
|
|
return samples_dir / "tesseract"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def document_webp_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a WebP document sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/document.webp``.
|
|
"""
|
|
return tesseract_samples_dir / "document.webp"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def encrypted_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to an encrypted PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/encrypted.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "encrypted.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def multi_page_digital_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a multi-page digital PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/multi-page-digital.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "multi-page-digital.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def multi_page_images_alpha_rgb_tiff_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a multi-page TIFF with alpha channel in RGB.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/multi-page-images-alpha-rgb.tiff``.
|
|
"""
|
|
return tesseract_samples_dir / "multi-page-images-alpha-rgb.tiff"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def multi_page_images_alpha_tiff_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a multi-page TIFF with alpha channel.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/multi-page-images-alpha.tiff``.
|
|
"""
|
|
return tesseract_samples_dir / "multi-page-images-alpha.tiff"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def multi_page_images_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a multi-page PDF with images.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/multi-page-images.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "multi-page-images.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def multi_page_images_tiff_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a multi-page TIFF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/multi-page-images.tiff``.
|
|
"""
|
|
return tesseract_samples_dir / "multi-page-images.tiff"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def multi_page_mixed_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a multi-page mixed PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/multi-page-mixed.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "multi-page-mixed.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def no_text_alpha_png_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a PNG with alpha channel and no text.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/no-text-alpha.png``.
|
|
"""
|
|
return tesseract_samples_dir / "no-text-alpha.png"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def rotated_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a rotated PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/rotated.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "rotated.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def rtl_test_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to an RTL test PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/rtl-test.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "rtl-test.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def signed_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a signed PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/signed.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "signed.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_alpha_png_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple PNG with alpha channel.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple-alpha.png``.
|
|
"""
|
|
return tesseract_samples_dir / "simple-alpha.png"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_digital_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple digital PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple-digital.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "simple-digital.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_no_dpi_png_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple PNG without DPI information.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple-no-dpi.png``.
|
|
"""
|
|
return tesseract_samples_dir / "simple-no-dpi.png"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_bmp_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple BMP sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple.bmp``.
|
|
"""
|
|
return tesseract_samples_dir / "simple.bmp"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_gif_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple GIF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple.gif``.
|
|
"""
|
|
return tesseract_samples_dir / "simple.gif"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_heic_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple HEIC sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple.heic``.
|
|
"""
|
|
return tesseract_samples_dir / "simple.heic"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_jpg_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple JPG sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple.jpg``.
|
|
"""
|
|
return tesseract_samples_dir / "simple.jpg"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_png_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple PNG sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple.png``.
|
|
"""
|
|
return tesseract_samples_dir / "simple.png"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def simple_tif_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a simple TIF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/simple.tif``.
|
|
"""
|
|
return tesseract_samples_dir / "simple.tif"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def single_page_mixed_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a single-page mixed PDF sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/single-page-mixed.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "single-page-mixed.pdf"
|
|
|
|
|
|
@pytest.fixture(scope="session")
|
|
def with_form_pdf_file(tesseract_samples_dir: Path) -> Path:
|
|
"""Path to a PDF with form sample file.
|
|
|
|
Returns
|
|
-------
|
|
Path
|
|
Absolute path to ``tesseract/with-form.pdf``.
|
|
"""
|
|
return tesseract_samples_dir / "with-form.pdf"
|
|
|
|
|
|
# ------------------------------------------------------------------
|
|
# Tesseract parser instance and settings helpers
|
|
# ------------------------------------------------------------------
|
|
|
|
|
|
@pytest.fixture()
|
|
def null_app_config(mocker: MockerFixture) -> MagicMock:
|
|
"""Return a MagicMock with all OcrConfig fields set to None.
|
|
|
|
This allows the parser to fall back to Django settings instead of
|
|
hitting the database.
|
|
|
|
Returns
|
|
-------
|
|
MagicMock
|
|
Mock config with all fields as None
|
|
"""
|
|
return mocker.MagicMock(
|
|
output_type=None,
|
|
pages=None,
|
|
language=None,
|
|
mode=None,
|
|
archive_file_generation=None,
|
|
image_dpi=None,
|
|
unpaper_clean=None,
|
|
deskew=None,
|
|
rotate_pages=None,
|
|
rotate_pages_threshold=None,
|
|
max_image_pixels=None,
|
|
color_conversion_strategy=None,
|
|
user_args=None,
|
|
)
|
|
|
|
|
|
@pytest.fixture()
|
|
def tesseract_parser(
|
|
mocker: MockerFixture,
|
|
null_app_config: MagicMock,
|
|
) -> Generator[RasterisedDocumentParser, None, None]:
|
|
"""Yield a RasterisedDocumentParser and clean up its temporary directory afterwards.
|
|
|
|
Patches the config system to avoid database access.
|
|
|
|
Yields
|
|
------
|
|
RasterisedDocumentParser
|
|
A ready-to-use parser instance.
|
|
"""
|
|
mocker.patch(
|
|
"paperless.config.BaseConfig._get_config_instance",
|
|
return_value=null_app_config,
|
|
)
|
|
with RasterisedDocumentParser() as parser:
|
|
yield parser
|
|
|
|
|
|
@pytest.fixture()
|
|
def make_tesseract_parser(
|
|
mocker: MockerFixture,
|
|
null_app_config: MagicMock,
|
|
) -> MakeTesseractParser:
|
|
"""Return a factory for creating RasterisedDocumentParser with Django settings overrides.
|
|
|
|
This fixture is useful for tests that need to create parsers with different
|
|
settings configurations.
|
|
|
|
Returns
|
|
-------
|
|
Callable[..., contextmanager[RasterisedDocumentParser]]
|
|
A context manager factory that accepts Django settings overrides
|
|
"""
|
|
mocker.patch(
|
|
"paperless.config.BaseConfig._get_config_instance",
|
|
return_value=null_app_config,
|
|
)
|
|
|
|
@contextmanager
|
|
def _make_parser(**django_settings_overrides):
|
|
with override_settings(**django_settings_overrides):
|
|
with RasterisedDocumentParser() as parser:
|
|
yield parser
|
|
|
|
return _make_parser
|