Bläddra i källkod

Fixed #32183 -- Fixed shell crash when passing code with nested scopes.

William Schwartz 4 år sedan
förälder
incheckning
c0fc5ba380
2 ändrade filer med 25 tillägg och 2 borttagningar
  1. 2 2
      django/core/management/commands/shell.py
  2. 23 0
      tests/shell/tests.py

+ 2 - 2
django/core/management/commands/shell.py

@@ -84,13 +84,13 @@ class Command(BaseCommand):
     def handle(self, **options):
         # Execute the command and exit.
         if options['command']:
-            exec(options['command'])
+            exec(options['command'], globals())
             return
 
         # Execute stdin if it has anything to read and exit.
         # Not supported on Windows due to select.select() limitations.
         if sys.platform != 'win32' and not sys.stdin.isatty() and select.select([sys.stdin], [], [], 0)[0]:
-            exec(sys.stdin.read())
+            exec(sys.stdin.read(), globals())
             return
 
         available_shells = [options['interface']] if options['interface'] else self.shells

+ 23 - 0
tests/shell/tests.py

@@ -10,6 +10,12 @@ from django.test.utils import captured_stdin, captured_stdout
 
 class ShellCommandTestCase(SimpleTestCase):
     script_globals = 'print("__name__" in globals())'
+    script_with_inline_function = (
+        'import django\n'
+        'def f():\n'
+        '    print(django.__version__)\n'
+        'f()'
+    )
 
     def test_command_option(self):
         with self.assertLogs('test', 'INFO') as cm:
@@ -27,6 +33,11 @@ class ShellCommandTestCase(SimpleTestCase):
             call_command('shell', command=self.script_globals)
         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)
+        self.assertEqual(stdout.getvalue().strip(), __version__)
+
     @unittest.skipIf(sys.platform == 'win32', "Windows select() doesn't support file descriptors.")
     @mock.patch('django.core.management.commands.shell.select')
     def test_stdin_read(self, select):
@@ -48,6 +59,18 @@ class ShellCommandTestCase(SimpleTestCase):
             call_command('shell')
         self.assertEqual(stdout.getvalue().strip(), 'True')
 
+    @unittest.skipIf(
+        sys.platform == 'win32',
+        "Windows select() doesn't support file descriptors.",
+    )
+    @mock.patch('django.core.management.commands.shell.select')  # [1]
+    def test_stdin_read_inline_function_call(self, select):
+        with captured_stdin() as stdin, captured_stdout() as stdout:
+            stdin.write(self.script_with_inline_function)
+            stdin.seek(0)
+            call_command('shell')
+        self.assertEqual(stdout.getvalue().strip(), __version__)
+
     @mock.patch('django.core.management.commands.shell.select.select')  # [1]
     @mock.patch.dict('sys.modules', {'IPython': None})
     def test_shell_with_ipython_not_installed(self, select):