From de4a1dd71da1de6e0ad366e3ee967b76383e70e8 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 25 May 2022 12:58:51 +0200 Subject: [PATCH 1/2] Fix error handling with pyrepl.readline.read_history_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - close file handler always - do not throw UnicodeDecodeError with invalid unicode data, which appeared to have gotten there in the context of some Python segfault (`0���p`) --- pyrepl/readline.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pyrepl/readline.py b/pyrepl/readline.py index 8ac466d..4bddcae 100644 --- a/pyrepl/readline.py +++ b/pyrepl/readline.py @@ -291,19 +291,18 @@ def read_history_file(self, filename='~/.history'): # history item: we use \r\n instead of just \n. If the history # file is passed to GNU readline, the extra \r are just ignored. history = self.get_reader().history - f = open(os.path.expanduser(filename), 'r') buffer = [] - for line in f: - if line.endswith('\r\n'): - buffer.append(line) - else: - line = self._histline(line) - if buffer: - line = ''.join(buffer).replace('\r', '') + line - del buffer[:] - if line: - history.append(line) - f.close() + with open(os.path.expanduser(filename), 'r', errors='replace') as f: + for line in f: + if line.endswith('\r\n'): + buffer.append(line) + else: + line = self._histline(line) + if buffer: + line = ''.join(buffer).replace('\r', '') + line + del buffer[:] + if line: + history.append(line) def write_history_file(self, filename='~/.history'): maxlength = self.saved_history_length From 0c53ea197447aa2422bb3b78abb2446c2bf64442 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 25 May 2022 14:31:54 +0200 Subject: [PATCH 2/2] use codecs.open for py27 compat --- pyrepl/readline.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyrepl/readline.py b/pyrepl/readline.py index 4bddcae..5ce0c1f 100644 --- a/pyrepl/readline.py +++ b/pyrepl/readline.py @@ -290,9 +290,11 @@ def read_history_file(self, filename='~/.history'): # are actually continuations inside a single multiline_input() # history item: we use \r\n instead of just \n. If the history # file is passed to GNU readline, the extra \r are just ignored. + import codecs # for py27 compatibility. + history = self.get_reader().history buffer = [] - with open(os.path.expanduser(filename), 'r', errors='replace') as f: + with codecs.open(os.path.expanduser(filename), 'r', errors='replace') as f: for line in f: if line.endswith('\r\n'): buffer.append(line)