Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-122273: Support PyREPL history on Windows #127141

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Lib/_pyrepl/readline.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
55 changes: 36 additions & 19 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,40 +498,55 @@ 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:
original_path = sys.path
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
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support PyREPL history on Windows. Patch by devdanzin and Victor Stinner.
Loading