summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Lapeyre <remi.lapeyre@lenstra.fr>2024-03-01 19:39:16 (GMT)
committerGitHub <noreply@github.com>2024-03-01 19:39:16 (GMT)
commitb5949eac6220ee8002971b5e7026432ac7990c74 (patch)
tree31ce0e7194306baa3afdfba3b3fcc2584aeb7aef
parente6e35327d87e5456ba2178915e4f523a42051d4b (diff)
downloadcpython-b5949eac6220ee8002971b5e7026432ac7990c74.zip
cpython-b5949eac6220ee8002971b5e7026432ac7990c74.tar.gz
cpython-b5949eac6220ee8002971b5e7026432ac7990c74.tar.bz2
gh-84995: Run sys.__interactivehook__() on asyncio REPL startup (#20517)
This makes the asyncio REPL (`python -m asyncio`) more usable and similar to the regular REPL. This exposes register_readline() as a top-level function in site.py, but it's intentionally undocumented. Co-authored-by: Carol Willing <carolcode@willingconsulting.com> Co-authored-by: Itamar Oren <itamarost@gmail.com>
-rw-r--r--Lib/asyncio/__main__.py16
-rw-r--r--Lib/site.py82
-rw-r--r--Misc/NEWS.d/next/Library/2020-05-29-18-08-54.bpo-40818.Ij8ffq.rst3
3 files changed, 62 insertions, 39 deletions
diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py
index 18bb87a..cbc1d7c 100644
--- a/Lib/asyncio/__main__.py
+++ b/Lib/asyncio/__main__.py
@@ -3,6 +3,7 @@ import asyncio
import code
import concurrent.futures
import inspect
+import site
import sys
import threading
import types
@@ -109,6 +110,21 @@ if __name__ == '__main__':
except ImportError:
pass
+ interactive_hook = getattr(sys, "__interactivehook__", None)
+
+ if interactive_hook is not None:
+ interactive_hook()
+
+ if interactive_hook is site.register_readline:
+ # Fix the completer function to use the interactive console locals
+ try:
+ import rlcompleter
+ except:
+ pass
+ else:
+ completer = rlcompleter.Completer(console.locals)
+ readline.set_completer(completer.complete)
+
repl_thread = REPLThread()
repl_thread.daemon = True
repl_thread.start()
diff --git a/Lib/site.py b/Lib/site.py
index 0631f3f..2aee63e 100644
--- a/Lib/site.py
+++ b/Lib/site.py
@@ -460,60 +460,64 @@ def gethistoryfile():
def enablerlcompleter():
"""Enable default readline configuration on interactive prompts, by
registering a sys.__interactivehook__.
+ """
+ sys.__interactivehook__ = register_readline
+
+
+def register_readline():
+ """Configure readline completion on interactive prompts.
If the readline module can be imported, the hook will set the Tab key
as completion key and register ~/.python_history as history file.
This can be overridden in the sitecustomize or usercustomize module,
or in a PYTHONSTARTUP file.
"""
- def register_readline():
- import atexit
- try:
- import readline
- import rlcompleter
- except ImportError:
- return
-
- # Reading the initialization (config) file may not be enough to set a
- # completion key, so we set one first and then read the file.
- if readline.backend == 'editline':
- readline.parse_and_bind('bind ^I rl_complete')
- else:
- readline.parse_and_bind('tab: complete')
+ import atexit
+ try:
+ import readline
+ import rlcompleter
+ except ImportError:
+ return
+ # Reading the initialization (config) file may not be enough to set a
+ # completion key, so we set one first and then read the file.
+ if readline.backend == 'editline':
+ readline.parse_and_bind('bind ^I rl_complete')
+ else:
+ readline.parse_and_bind('tab: complete')
+
+ try:
+ readline.read_init_file()
+ except OSError:
+ # An OSError here could have many causes, but the most likely one
+ # is that there's no .inputrc file (or .editrc file in the case of
+ # Mac OS X + libedit) in the expected location. In that case, we
+ # want to ignore the exception.
+ pass
+
+ if readline.get_current_history_length() == 0:
+ # If no history was loaded, default to .python_history,
+ # or PYTHON_HISTORY.
+ # The guard is necessary to avoid doubling history size at
+ # each interpreter exit when readline was already configured
+ # through a PYTHONSTARTUP hook, see:
+ # http://bugs.python.org/issue5845#msg198636
+ history = gethistoryfile()
try:
- readline.read_init_file()
+ readline.read_history_file(history)
except OSError:
- # An OSError here could have many causes, but the most likely one
- # is that there's no .inputrc file (or .editrc file in the case of
- # Mac OS X + libedit) in the expected location. In that case, we
- # want to ignore the exception.
pass
- if readline.get_current_history_length() == 0:
- # If no history was loaded, default to .python_history,
- # or PYTHON_HISTORY.
- # The guard is necessary to avoid doubling history size at
- # each interpreter exit when readline was already configured
- # through a PYTHONSTARTUP hook, see:
- # http://bugs.python.org/issue5845#msg198636
- history = gethistoryfile()
+ def write_history():
try:
- readline.read_history_file(history)
- except OSError:
+ readline.write_history_file(history)
+ except (FileNotFoundError, PermissionError):
+ # home directory does not exist or is not writable
+ # https://bugs.python.org/issue19891
pass
- def write_history():
- try:
- readline.write_history_file(history)
- except OSError:
- # bpo-19891, bpo-41193: Home directory does not exist
- # or is not writable, or the filesystem is read-only.
- pass
+ atexit.register(write_history)
- atexit.register(write_history)
-
- sys.__interactivehook__ = register_readline
def venv(known_paths):
global PREFIXES, ENABLE_USER_SITE
diff --git a/Misc/NEWS.d/next/Library/2020-05-29-18-08-54.bpo-40818.Ij8ffq.rst b/Misc/NEWS.d/next/Library/2020-05-29-18-08-54.bpo-40818.Ij8ffq.rst
new file mode 100644
index 0000000..27f6a6d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-05-29-18-08-54.bpo-40818.Ij8ffq.rst
@@ -0,0 +1,3 @@
+The asyncio REPL now runs :data:`sys.__interactivehook__` on startup. The
+default implementation of :data:`sys.__interactivehook__` provides
+auto-completion to the asyncio REPL. Patch contributed by Rémi Lapeyre.