Skip to content

Commit 5126bf0

Browse files
committed
fix editline analysis on macOS
1 parent e44596e commit 5126bf0

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

Lib/_pyrepl/readline.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
from .unix_console import UnixConsole as Console, _error
5151

5252
ENCODING = sys.getdefaultencoding() or "latin1"
53+
_EDITLINE_MARKER = "_HiStOrY_V2_"
54+
_EDITLINE_BYTES_MARKER = b"_HiStOrY_V2_"
5355

5456

5557
# types
@@ -60,7 +62,7 @@
6062
TYPE_CHECKING = False
6163

6264
if TYPE_CHECKING:
63-
from typing import Any, Mapping
65+
from typing import Any, IO, Mapping
6466

6567

6668
MoreLinesCallable = Callable[[str], bool]
@@ -425,6 +427,19 @@ def set_history_length(self, length: int) -> None:
425427
def get_current_history_length(self) -> int:
426428
return len(self.get_reader().history)
427429

430+
@staticmethod
431+
def _analyze_history_file(filename: str | IO[bytes]) -> tuple[bool, str]:
432+
if isinstance(filename, str):
433+
if not os.path.exists(filename):
434+
return False, "utf-8"
435+
with open(filename, "rb") as f:
436+
is_editline = f.readline().startswith(_EDITLINE_BYTES_MARKER)
437+
else:
438+
is_editline = f.readline().startswith(_EDITLINE_BYTES_MARKER)
439+
if is_editline:
440+
return True, "unicode-escape"
441+
return False, "utf-8"
442+
428443
def read_history_file(self, filename: str = gethistoryfile()) -> None:
429444
# multiline extension (really a hack) for the end of lines that
430445
# are actually continuations inside a single multiline_input()
@@ -433,12 +448,9 @@ def read_history_file(self, filename: str = gethistoryfile()) -> None:
433448
history = self.get_reader().history
434449

435450
with open(os.path.expanduser(filename), 'rb') as f:
436-
is_editline = f.readline().startswith(b"_HiStOrY_V2_")
437-
if is_editline:
438-
encoding = "unicode-escape"
439-
else:
451+
is_editline, encoding = self._analyze_history_file(f)
452+
if not is_editline:
440453
f.seek(0)
441-
encoding = "utf-8"
442454

443455
lines = [line.decode(encoding, errors='replace') for line in f.read().split(b'\n')]
444456
buffer = []
@@ -457,9 +469,12 @@ def read_history_file(self, filename: str = gethistoryfile()) -> None:
457469
def write_history_file(self, filename: str = gethistoryfile()) -> None:
458470
maxlength = self.saved_history_length
459471
history = self.get_reader().get_trimmed_history(maxlength)
460-
f = open(os.path.expanduser(filename), "w",
461-
encoding="utf-8", newline="\n")
462-
with f:
472+
473+
filename = os.path.expanduser(filename)
474+
is_editline, encoding = self._analyze_history_file(filename)
475+
with open(filename, "w", encoding=encoding, newline="\n") as f:
476+
if is_editline:
477+
f.write(f"{_EDITLINE_MARKER}\n")
463478
for entry in history:
464479
entry = entry.replace("\n", "\r\n") # multiline history support
465480
f.write(entry + "\n")
@@ -469,9 +484,10 @@ def append_history_file(self, filename: str = gethistoryfile()) -> None:
469484
saved_length = self.get_history_length()
470485
length = self.get_current_history_length() - saved_length
471486
history = reader.get_trimmed_history(length)
472-
f = open(os.path.expanduser(filename), "a",
473-
encoding="utf-8", newline="\n")
474-
with f:
487+
488+
filename = os.path.expanduser(filename)
489+
_, encoding = self._analyze_history_file(filename)
490+
with open(filename, "a", encoding=encoding, newline="\n") as f:
475491
for entry in history:
476492
entry = entry.replace("\n", "\r\n") # multiline history support
477493
f.write(entry + "\n")

0 commit comments

Comments
 (0)