diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 5e1d3085874380..24e1656237d966 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -450,7 +450,7 @@ def read_history_file(self, filename: str = gethistoryfile()) -> None: def write_history_file(self, filename: str = gethistoryfile()) -> None: maxlength = self.saved_history_length history = self.get_reader().get_trimmed_history(maxlength) - with open(os.path.expanduser(filename), "w", encoding="utf-8") as f: + with open(os.path.expanduser(filename), "w", encoding="utf-8", newline="\n") as f: for entry in history: entry = entry.replace("\n", "\r\n") # multiline history support f.write(entry + "\n") diff --git a/Lib/site.py b/Lib/site.py index 07a6361fad44e5..b789fa67d3d937 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -498,7 +498,12 @@ def register_readline(): import atexit try: - import readline + try: + import readline + real_readline = True + except ImportError: + readline = None + real_readline = False import rlcompleter # noqa: F401 if PYTHON_BASIC_REPL: CAN_USE_PYREPL = False @@ -506,9 +511,15 @@ def register_readline(): original_path = sys.path sys.path = [p for p in original_path if p != ''] try: - import _pyrepl.readline - import _pyrepl.unix_console + if not readline: + import _pyrepl.readline as readline from _pyrepl.main import CAN_USE_PYREPL + if real_readline: + import _pyrepl.unix_console + console_error = _pyrepl.unix_console._error + else: + import _pyrepl.windows_console + console_error = [_pyrepl.windows_console._error] finally: sys.path = original_path except ImportError: @@ -516,13 +527,15 @@ def register_readline(): # 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': + backend = getattr(readline, "backend", None) + if backend == 'editline': readline.parse_and_bind('bind ^I rl_complete') - else: + elif backend: readline.parse_and_bind('tab: complete') try: - readline.read_init_file() + if real_readline: + 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 @@ -530,7 +543,7 @@ def register_readline(): # want to ignore the exception. pass - if readline.get_current_history_length() == 0: + if readline and 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 @@ -541,19 +554,21 @@ def register_readline(): if CAN_USE_PYREPL: readline_module = _pyrepl.readline - exceptions = (OSError, *_pyrepl.unix_console._error) + exceptions = (OSError, *console_error) else: readline_module = readline exceptions = OSError try: - readline_module.read_history_file(history) + if readline: + readline_module.read_history_file(history) except exceptions: pass def write_history(): try: - readline_module.write_history_file(history) + if readline: + readline_module.write_history_file(history) except (FileNotFoundError, PermissionError): # home directory does not exist or is not writable # https://bugs.python.org/issue19891 diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-07-25-20-04-31.gh-issue-122273.ud9Vsi.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-07-25-20-04-31.gh-issue-122273.ud9Vsi.rst new file mode 100644 index 00000000000000..f5d7f81aa6e5b3 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-07-25-20-04-31.gh-issue-122273.ud9Vsi.rst @@ -0,0 +1 @@ +Add support for command history in the new REPL running on Windows.