From b23232b6ab1b32969b018380922a6c550ba4f4aa Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Fri, 26 Feb 2021 07:23:26 -0500 Subject: [PATCH] Fixed #27854 -- Added system check for nonexistent directories in STATICFILES_DIRS setting. --- django/contrib/staticfiles/finders.py | 16 ++++++++++++---- docs/ref/checks.txt | 2 ++ tests/staticfiles_tests/test_checks.py | 25 +++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/django/contrib/staticfiles/finders.py b/django/contrib/staticfiles/finders.py index ee612cf3e6..35e62a3ae0 100644 --- a/django/contrib/staticfiles/finders.py +++ b/django/contrib/staticfiles/finders.py @@ -4,7 +4,7 @@ import os from django.apps import apps from django.conf import settings from django.contrib.staticfiles import utils -from django.core.checks import Error +from django.core.checks import Error, Warning from django.core.exceptions import ImproperlyConfigured from django.core.files.storage import ( FileSystemStorage, Storage, default_storage, @@ -91,6 +91,12 @@ class FileSystemFinder(BaseFinder): 'STATIC_ROOT setting.', id='staticfiles.E002', )) + if not os.path.isdir(root): + errors.append(Warning( + f"The directory '{root}' in the STATICFILES_DIRS setting " + f"does not exist.", + id='staticfiles.W004', + )) return errors def find(self, path, all=False): @@ -127,9 +133,11 @@ class FileSystemFinder(BaseFinder): List all files in all locations. """ for prefix, root in self.locations: - storage = self.storages[root] - for path in utils.get_files(storage, ignore_patterns): - yield path, storage + # Skip nonexistent directories. + if os.path.isdir(root): + storage = self.storages[root] + for path in utils.get_files(storage, ignore_patterns): + yield path, storage class AppDirectoriesFinder(BaseFinder): diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index dbba801e39..16d0fdb27f 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -869,3 +869,5 @@ configured: contain the :setting:`STATIC_ROOT` setting. * **staticfiles.E003**: The prefix ```` in the :setting:`STATICFILES_DIRS` setting must not end with a slash. +* **staticfiles.W004**: The directory ```` in the + :setting:`STATICFILES_DIRS` does not exist. diff --git a/tests/staticfiles_tests/test_checks.py b/tests/staticfiles_tests/test_checks.py index 44666d141d..4b2195b46f 100644 --- a/tests/staticfiles_tests/test_checks.py +++ b/tests/staticfiles_tests/test_checks.py @@ -3,8 +3,8 @@ from unittest import mock from django.conf import settings from django.contrib.staticfiles.checks import check_finders -from django.contrib.staticfiles.finders import BaseFinder -from django.core.checks import Error +from django.contrib.staticfiles.finders import BaseFinder, get_finder +from django.core.checks import Error, Warning from django.test import override_settings from .cases import CollectionTestCase @@ -91,3 +91,24 @@ class FindersCheckTests(CollectionTestCase): id='staticfiles.E003', ), ]) + + def test_nonexistent_directories(self): + with self.settings(STATICFILES_DIRS=[ + '/fake/path', + ('prefix', '/fake/prefixed/path'), + ]): + self.assertEqual(check_finders(None), [ + Warning( + "The directory '/fake/path' in the STATICFILES_DIRS " + "setting does not exist.", + id='staticfiles.W004', + ), + Warning( + "The directory '/fake/prefixed/path' in the " + "STATICFILES_DIRS setting does not exist.", + id='staticfiles.W004', + ), + ]) + # Nonexistent directories are skipped. + finder = get_finder('django.contrib.staticfiles.finders.FileSystemFinder') + self.assertEqual(list(finder.list(None)), [])