mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-02-26 01:09:34 -06:00
Fixing up the tests and redirecting the progress bar to stderr
This commit is contained in:
@@ -18,6 +18,7 @@ from typing import TypeVar
|
|||||||
from django import db
|
from django import db
|
||||||
from django.core.management import CommandError
|
from django.core.management import CommandError
|
||||||
from django_rich.management import RichCommand
|
from django_rich.management import RichCommand
|
||||||
|
from rich.console import Console
|
||||||
from rich.progress import BarColumn
|
from rich.progress import BarColumn
|
||||||
from rich.progress import MofNCompleteColumn
|
from rich.progress import MofNCompleteColumn
|
||||||
from rich.progress import Progress
|
from rich.progress import Progress
|
||||||
@@ -142,6 +143,12 @@ class PaperlessCommand(RichCommand):
|
|||||||
"""
|
"""
|
||||||
Create a configured Progress instance.
|
Create a configured Progress instance.
|
||||||
|
|
||||||
|
Progress output is directed to stderr to match the convention that
|
||||||
|
progress bars are transient UI feedback, not command output. This
|
||||||
|
mirrors tqdm's default behavior and prevents progress bar rendering
|
||||||
|
from interfering with stdout-based assertions in tests or piped
|
||||||
|
command output.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
description: Text to display alongside the progress bar.
|
description: Text to display alongside the progress bar.
|
||||||
|
|
||||||
@@ -155,7 +162,7 @@ class PaperlessCommand(RichCommand):
|
|||||||
MofNCompleteColumn(),
|
MofNCompleteColumn(),
|
||||||
TimeElapsedColumn(),
|
TimeElapsedColumn(),
|
||||||
TimeRemainingColumn(),
|
TimeRemainingColumn(),
|
||||||
console=self.console,
|
console=Console(stderr=True),
|
||||||
transient=False,
|
transient=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,10 @@ class Command(PaperlessCommand):
|
|||||||
RATIO_MAX: Final[float] = 100.0
|
RATIO_MAX: Final[float] = 100.0
|
||||||
|
|
||||||
if options["delete"]:
|
if options["delete"]:
|
||||||
self.console.print(
|
self.stdout.write(
|
||||||
"[yellow]The command is configured to delete documents. "
|
self.style.WARNING(
|
||||||
"Use with caution.[/yellow]",
|
"The command is configured to delete documents. Use with caution",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
opt_ratio = options["ratio"]
|
opt_ratio = options["ratio"]
|
||||||
@@ -90,17 +91,21 @@ class Command(PaperlessCommand):
|
|||||||
work_pkgs.append(_WorkPackage(first_doc, second_doc))
|
work_pkgs.append(_WorkPackage(first_doc, second_doc))
|
||||||
|
|
||||||
results: list[_WorkResult] = []
|
results: list[_WorkResult] = []
|
||||||
for result in self.process_parallel(
|
if self.process_count == 1:
|
||||||
|
for work in self.track(work_pkgs, description="Matching..."):
|
||||||
|
results.append(_process_and_match(work))
|
||||||
|
else: # pragma: no cover
|
||||||
|
for proc_result in self.process_parallel(
|
||||||
_process_and_match,
|
_process_and_match,
|
||||||
work_pkgs,
|
work_pkgs,
|
||||||
description="Matching...",
|
description="Matching...",
|
||||||
):
|
):
|
||||||
if result.error:
|
if proc_result.error:
|
||||||
self.console.print(
|
self.console.print(
|
||||||
f"[red]Failed: {result.error}[/red]",
|
f"[red]Failed: {proc_result.error}[/red]",
|
||||||
)
|
)
|
||||||
elif result.result is not None:
|
elif proc_result.result is not None:
|
||||||
results.append(result.result)
|
results.append(proc_result.result)
|
||||||
|
|
||||||
messages: list[str] = []
|
messages: list[str] = []
|
||||||
maybe_delete_ids: list[int] = []
|
maybe_delete_ids: list[int] = []
|
||||||
@@ -120,8 +125,9 @@ class Command(PaperlessCommand):
|
|||||||
self.stdout.writelines(messages)
|
self.stdout.writelines(messages)
|
||||||
|
|
||||||
if options["delete"]:
|
if options["delete"]:
|
||||||
self.console.print(
|
self.stdout.write(
|
||||||
f"[yellow]Deleting {len(maybe_delete_ids)} documents "
|
self.style.NOTICE(
|
||||||
f"based on ratio matches[/yellow]",
|
f"Deleting {len(maybe_delete_ids)} documents based on ratio matches",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
Document.objects.filter(pk__in=maybe_delete_ids).delete()
|
Document.objects.filter(pk__in=maybe_delete_ids).delete()
|
||||||
|
|||||||
@@ -5,13 +5,19 @@ from documents.management.commands.base import PaperlessCommand
|
|||||||
from documents.models import Document
|
from documents.models import Document
|
||||||
from documents.parsers import get_parser_class_for_mime_type
|
from documents.parsers import get_parser_class_for_mime_type
|
||||||
|
|
||||||
|
logger = logging.getLogger("paperless.management.thumbnails")
|
||||||
|
|
||||||
|
|
||||||
def _process_document(doc_id: int) -> None:
|
def _process_document(doc_id: int) -> None:
|
||||||
document: Document = Document.objects.get(id=doc_id)
|
document: Document = Document.objects.get(id=doc_id)
|
||||||
parser_class = get_parser_class_for_mime_type(document.mime_type)
|
parser_class = get_parser_class_for_mime_type(document.mime_type)
|
||||||
|
|
||||||
if parser_class is None:
|
if parser_class is None:
|
||||||
print(f"{document} No parser for mime type {document.mime_type}") # noqa: T201
|
logger.warning(
|
||||||
|
"%s: No parser for mime type %s",
|
||||||
|
document,
|
||||||
|
document.mime_type,
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
parser = parser_class(logging_group=None)
|
parser = parser_class(logging_group=None)
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ class TestFuzzyMatchCommand(TestCase):
|
|||||||
mime_type="application/pdf",
|
mime_type="application/pdf",
|
||||||
filename="final_test.pdf",
|
filename="final_test.pdf",
|
||||||
)
|
)
|
||||||
stdout, _ = self.call_command()
|
stdout, _ = self.call_command("--no-progress-bar")
|
||||||
lines = [x.strip() for x in stdout.splitlines() if x.strip()]
|
lines = [x.strip() for x in stdout.splitlines() if x.strip()]
|
||||||
self.assertEqual(len(lines), 3)
|
self.assertEqual(len(lines), 3)
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
|||||||
Reference in New Issue
Block a user