summaryrefslogtreecommitdiff
path: root/tests/user_commands
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2024-11-29 07:04:48 -0500
committerGitHub <noreply@github.com>2024-11-29 09:04:48 -0300
commit58cc91275a68bb42780cf0e663dad9ecf49039de (patch)
treee60317923d4f2faf61238f46528ed180a5134651 /tests/user_commands
parent978aae4334fa71ba78a3e94408f0f3aebde8d07c (diff)
Fixed #35308 -- Handled OSError when launching code formatters.
Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
Diffstat (limited to 'tests/user_commands')
-rw-r--r--tests/user_commands/test_files/black1
-rw-r--r--tests/user_commands/tests.py25
-rw-r--r--tests/user_commands/utils.py23
3 files changed, 49 insertions, 0 deletions
diff --git a/tests/user_commands/test_files/black b/tests/user_commands/test_files/black
new file mode 100644
index 0000000000..d95ebc8c1e
--- /dev/null
+++ b/tests/user_commands/test_files/black
@@ -0,0 +1 @@
+# This file is not executable, to simulate a broken `black` install.
diff --git a/tests/user_commands/tests.py b/tests/user_commands/tests.py
index 2a1e904f3b..2add272c10 100644
--- a/tests/user_commands/tests.py
+++ b/tests/user_commands/tests.py
@@ -1,6 +1,8 @@
import os
+import sys
from argparse import ArgumentDefaultsHelpFormatter
from io import StringIO
+from pathlib import Path
from unittest import mock
from admin_scripts.tests import AdminScriptTestCase
@@ -15,6 +17,7 @@ from django.core.management.utils import (
is_ignored_path,
normalize_path_patterns,
popen_wrapper,
+ run_formatters,
)
from django.db import connection
from django.test import SimpleTestCase, override_settings
@@ -22,6 +25,7 @@ from django.test.utils import captured_stderr, extend_sys_path
from django.utils import translation
from .management.commands import dance
+from .utils import AssertFormatterFailureCaughtContext
# A minimal set of apps to avoid system checks running on all apps.
@@ -535,3 +539,24 @@ class UtilsTests(SimpleTestCase):
def test_normalize_path_patterns_truncates_wildcard_base(self):
expected = [os.path.normcase(p) for p in ["foo/bar", "bar/*/"]]
self.assertEqual(normalize_path_patterns(["foo/bar/*", "bar/*/"]), expected)
+
+ def test_run_formatters_handles_oserror_for_black_path(self):
+ cases = [
+ (FileNotFoundError, "nonexistent"),
+ (
+ OSError if sys.platform == "win32" else PermissionError,
+ str(Path(__file__).parent / "test_files" / "black"),
+ ),
+ ]
+ for exception, location in cases:
+ with (
+ self.subTest(exception.__qualname__),
+ AssertFormatterFailureCaughtContext(
+ self, shutil_which_result=location
+ ) as ctx,
+ ):
+ run_formatters([], stderr=ctx.stderr)
+ parsed_error = ctx.stderr.getvalue()
+ self.assertIn(exception.__qualname__, parsed_error)
+ if sys.platform != "win32":
+ self.assertIn(location, parsed_error)
diff --git a/tests/user_commands/utils.py b/tests/user_commands/utils.py
new file mode 100644
index 0000000000..84f6bdbc5c
--- /dev/null
+++ b/tests/user_commands/utils.py
@@ -0,0 +1,23 @@
+from io import StringIO
+from unittest import mock
+
+
+class AssertFormatterFailureCaughtContext:
+
+ def __init__(self, test, shutil_which_result="nonexistent"):
+ self.stdout = StringIO()
+ self.stderr = StringIO()
+ self.test = test
+ self.shutil_which_result = shutil_which_result
+
+ def __enter__(self):
+ self.mocker = mock.patch(
+ "django.core.management.utils.shutil.which",
+ return_value=self.shutil_which_result,
+ )
+ self.mocker.start()
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.mocker.stop()
+ self.test.assertIn("Formatters failed to launch", self.stderr.getvalue())