summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Inglesby <peter.inglesby@gmail.com>2021-01-18 19:07:07 +0000
committerCarlton Gibson <carlton.gibson@noumenal.es>2021-06-23 14:53:41 +0200
commit1bbb98d9a4b7d83e422b14ae2429cb368eff5a13 (patch)
tree07d2b386ad5c17ce5e78a9748b57fc07a7193325
parent1e5aa8e1c79252cc810af21294a6e945d11d37b3 (diff)
Fixed #32363 -- Ensured sys.__interactivehook__ is called in shell
By default, this means that readline is properly registered, so that .python_history is used. sys.__interactivehook__ may be set by a $PYTHONSTARTUP file.
-rw-r--r--django/core/management/commands/shell.py40
-rw-r--r--docs/releases/4.0.txt5
2 files changed, 27 insertions, 18 deletions
diff --git a/django/core/management/commands/shell.py b/django/core/management/commands/shell.py
index 3e8a451e3e..fe24f4b3fb 100644
--- a/django/core/management/commands/shell.py
+++ b/django/core/management/commands/shell.py
@@ -42,25 +42,8 @@ class Command(BaseCommand):
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.
+ # Set up a dictionary to serve as the environment for the shell.
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)
- # Enable tab completion on systems using libedit (e.g. macOS).
- # These lines are copied from Python's Lib/site.py.
- readline_doc = getattr(readline, '__doc__', '')
- if readline_doc is not None and 'libedit' in readline_doc:
- readline.parse_and_bind("bind ^I rl_complete")
- else:
- 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.
@@ -79,6 +62,27 @@ class Command(BaseCommand):
except Exception:
traceback.print_exc()
+ # By default, this will set up readline to do tab completion and to read and
+ # write history to the .python_history file, but this can be overridden by
+ # $PYTHONSTARTUP or ~/.pythonrc.py.
+ try:
+ sys.__interactivehook__()
+ except Exception:
+ # Match the behavior of the cpython shell where an error in
+ # sys.__interactivehook__ prints a warning and the exception and continues.
+ print("Failed calling sys.__interactivehook__")
+ traceback.print_exc()
+
+ # Set up tab completion for objects imported by $PYTHONSTARTUP or
+ # ~/.pythonrc.py.
+ try:
+ import readline
+ import rlcompleter
+ readline.set_completer(rlcompleter.Completer(imported_objects).complete)
+ except ImportError:
+ pass
+
+ # Start the interactive interpreter.
code.interact(local=imported_objects)
def handle(self, **options):
diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt
index a9e660f0f1..9b57a524aa 100644
--- a/docs/releases/4.0.txt
+++ b/docs/releases/4.0.txt
@@ -236,6 +236,11 @@ Management Commands
* On PostgreSQL, :djadmin:`dbshell` now supports specifying a password file.
+* The :djadmin:`shell` command now respects :py:data:`sys.__interactivehook__`
+ at startup. This allows loading shell history between interactive sessions.
+ As a consequence, ``readline`` is no longer loaded if running in *isolated*
+ mode.
+
Migrations
~~~~~~~~~~