mirror of
https://github.com/django/django.git
synced 2025-04-13 03:52:20 +00:00
Fixed #36224 -- Fixed shell imports when settings not configured.
Thank you Raffaella for the report. Thank you Tim Schilling and Natalia Bidart for the reviews.
This commit is contained in:
parent
647dca4132
commit
de1117ea8e
@ -6,6 +6,7 @@ from collections import defaultdict
|
||||
from importlib import import_module
|
||||
|
||||
from django.apps import apps
|
||||
from django.core.exceptions import AppRegistryNotReady
|
||||
from django.core.management import BaseCommand, CommandError
|
||||
from django.utils.datastructures import OrderedSet
|
||||
from django.utils.module_loading import import_string as import_dotted_path
|
||||
@ -150,6 +151,22 @@ class Command(BaseCommand):
|
||||
if options and options.get("no_imports"):
|
||||
return {}
|
||||
|
||||
verbosity = options["verbosity"] if options else 0
|
||||
|
||||
try:
|
||||
apps.check_models_ready()
|
||||
except AppRegistryNotReady:
|
||||
if verbosity > 0:
|
||||
settings_env_var = os.getenv("DJANGO_SETTINGS_MODULE")
|
||||
self.stdout.write(
|
||||
"Automatic imports are disabled since settings are not configured."
|
||||
f"\nDJANGO_SETTINGS_MODULE value is {settings_env_var!r}.\n"
|
||||
"HINT: Ensure that the settings module is configured and set.",
|
||||
self.style.ERROR,
|
||||
ending="\n\n",
|
||||
)
|
||||
return {}
|
||||
|
||||
path_imports = self.get_auto_imports()
|
||||
if path_imports is None:
|
||||
return {}
|
||||
@ -175,7 +192,6 @@ class Command(BaseCommand):
|
||||
name: obj for items in auto_imports.values() for name, obj in items
|
||||
}
|
||||
|
||||
verbosity = options["verbosity"] if options else 0
|
||||
if verbosity < 1:
|
||||
return namespace
|
||||
|
||||
@ -228,7 +244,7 @@ class Command(BaseCommand):
|
||||
def handle(self, **options):
|
||||
# Execute the command and exit.
|
||||
if options["command"]:
|
||||
exec(options["command"], {**globals(), **self.get_namespace()})
|
||||
exec(options["command"], {**globals(), **self.get_namespace(**options)})
|
||||
return
|
||||
|
||||
# Execute stdin if it has anything to read and exit.
|
||||
@ -238,7 +254,7 @@ class Command(BaseCommand):
|
||||
and not sys.stdin.isatty()
|
||||
and select.select([sys.stdin], [], [], 0)[0]
|
||||
):
|
||||
exec(sys.stdin.read(), {**globals(), **self.get_namespace()})
|
||||
exec(sys.stdin.read(), {**globals(), **self.get_namespace(**options)})
|
||||
return
|
||||
|
||||
available_shells = (
|
||||
|
@ -1,3 +1,5 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import mock
|
||||
@ -23,25 +25,85 @@ class ShellCommandTestCase(SimpleTestCase):
|
||||
|
||||
def test_command_option(self):
|
||||
with self.assertLogs("test", "INFO") as cm:
|
||||
call_command(
|
||||
"shell",
|
||||
command=(
|
||||
"import django; from logging import getLogger; "
|
||||
'getLogger("test").info(django.__version__)'
|
||||
),
|
||||
)
|
||||
with captured_stdout():
|
||||
call_command(
|
||||
"shell",
|
||||
command=(
|
||||
"import django; from logging import getLogger; "
|
||||
'getLogger("test").info(django.__version__)'
|
||||
),
|
||||
)
|
||||
self.assertEqual(cm.records[0].getMessage(), __version__)
|
||||
|
||||
def test_command_option_globals(self):
|
||||
with captured_stdout() as stdout:
|
||||
call_command("shell", command=self.script_globals)
|
||||
call_command("shell", command=self.script_globals, verbosity=0)
|
||||
self.assertEqual(stdout.getvalue().strip(), "True")
|
||||
|
||||
def test_command_option_inline_function_call(self):
|
||||
with captured_stdout() as stdout:
|
||||
call_command("shell", command=self.script_with_inline_function)
|
||||
call_command("shell", command=self.script_with_inline_function, verbosity=0)
|
||||
self.assertEqual(stdout.getvalue().strip(), __version__)
|
||||
|
||||
@override_settings(INSTALLED_APPS=["shell"])
|
||||
def test_no_settings(self):
|
||||
test_environ = os.environ.copy()
|
||||
if "DJANGO_SETTINGS_MODULE" in test_environ:
|
||||
del test_environ["DJANGO_SETTINGS_MODULE"]
|
||||
error = (
|
||||
"Automatic imports are disabled since settings are not configured.\n"
|
||||
"DJANGO_SETTINGS_MODULE value is None.\n"
|
||||
"HINT: Ensure that the settings module is configured and set.\n\n"
|
||||
)
|
||||
for verbosity, assertError in [
|
||||
("0", self.assertNotIn),
|
||||
("1", self.assertIn),
|
||||
("2", self.assertIn),
|
||||
]:
|
||||
with self.subTest(verbosity=verbosity, get_auto_imports="models"):
|
||||
p = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"django",
|
||||
"shell",
|
||||
"-c",
|
||||
"print(globals())",
|
||||
"-v",
|
||||
verbosity,
|
||||
],
|
||||
capture_output=True,
|
||||
env=test_environ,
|
||||
text=True,
|
||||
umask=-1,
|
||||
)
|
||||
assertError(error, p.stdout)
|
||||
self.assertNotIn("Marker", p.stdout)
|
||||
|
||||
with self.subTest(verbosity=verbosity, get_auto_imports="without-models"):
|
||||
with mock.patch(
|
||||
"django.core.management.commands.shell.Command.get_auto_imports",
|
||||
return_value=["django.urls.resolve"],
|
||||
):
|
||||
p = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"django",
|
||||
"shell",
|
||||
"-c",
|
||||
"print(globals())",
|
||||
"-v",
|
||||
verbosity,
|
||||
],
|
||||
capture_output=True,
|
||||
env=test_environ,
|
||||
text=True,
|
||||
umask=-1,
|
||||
)
|
||||
assertError(error, p.stdout)
|
||||
self.assertNotIn("resolve", p.stdout)
|
||||
|
||||
@unittest.skipIf(
|
||||
sys.platform == "win32", "Windows select() doesn't support file descriptors."
|
||||
)
|
||||
@ -50,7 +112,7 @@ class ShellCommandTestCase(SimpleTestCase):
|
||||
with captured_stdin() as stdin, captured_stdout() as stdout:
|
||||
stdin.write("print(100)\n")
|
||||
stdin.seek(0)
|
||||
call_command("shell")
|
||||
call_command("shell", verbosity=0)
|
||||
self.assertEqual(stdout.getvalue().strip(), "100")
|
||||
|
||||
@unittest.skipIf(
|
||||
@ -62,7 +124,7 @@ class ShellCommandTestCase(SimpleTestCase):
|
||||
with captured_stdin() as stdin, captured_stdout() as stdout:
|
||||
stdin.write(self.script_globals)
|
||||
stdin.seek(0)
|
||||
call_command("shell")
|
||||
call_command("shell", verbosity=0)
|
||||
self.assertEqual(stdout.getvalue().strip(), "True")
|
||||
|
||||
@unittest.skipIf(
|
||||
@ -74,7 +136,7 @@ class ShellCommandTestCase(SimpleTestCase):
|
||||
with captured_stdin() as stdin, captured_stdout() as stdout:
|
||||
stdin.write(self.script_with_inline_function)
|
||||
stdin.seek(0)
|
||||
call_command("shell")
|
||||
call_command("shell", verbosity=0)
|
||||
self.assertEqual(stdout.getvalue().strip(), __version__)
|
||||
|
||||
def test_ipython(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user