diff options
| author | SaJH <wogur981208@gmail.com> | 2025-09-24 00:11:31 +0900 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-09-25 11:40:04 +0200 |
| commit | db2f206ee1b1be68e77ffc26eccdcd662897df65 (patch) | |
| tree | 22b1a5a2db3d185ee906456ea87766a640355335 | |
| parent | 315e7def3c7484cfbc63a818597fe46012a42381 (diff) | |
[6.0.x] Fixed #36434 -- Preserved unbuffered stdio (-u) in autoreloader child.
Signed-off-by: SaJH <wogur981208@gmail.com>
Backport of 68aae8878ff90dd787db55ecc44ee712525ccdc6 from main.
| -rw-r--r-- | django/utils/autoreload.py | 13 | ||||
| -rw-r--r-- | tests/utils_tests/test_autoreload.py | 47 |
2 files changed, 60 insertions, 0 deletions
diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index c6716215f5..99812979d7 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -268,6 +268,19 @@ def trigger_reload(filename): def restart_with_reloader(): new_environ = {**os.environ, DJANGO_AUTORELOAD_ENV: "true"} + orig = getattr(sys, "orig_argv", ()) + if any( + (arg == "-u") + or ( + arg.startswith("-") + and not arg.startswith(("--", "-X", "-W")) + and len(arg) > 2 + and arg[1:].isalpha() + and "u" in arg + ) + for arg in orig[1:] + ): + new_environ.setdefault("PYTHONUNBUFFERED", "1") args = get_child_arguments() while True: p = subprocess.run(args, env=new_environ, close_fds=False) diff --git a/tests/utils_tests/test_autoreload.py b/tests/utils_tests/test_autoreload.py index 83f3e3898f..c9e6443c6f 100644 --- a/tests/utils_tests/test_autoreload.py +++ b/tests/utils_tests/test_autoreload.py @@ -535,6 +535,53 @@ class RestartWithReloaderTests(SimpleTestCase): [self.executable, "-Wall", "-m", "django"] + argv[1:], ) + def test_propagates_unbuffered_from_parent(self): + for args in ("-u", "-Iuv"): + with self.subTest(args=args): + with mock.patch.dict(os.environ, {}, clear=True): + with tempfile.TemporaryDirectory() as d: + script = Path(d) / "manage.py" + script.touch() + mock_call = self.patch_autoreload([str(script), "runserver"]) + with ( + mock.patch("__main__.__spec__", None), + mock.patch.object( + autoreload.sys, + "orig_argv", + [self.executable, args, str(script), "runserver"], + ), + ): + autoreload.restart_with_reloader() + env = mock_call.call_args.kwargs["env"] + self.assertEqual(env.get("PYTHONUNBUFFERED"), "1") + + def test_does_not_propagate_unbuffered_from_parent(self): + for args in ( + "-Xdev", + "-Xfaulthandler", + "--user", + "-Wall", + "-Wdefault", + "-Wignore::UserWarning", + ): + with self.subTest(args=args): + with mock.patch.dict(os.environ, {}, clear=True): + with tempfile.TemporaryDirectory() as d: + script = Path(d) / "manage.py" + script.touch() + mock_call = self.patch_autoreload([str(script), "runserver"]) + with ( + mock.patch("__main__.__spec__", None), + mock.patch.object( + autoreload.sys, + "orig_argv", + [self.executable, args, str(script), "runserver"], + ), + ): + autoreload.restart_with_reloader() + env = mock_call.call_args.kwargs["env"] + self.assertIsNone(env.get("PYTHONUNBUFFERED")) + class ReloaderTests(SimpleTestCase): RELOADER_CLS = None |
