Files
paperless-ngx/src/paperless_testing/dirs.py
T
Trenton H b457610ffb Chore: Fix bugs in the test suite (#14244)
* Fix: redirect SHARE_LINK_BUNDLE_DIR to the test temp layout instead of the real media directory

* Fix: include f_to in test_filters subTest labels so each of the 8 cases reports distinctly

* Fix: run the post_consume error-log assertion after the raising call and match the actual paperless_mail logger name

* Fix: rename the blank-password workflow test to match its behavior and add a real wrong-password-fails test

* Fix: use the created social account's actual pk and remove an accidental tuple wrapping the mock provider

* Fix: assert against the created documents' actual pks instead of hardcoded 1 and 2

* Fix: assert test_compression actually produces a valid LZMA-compressed zip

* Fix: clear os.environ when patching PAPERLESS_ADMIN_* vars so a host-set value can't leak into the no-user test

* Fix: restore MIDDLEWARE, AUTHENTICATION_BACKENDS and REST_FRAMEWORK auth classes after each remote-user settings test instead of leaking the mutation into later tests

* Fix: use a guaranteed-nonexistent temp path instead of hardcoded /tmp/foo/bar in test_export_target_not_exists
2026-09-23 19:11:58 +00:00

151 lines
4.2 KiB
Python

"""The Paperless-ngx temp directory layout, stated once.
``build_paperless_dirs`` owns where things go and creates them.
``dirs_settings`` owns the mapping onto Django setting names and is pure.
Everything else in the test suite is a caller of these two.
"""
from __future__ import annotations
from contextlib import contextmanager
from dataclasses import dataclass
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import TYPE_CHECKING
from typing import TypedDict
import pytest
from django.test import override_settings
if TYPE_CHECKING:
from collections.abc import Iterator
@dataclass(frozen=True, slots=True)
class PaperlessDirs:
"""Standard Paperless-ngx directory layout for tests."""
data_dir: Path
scratch_dir: Path
media_dir: Path
consumption_dir: Path
static_dir: Path
index_dir: Path
originals_dir: Path
thumbnail_dir: Path
archive_dir: Path
logging_dir: Path
model_file: Path
media_lock: Path
share_link_bundle_dir: Path
class DirSettings(TypedDict):
"""The Django settings the layout above maps onto."""
DATA_DIR: Path
SCRATCH_DIR: Path
MEDIA_ROOT: Path
ORIGINALS_DIR: Path
THUMBNAIL_DIR: Path
ARCHIVE_DIR: Path
CONSUMPTION_DIR: Path
LOGGING_DIR: Path
INDEX_DIR: Path
STATIC_ROOT: Path
MODEL_FILE: Path
MEDIA_LOCK: Path
SHARE_LINK_BUNDLE_DIR: Path
def build_paperless_dirs(root: Path) -> PaperlessDirs:
"""Compute the layout under root and create the directories."""
data_dir = root / "data"
media_dir = root / "media"
documents_dir = media_dir / "documents"
dirs = PaperlessDirs(
data_dir=data_dir,
scratch_dir=root / "scratch",
media_dir=media_dir,
consumption_dir=root / "consume",
static_dir=root / "static",
index_dir=data_dir / "index",
originals_dir=documents_dir / "originals",
thumbnail_dir=documents_dir / "thumbnails",
archive_dir=documents_dir / "archive",
logging_dir=data_dir / "log",
model_file=data_dir / "classification_model.pickle",
media_lock=media_dir / "media.lock",
share_link_bundle_dir=documents_dir / "share_link_bundles",
)
for directory in (
dirs.data_dir,
dirs.scratch_dir,
dirs.media_dir,
dirs.consumption_dir,
dirs.static_dir,
dirs.index_dir,
dirs.originals_dir,
dirs.thumbnail_dir,
dirs.archive_dir,
dirs.logging_dir,
):
directory.mkdir(parents=True, exist_ok=True)
return dirs
def dirs_settings(dirs: PaperlessDirs) -> DirSettings:
"""Map the layout onto Django setting names."""
return DirSettings(
DATA_DIR=dirs.data_dir,
SCRATCH_DIR=dirs.scratch_dir,
MEDIA_ROOT=dirs.media_dir,
ORIGINALS_DIR=dirs.originals_dir,
THUMBNAIL_DIR=dirs.thumbnail_dir,
ARCHIVE_DIR=dirs.archive_dir,
CONSUMPTION_DIR=dirs.consumption_dir,
LOGGING_DIR=dirs.logging_dir,
INDEX_DIR=dirs.index_dir,
STATIC_ROOT=dirs.static_dir,
MODEL_FILE=dirs.model_file,
MEDIA_LOCK=dirs.media_lock,
SHARE_LINK_BUNDLE_DIR=dirs.share_link_bundle_dir,
)
@contextmanager
def paperless_environment() -> Iterator[PaperlessDirs]:
"""A second, isolated environment for the duration of the block.
Only for tests needing a fresh environment part way through a test body,
which a fixture cannot provide. Everything else uses the paperless_dirs
fixture.
"""
from documents.search import reset_backend
with TemporaryDirectory(ignore_cleanup_errors=True) as tmp:
dirs = build_paperless_dirs(Path(tmp))
with override_settings(**dirs_settings(dirs)):
reset_backend()
try:
yield dirs
finally:
reset_backend()
class DirectoriesMixin:
"""Bridges the directory fixture to unittest TestCase subclasses and to
plain pytest test classes that want `self.dirs`.
Delete once no class depends on it.
"""
dirs: PaperlessDirs
@pytest.fixture(autouse=True)
def _paperless_dirs(self, paperless_dirs: PaperlessDirs) -> None:
self.dirs = paperless_dirs