Skip to content

Commit

Permalink
Refactor register_readline()
Browse files Browse the repository at this point in the history
* make readline stuff more symmetrical wrt reading/writing
* prevent truncation of the history file
* add regression test

Should finally address python#121245.
  • Loading branch information
skirpichev committed Jul 2, 2024
1 parent 7a807c3 commit c13de70
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 14 deletions.
28 changes: 14 additions & 14 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,35 +509,35 @@ def register_readline():
pass

if readline.get_current_history_length() == 0:
try:
from _pyrepl.main import CAN_USE_PYREPL
except ImportError:
CAN_USE_PYREPL = False
# 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()
if os.getenv("PYTHON_BASIC_REPL") or not CAN_USE_PYREPL:
my_readline = readline
else:
my_readline = _pyrepl.readline
try:
if os.getenv("PYTHON_BASIC_REPL"):
readline.read_history_file(history)
else:
_pyrepl.readline.read_history_file(history)
my_readline.read_history_file(history)
except (OSError,* _pyrepl.unix_console._error):
pass

def write_history():
try:
from _pyrepl.main import CAN_USE_PYREPL
except ImportError:
CAN_USE_PYREPL = False

try:
if os.getenv("PYTHON_BASIC_REPL") or not CAN_USE_PYREPL:
readline.write_history_file(history)
else:
_pyrepl.readline.write_history_file(history)
except (FileNotFoundError, PermissionError):
if my_readline.get_current_history_length() > 0:
my_readline.write_history_file(history)
except (FileNotFoundError, PermissionError,
_pyrepl.unix_console.InvalidTerminal):
# home directory does not exist or is not writable
# https://bugs.python.org/issue19891
# or terminal doesn't have the required capability
pass

atexit.register(write_history)
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/test_pyrepl/test_pyrepl.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import io
import itertools
import os
import pathlib
import rlcompleter
import select
import subprocess
import sys
import tempfile
from unittest import TestCase, skipUnless
from unittest.mock import patch
from test.support import force_not_colorized
Expand Down Expand Up @@ -898,6 +900,21 @@ def test_python_basic_repl(self):
self.assertNotIn("Exception", output)
self.assertNotIn("Traceback", output)

def setUp(self):
self.hfile = tempfile.NamedTemporaryFile(delete=False)

def tearDown(self):
self.hfile.close()

def test_not_wiping_history_file(self):
env = os.environ.copy()
env.update({"PYTHON_HISTORY": self.hfile.name})
commands = "123\nspam\nexit()\n"
output, exit_code = self.run_repl(commands, env=env)
self.assertIn("123", output)
self.assertIn("spam", output)
self.assertNotEqual(pathlib.Path(self.hfile.name).stat().st_size, 0)

def run_repl(self, repl_input: str | list[str], env: dict | None = None) -> tuple[str, int]:
master_fd, slave_fd = pty.openpty()
process = subprocess.Popen(
Expand Down

0 comments on commit c13de70

Please sign in to comment.