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.
This commit is contained in:
Peter Inglesby 2021-01-18 19:07:07 +00:00 committed by Carlton Gibson
parent 1e5aa8e1c7
commit 1bbb98d9a4
2 changed files with 27 additions and 18 deletions

View File

@ -42,25 +42,8 @@ class Command(BaseCommand):
def python(self, options): def python(self, options):
import code import code
# Set up a dictionary to serve as the environment for the shell, so # Set up a dictionary to serve as the environment for the shell.
# that tab completion works on objects that are imported at runtime.
imported_objects = {} 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 # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system
# conventions and get $PYTHONSTARTUP first then .pythonrc.py. # conventions and get $PYTHONSTARTUP first then .pythonrc.py.
@ -79,6 +62,27 @@ class Command(BaseCommand):
except Exception: except Exception:
traceback.print_exc() 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) code.interact(local=imported_objects)
def handle(self, **options): def handle(self, **options):

View File

@ -236,6 +236,11 @@ Management Commands
* On PostgreSQL, :djadmin:`dbshell` now supports specifying a password file. * 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 Migrations
~~~~~~~~~~ ~~~~~~~~~~