diff --git a/Lib/_pyrepl/readline.py b/Lib/_pyrepl/readline.py index 5e1d3085874380..888185eb03be66 100644 --- a/Lib/_pyrepl/readline.py +++ b/Lib/_pyrepl/readline.py @@ -450,7 +450,9 @@ 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: + f = open(os.path.expanduser(filename), "w", + encoding="utf-8", newline="\n") + with 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 319fb540f14828..89a81c55cb63dd 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -498,9 +498,18 @@ def register_readline(): PYTHON_BASIC_REPL = False import atexit + + try: + try: + import readline + except ImportError: + readline = None + else: + import rlcompleter # noqa: F401 + except ImportError: + return + try: - import readline - import rlcompleter if PYTHON_BASIC_REPL: CAN_USE_PYREPL = False else: @@ -508,30 +517,36 @@ def register_readline(): sys.path = [p for p in original_path if p != ''] try: import _pyrepl.readline - import _pyrepl.unix_console + if os.name == "nt": + import _pyrepl.windows_console + console_errors = (_pyrepl.windows_console._error,) + else: + import _pyrepl.unix_console + console_errors = _pyrepl.unix_console._error from _pyrepl.main import CAN_USE_PYREPL finally: sys.path = original_path 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') + if readline is not None: + # 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 + 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 readline is None or 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 @@ -542,8 +557,10 @@ def register_readline(): if CAN_USE_PYREPL: readline_module = _pyrepl.readline - exceptions = (OSError, *_pyrepl.unix_console._error) + exceptions = (OSError, *console_errors) else: + if readline is None: + return readline_module = readline exceptions = OSError diff --git a/Misc/NEWS.d/next/Library/2024-11-22-09-23-41.gh-issue-122273.H8M6fd.rst b/Misc/NEWS.d/next/Library/2024-11-22-09-23-41.gh-issue-122273.H8M6fd.rst new file mode 100644 index 00000000000000..99071e05377e33 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-11-22-09-23-41.gh-issue-122273.H8M6fd.rst @@ -0,0 +1 @@ +Support PyREPL history on Windows. Patch by devdanzin and Victor Stinner.