1
0
mirror of https://github.com/django/django.git synced 2025-08-21 01:09:13 +00:00

Fixed #36525 -- Silenced individual deleted file messages in collectstatic --clear's default verbosity.

This commit is contained in:
James Bligh 2025-08-05 15:49:10 +01:00 committed by Sarah Boyce
parent 31a43c571f
commit c1aa4a7a79
3 changed files with 54 additions and 4 deletions

View File

@ -26,6 +26,7 @@ class Command(BaseCommand):
self.unmodified_files = [] self.unmodified_files = []
self.post_processed_files = [] self.post_processed_files = []
self.skipped_files = [] self.skipped_files = []
self.deleted_files = []
self.storage = staticfiles_storage self.storage = staticfiles_storage
self.style = no_style() self.style = no_style()
@ -168,6 +169,7 @@ class Command(BaseCommand):
"unmodified": self.unmodified_files, "unmodified": self.unmodified_files,
"post_processed": self.post_processed_files, "post_processed": self.post_processed_files,
"skipped": self.skipped_files, "skipped": self.skipped_files,
"deleted": self.deleted_files,
} }
def handle(self, **options): def handle(self, **options):
@ -212,14 +214,21 @@ class Command(BaseCommand):
collected = self.collect() collected = self.collect()
if self.verbosity >= 1: if self.verbosity >= 1:
deleted_count = len(collected["deleted"])
modified_count = len(collected["modified"]) modified_count = len(collected["modified"])
unmodified_count = len(collected["unmodified"]) unmodified_count = len(collected["unmodified"])
post_processed_count = len(collected["post_processed"]) post_processed_count = len(collected["post_processed"])
skipped_count = len(collected["skipped"]) skipped_count = len(collected["skipped"])
return ( return (
"\n%(modified_count)s %(identifier)s %(action)s" "\n%(deleted)s%(modified_count)s %(identifier)s %(action)s"
"%(destination)s%(unmodified)s%(post_processed)s%(skipped)s." "%(destination)s%(unmodified)s%(post_processed)s%(skipped)s."
) % { ) % {
"deleted": (
"%s static file%s deleted, "
% (deleted_count, "" if deleted_count == 1 else "s")
if deleted_count > 0
else ""
),
"modified_count": modified_count, "modified_count": modified_count,
"identifier": "static file" + ("" if modified_count == 1 else "s"), "identifier": "static file" + ("" if modified_count == 1 else "s"),
"action": "symlinked" if self.symlink else "copied", "action": "symlinked" if self.symlink else "copied",
@ -264,9 +273,11 @@ class Command(BaseCommand):
for f in files: for f in files:
fpath = os.path.join(path, f) fpath = os.path.join(path, f)
if self.dry_run: if self.dry_run:
self.log("Pretending to delete '%s'" % fpath, level=1) self.log("Pretending to delete '%s'" % fpath, level=2)
self.deleted_files.append(fpath)
else: else:
self.log("Deleting '%s'" % fpath, level=1) self.log("Deleting '%s'" % fpath, level=2)
self.deleted_files.append(fpath)
try: try:
full_path = self.storage.path(fpath) full_path = self.storage.path(fpath)
except NotImplementedError: except NotImplementedError:

View File

@ -474,6 +474,10 @@ Miscellaneous
files due to conflicts when ``--verbosity`` is 1. To see warnings for each files due to conflicts when ``--verbosity`` is 1. To see warnings for each
conflicting destination path, set the ``--verbosity`` flag to 2 or higher. conflicting destination path, set the ``--verbosity`` flag to 2 or higher.
* The :option:`collectstatic --clear` command now reports only a summary of
deleted files when ``--verbosity`` is 1. To see the details for each file
deleted, set the ``--verbosity`` flag to 2 or higher.
.. _deprecated-features-6.0: .. _deprecated-features-6.0:
Features deprecated in 6.0 Features deprecated in 6.0

View File

@ -291,11 +291,13 @@ class TestCollectionClear(CollectionTestCase):
Test the ``--clear`` option of the ``collectstatic`` management command. Test the ``--clear`` option of the ``collectstatic`` management command.
""" """
run_collectstatic_in_setUp = False
def run_collectstatic(self, **kwargs): def run_collectstatic(self, **kwargs):
clear_filepath = os.path.join(settings.STATIC_ROOT, "cleared.txt") clear_filepath = os.path.join(settings.STATIC_ROOT, "cleared.txt")
with open(clear_filepath, "w") as f: with open(clear_filepath, "w") as f:
f.write("should be cleared") f.write("should be cleared")
super().run_collectstatic(clear=True) super().run_collectstatic(clear=True, **kwargs)
def test_cleared_not_found(self): def test_cleared_not_found(self):
self.assertFileNotFound("cleared.txt") self.assertFileNotFound("cleared.txt")
@ -316,6 +318,39 @@ class TestCollectionClear(CollectionTestCase):
self.run_collectstatic() self.run_collectstatic()
self.assertFileNotFound("cleared.txt") self.assertFileNotFound("cleared.txt")
def test_verbosity_0(self):
for kwargs in [{}, {"dry_run": True}]:
with self.subTest(kwargs=kwargs):
stdout = StringIO()
self.run_collectstatic(verbosity=0, stdout=stdout, **kwargs)
self.assertEqual(stdout.getvalue(), "")
def test_verbosity_1(self):
for deletion_message, kwargs in [
("Deleting", {}),
("Pretending to delete", {"dry_run": True}),
]:
with self.subTest(kwargs=kwargs):
stdout = StringIO()
self.run_collectstatic(verbosity=1, stdout=stdout, **kwargs)
output = stdout.getvalue()
self.assertIn("static file", output)
self.assertIn("deleted", output)
self.assertNotIn(deletion_message, output)
def test_verbosity_2(self):
for deletion_message, kwargs in [
("Deleting", {}),
("Pretending to delete", {"dry_run": True}),
]:
with self.subTest(kwargs=kwargs):
stdout = StringIO()
self.run_collectstatic(verbosity=2, stdout=stdout, **kwargs)
output = stdout.getvalue()
self.assertIn("static file", output)
self.assertIn("deleted", output)
self.assertIn(deletion_message, output)
class TestInteractiveMessages(CollectionTestCase): class TestInteractiveMessages(CollectionTestCase):
overwrite_warning_msg = "This will overwrite existing files!" overwrite_warning_msg = "This will overwrite existing files!"