]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-122273: Support PyREPL history on Windows (#127141)
authorVictor Stinner <vstinner@python.org>
Tue, 26 Nov 2024 09:21:57 +0000 (10:21 +0100)
committerGitHub <noreply@github.com>
Tue, 26 Nov 2024 09:21:57 +0000 (10:21 +0100)
Co-authored-by: devdanzin <74280297+devdanzin@users.noreply.github.com>
Lib/_pyrepl/readline.py
Lib/site.py
Misc/NEWS.d/next/Library/2024-11-22-09-23-41.gh-issue-122273.H8M6fd.rst [new file with mode: 0644]

index 5e1d30858743808c2775a7a304bcea9b309b7680..888185eb03be6601c8b1b61be153eb7e6db9a9da 100644 (file)
@@ -450,7 +450,9 @@ class _ReadlineWrapper:
     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")
index 54f07ab5b4e6d5df23060cb9d0e16b155de6c4e2..abf4b5202445544528939083ee5820e8e85eb8fa 100644 (file)
@@ -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  # noqa: F401
         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 (file)
index 0000000..99071e0
--- /dev/null
@@ -0,0 +1 @@
+Support PyREPL history on Windows. Patch by devdanzin and Victor Stinner.