Browse Source

Fixed #25838 -- Added "python" as an interface to the shell command.

Deprecates the "--plain" option.
Jon Dufresne 9 years ago
parent
commit
f1628f6be1

+ 50 - 48
django/core/management/commands/shell.py

@@ -1,20 +1,23 @@
 import os
+import warnings
 
 from django.core.management.base import BaseCommand
+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."
     requires_system_checks = False
-    shells = ['ipython', 'bpython']
+    shells = ['ipython', 'bpython', 'python']
 
     def add_arguments(self, parser):
         parser.add_argument('--plain', action='store_true', dest='plain',
-            help='Tells Django to use plain Python, not IPython or bpython.')
+            help='Tells Django to use plain Python, not IPython or bpython. '
+            'Deprecated, use the `-i python` or `--interface python` option instead.')
         parser.add_argument('--no-startup', action='store_true', dest='no_startup',
             help='When using plain Python, ignore the PYTHONSTARTUP environment variable and ~/.pythonrc.py script.')
         parser.add_argument('-i', '--interface', choices=self.shells, dest='interface',
-            help='Specify an interactive interpreter interface. Available options: "ipython" and "bpython"')
+            help='Specify an interactive interpreter interface. Available options: "ipython", "bpython", and "python"')
 
     def _ipython_pre_011(self):
         """Start IPython pre-0.11"""
@@ -34,7 +37,7 @@ class Command(BaseCommand):
         from IPython import start_ipython
         start_ipython(argv=[])
 
-    def ipython(self):
+    def ipython(self, options):
         """Start any version of IPython"""
         for ip in (self._ipython, self._ipython_pre_100, self._ipython_pre_011):
             try:
@@ -46,56 +49,55 @@ class Command(BaseCommand):
         # no IPython, raise ImportError
         raise ImportError("No IPython")
 
-    def bpython(self):
+    def bpython(self, options):
         import bpython
         bpython.embed()
 
-    def run_shell(self, shell=None):
-        available_shells = [shell] if shell else self.shells
+    def python(self, options):
+        import code
+        # Set up a dictionary to serve as the environment for the shell, so
+        # that tab completion works on objects that are imported at runtime.
+        imported_objects = {}
+        try:  # Try activating rlcompleter, because it's handy.
+            import readline
+        except ImportError:
+            pass
+        else:
+            # We don't have to wrap the following import in a 'try', because
+            # we already know 'readline' was imported successfully.
+            import rlcompleter
+            readline.set_completer(rlcompleter.Completer(imported_objects).complete)
+            readline.parse_and_bind("tab:complete")
 
-        for shell in available_shells:
-            try:
-                return getattr(self, shell)()
-            except ImportError:
-                pass
-        raise ImportError
+        # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
+        # conventions and get $PYTHONSTARTUP first then .pythonrc.py.
+        if not options['no_startup']:
+            for pythonrc in (os.environ.get("PYTHONSTARTUP"), '~/.pythonrc.py'):
+                if not pythonrc:
+                    continue
+                pythonrc = os.path.expanduser(pythonrc)
+                if not os.path.isfile(pythonrc):
+                    continue
+                try:
+                    with open(pythonrc) as handle:
+                        exec(compile(handle.read(), pythonrc, 'exec'), imported_objects)
+                except NameError:
+                    pass
+        code.interact(local=imported_objects)
 
     def handle(self, **options):
-        try:
-            if options['plain']:
-                # Don't bother loading IPython, because the user wants plain Python.
-                raise ImportError
+        if options['plain']:
+            warnings.warn(
+                "The --plain option is deprecated in favor of the -i python or --interface python option.",
+                RemovedInDjango20Warning
+            )
+            options['interface'] = 'python'
 
-            self.run_shell(shell=options['interface'])
-        except ImportError:
-            import code
-            # Set up a dictionary to serve as the environment for the shell, so
-            # that tab completion works on objects that are imported at runtime.
-            # See ticket 5082.
-            imported_objects = {}
-            try:  # Try activating rlcompleter, because it's handy.
-                import readline
+        available_shells = [options['interface']] if options['interface'] else self.shells
+
+        for shell in available_shells:
+            try:
+                return getattr(self, shell)(options)
             except ImportError:
                 pass
-            else:
-                # We don't have to wrap the following import in a 'try', because
-                # we already know 'readline' was imported successfully.
-                import rlcompleter
-                readline.set_completer(rlcompleter.Completer(imported_objects).complete)
-                readline.parse_and_bind("tab:complete")
-
-            # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
-            # conventions and get $PYTHONSTARTUP first then .pythonrc.py.
-            if not options['no_startup']:
-                for pythonrc in (os.environ.get("PYTHONSTARTUP"), '~/.pythonrc.py'):
-                    if not pythonrc:
-                        continue
-                    pythonrc = os.path.expanduser(pythonrc)
-                    if not os.path.isfile(pythonrc):
-                        continue
-                    try:
-                        with open(pythonrc) as handle:
-                            exec(compile(handle.read(), pythonrc, 'exec'), imported_objects)
-                    except NameError:
-                        pass
-            code.interact(local=imported_objects)
+        raise ImportError("Couldn't load any of the specified interfaces.")

+ 2 - 0
docs/internals/deprecation.txt

@@ -126,6 +126,8 @@ details on these changes.
 
 * ``django.utils.functional.allow_lazy()`` will be removed.
 
+* The ``shell --plain`` option will be removed.
+
 .. _deprecation-removed-in-1.10:
 
 1.10

+ 11 - 5
docs/ref/django-admin.txt

@@ -933,9 +933,15 @@ Starts the Python interactive interpreter.
 
 Django will use IPython_ or bpython_ if either is installed. If you have a
 rich shell installed but want to force use of the "plain" Python interpreter,
-use the ``--plain`` option, like so::
+use the ``-i python`` or ``--interface python`` option, like so::
 
-    django-admin shell --plain
+    django-admin shell -i python
+    django-admin shell --interface python
+
+.. deprecated:: 1.10
+
+   In older versions, use the ``--plain`` option. This is deprecated and will
+   be removed in Django 2.0.
 
 If you would like to specify either IPython or bpython as your interpreter if
 you have both installed you can specify an alternative interpreter interface
@@ -957,12 +963,12 @@ bpython::
 .. _bpython: http://bpython-interpreter.org/
 
 When the "plain" Python interactive interpreter starts (be it because
-``--plain`` was specified or because no other interactive interface is
-available) it reads the script pointed to by the :envvar:`PYTHONSTARTUP`
+``--interface python`` was specified or because no other interactive interface
+is available) it reads the script pointed to by the :envvar:`PYTHONSTARTUP`
 environment variable and the ``~/.pythonrc.py`` script. If you don't wish this
 behavior you can use the ``--no-startup`` option. e.g.::
 
-    django-admin shell --plain --no-startup
+    django-admin shell --interface python --no-startup
 
 showmigrations [<app_label> [<app_label>]]
 ------------------------------------------

+ 6 - 0
docs/releases/1.10.txt

@@ -212,6 +212,9 @@ Management Commands
 * :djadmin:`makemigrations` now displays the path to the migration files that
   it generates.
 
+* The :djadmin:`shell` ``--interface`` option now accepts ``python`` to force
+  use of the "plain" Python interpreter.
+
 Migrations
 ^^^^^^^^^^
 
@@ -432,6 +435,9 @@ Miscellaneous
   :func:`~django.utils.functional.keep_lazy` function which can be used with a
   more natural decorator syntax.
 
+* The ``shell --plain`` option is deprecated in favor of ``-i python`` or
+  ``--interface python``.
+
 .. _removed-features-1.10:
 
 Features removed in 1.10