mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-07-17 01:14:55 +00:00
feat(fuzzy-match): add --yes flag and interactive confirmation before deletion
Without --yes, --delete now prompts "Delete N document(s)? [y/N]" and aborts with "Deletion cancelled." if the user does not confirm. --yes skips the prompt for non-interactive/scripted use. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
a7724aa0d2
commit
5869c7b301
@@ -66,6 +66,12 @@ class Command(PaperlessCommand):
|
||||
action="store_true",
|
||||
help="If set, one document of matches above the ratio WILL BE DELETED",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--yes",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help="Skip the confirmation prompt when used with --delete",
|
||||
)
|
||||
|
||||
def _render_results(
|
||||
self,
|
||||
@@ -199,8 +205,21 @@ class Command(PaperlessCommand):
|
||||
)
|
||||
|
||||
if options["delete"] and maybe_delete_ids:
|
||||
self.console.print(
|
||||
f"[red]Deleting {len(maybe_delete_ids)} document(s)...[/red]",
|
||||
)
|
||||
Document.objects.filter(pk__in=maybe_delete_ids).delete()
|
||||
self.console.print("[green]Done.[/green]")
|
||||
confirmed = options["yes"]
|
||||
if not confirmed:
|
||||
self.console.print(
|
||||
f"\nDelete [bold]{len(maybe_delete_ids)}[/bold] document(s)? "
|
||||
"[bold]\\[y/N][/bold] ",
|
||||
end="",
|
||||
)
|
||||
answer = input().strip().lower()
|
||||
confirmed = answer in {"y", "yes"}
|
||||
|
||||
if confirmed:
|
||||
self.console.print(
|
||||
f"[red]Deleting {len(maybe_delete_ids)} document(s)...[/red]",
|
||||
)
|
||||
Document.objects.filter(pk__in=maybe_delete_ids).delete()
|
||||
self.console.print("[green]Done.[/green]")
|
||||
else:
|
||||
self.console.print("[yellow]Deletion cancelled.[/yellow]")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from io import StringIO
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from django.core.management import CommandError
|
||||
@@ -182,6 +183,7 @@ class TestFuzzyMatchCommand(TestCase):
|
||||
|
||||
stdout, _ = self.call_command(
|
||||
"--delete",
|
||||
"--yes",
|
||||
"--no-progress-bar",
|
||||
"--processes",
|
||||
"1",
|
||||
@@ -195,6 +197,51 @@ class TestFuzzyMatchCommand(TestCase):
|
||||
self.assertIsNotNone(Document.objects.get(pk=1))
|
||||
self.assertIsNotNone(Document.objects.get(pk=2))
|
||||
|
||||
def test_document_deletion_cancelled(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- 3 documents exist
|
||||
- Document 1 to document 3 has a similarity over 85.0
|
||||
WHEN:
|
||||
- Command is called with --delete but user answers "n" at the prompt
|
||||
THEN:
|
||||
- No documents are deleted
|
||||
"""
|
||||
Document.objects.create(
|
||||
checksum="BEEFCAFE",
|
||||
title="A",
|
||||
content="first document scanned by bob",
|
||||
mime_type="application/pdf",
|
||||
filename="test.pdf",
|
||||
)
|
||||
Document.objects.create(
|
||||
checksum="DEADBEAF",
|
||||
title="A",
|
||||
content="second document scanned by alice",
|
||||
mime_type="application/pdf",
|
||||
filename="other_test.pdf",
|
||||
)
|
||||
Document.objects.create(
|
||||
checksum="CATTLE",
|
||||
title="A",
|
||||
content="first document scanned by pete",
|
||||
mime_type="application/pdf",
|
||||
filename="final_test.pdf",
|
||||
)
|
||||
|
||||
self.assertEqual(Document.objects.count(), 3)
|
||||
|
||||
with patch("builtins.input", return_value="n"):
|
||||
stdout, _ = self.call_command(
|
||||
"--delete",
|
||||
"--no-progress-bar",
|
||||
"--processes",
|
||||
"1",
|
||||
)
|
||||
|
||||
self.assertIn("Deletion cancelled", stdout)
|
||||
self.assertEqual(Document.objects.count(), 3)
|
||||
|
||||
def test_empty_content(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
|
||||
Reference in New Issue
Block a user