Fixed #27600 -- Suppressed the REPL during shell's reading from stdin.
Thanks Adam Chainz for review and guidance.
This commit is contained in:
parent
24fa728a47
commit
bf6392bb75
|
@ -1,4 +1,6 @@
|
|||
import os
|
||||
import select
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
@ -7,7 +9,12 @@ from django.utils.deprecation import RemovedInDjango20Warning
|
|||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Runs a Python interactive interpreter. Tries to use IPython or bpython, if one of them is available."
|
||||
help = (
|
||||
"Runs a Python interactive interpreter. Tries to use IPython or "
|
||||
"bpython, if one of them is available. Any standard input is executed "
|
||||
"as code."
|
||||
)
|
||||
|
||||
requires_system_checks = False
|
||||
shells = ['ipython', 'bpython', 'python']
|
||||
|
||||
|
@ -114,6 +121,12 @@ class Command(BaseCommand):
|
|||
exec(options['command'])
|
||||
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 select.select([sys.stdin], [], [], 0)[0]:
|
||||
exec(sys.stdin.read())
|
||||
return
|
||||
|
||||
available_shells = [options['interface']] if options['interface'] else self.shells
|
||||
|
||||
for shell in available_shells:
|
||||
|
|
|
@ -979,6 +979,22 @@ Lets you pass a command as a string to execute it as Django, like so::
|
|||
|
||||
django-admin shell --command="import django; print(django.__version__)"
|
||||
|
||||
You can also pass code in on standard input to execute it. For example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ django-admin shell <<EOF
|
||||
> import django
|
||||
> print(django.__version__)
|
||||
> EOF
|
||||
|
||||
On Windows, the REPL is output due to implementation limits of
|
||||
:func:`select.select` on that platform.
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
In older versions, the REPL is also output on UNIX systems.
|
||||
|
||||
``showmigrations``
|
||||
------------------
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import sys
|
||||
import unittest
|
||||
|
||||
from django import __version__
|
||||
from django.core.management import call_command
|
||||
from django.test import SimpleTestCase
|
||||
from django.test.utils import patch_logger
|
||||
from django.test import SimpleTestCase, mock
|
||||
from django.test.utils import captured_stdin, captured_stdout, patch_logger
|
||||
|
||||
|
||||
class ShellCommandTestCase(SimpleTestCase):
|
||||
|
@ -17,3 +20,12 @@ class ShellCommandTestCase(SimpleTestCase):
|
|||
)
|
||||
self.assertEqual(len(logger), 1)
|
||||
self.assertEqual(logger[0], __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):
|
||||
with captured_stdin() as stdin, captured_stdout() as stdout:
|
||||
stdin.write('print(100)\n')
|
||||
stdin.seek(0)
|
||||
call_command('shell')
|
||||
self.assertEqual(stdout.getvalue().strip(), '100')
|
||||
|
|
Loading…
Reference in New Issue