From cd3fda0616ece6e44bc86e21306c0404ff320027 Mon Sep 17 00:00:00 2001 From: bretello Date: Sun, 29 Oct 2023 15:16:07 +0100 Subject: [PATCH] fixes or python2->python3, misc linter warnings --- pyrepl/_minimal_curses.py | 10 ++--- pyrepl/cmdrepl.py | 16 ++++---- pyrepl/commands.py | 35 ++++++++-------- pyrepl/completer.py | 2 +- pyrepl/completing_reader.py | 12 +++--- pyrepl/console.py | 6 +-- pyrepl/historical_reader.py | 33 ++++++--------- pyrepl/input.py | 2 +- pyrepl/keymap.py | 12 ++---- pyrepl/keymaps.py | 2 - pyrepl/pygame_console.py | 8 ++-- pyrepl/pygame_keymap.py | 12 +++--- pyrepl/python_reader.py | 55 +++++++++---------------- pyrepl/reader.py | 13 ++---- pyrepl/readline.py | 80 +++++++++++++------------------------ pyrepl/simple_interact.py | 6 +-- pyrepl/trace.py | 5 +-- pyrepl/unix_console.py | 13 +++--- pyrepl/unix_eventqueue.py | 10 +---- pythoni | 15 ++++--- pythoni1 | 8 ++-- tests/infrastructure.py | 8 ++-- tests/test_functional.py | 7 +--- tests/test_readline.py | 15 +++---- 24 files changed, 148 insertions(+), 237 deletions(-) diff --git a/pyrepl/_minimal_curses.py b/pyrepl/_minimal_curses.py index c31fa3e..65621d3 100644 --- a/pyrepl/_minimal_curses.py +++ b/pyrepl/_minimal_curses.py @@ -45,17 +45,15 @@ def _find_clib(): try: from __pypy__ import builtinify - - builtinify # silence broken pyflakes except ImportError: - builtinify = lambda f: f + def builtinify(f): + return f @builtinify def setupterm(termstr, fd): - if termstr is not None: - if not isinstance(termstr, bytes): - termstr = termstr.encode() + if termstr is not None and not isinstance(termstr, bytes): + termstr = termstr.encode() err = ctypes.c_int(0) result = clib.setupterm(termstr, fd, ctypes.byref(err)) if result == ERR: diff --git a/pyrepl/cmdrepl.py b/pyrepl/cmdrepl.py index a790f07..87acaab 100644 --- a/pyrepl/cmdrepl.py +++ b/pyrepl/cmdrepl.py @@ -42,13 +42,13 @@ class CmdReader(CR): def collect_keymap(self): - return super(CmdReader, self).collect_keymap() + ( + return super().collect_keymap() + ( ("\\M-\\n", "invalid-key"), ("\\n", "accept"), ) def __init__(self, completions): - super(CmdReader, self).__init__() + super().__init__() self.completions = completions def get_completions(self, stem): @@ -75,21 +75,21 @@ def replize(klass, history_across_invocations=1): # if klass.cmdloop.im_class is not cmd.Cmd: # print "this may not work" - class MultiHist(object): + class MultiHist: __history = [] def __init__(self, *args, **kw): - super(MultiHist, self).__init__(*args, **kw) + super().__init__(*args, **kw) self.__reader = CmdReader(completions) self.__reader.history = self.__history self.__reader.historyi = len(self.__history) - class SimpleHist(object): + class SimpleHist: def __init__(self, *args, **kw): - super(SimpleHist, self).__init__(*args, **kw) + super().__init__(*args, **kw) self.__reader = CmdReader(completions) - class CmdLoopMixin(object): + class CmdLoopMixin: def cmdloop(self, intro=None): self.preloop() if intro is not None: @@ -115,6 +115,6 @@ def cmdloop(self, intro=None): hist = MultiHist if history_across_invocations else SimpleHist class CmdRepl(hist, CmdLoopMixin, klass): - __name__ = "replize(%s.%s)" % (klass.__module__, klass.__name__) + __name__ = f"replize({klass.__module__}.{klass.__name__})" return CmdRepl diff --git a/pyrepl/commands.py b/pyrepl/commands.py index b4ce55f..ba7063b 100644 --- a/pyrepl/commands.py +++ b/pyrepl/commands.py @@ -20,7 +20,8 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import os -import sys + +from pyrepl import input # noqa: F401 # Catgories of actions: # killing @@ -32,7 +33,7 @@ # [completion] -class Command(object): +class Command: finish = 0 kills_digit_arg = 1 @@ -159,21 +160,21 @@ def do(self): class unix_word_rubout(KillCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): self.kill_range(r.bow(), r.pos) class kill_word(KillCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): self.kill_range(r.pos, r.eow()) class backward_kill_word(KillCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): self.kill_range(r.bow(), r.pos) @@ -232,7 +233,7 @@ def do(self): class up(MotionCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): bol1 = r.bol() if bol1 == 0: if r.historyi > 0: @@ -254,7 +255,7 @@ class down(MotionCommand): def do(self): r = self.reader b = r.buffer - for i in range(r.get_arg()): + for _i in range(r.get_arg()): bol1 = r.bol() eol1 = r.eol() if eol1 == len(b): @@ -275,7 +276,7 @@ def do(self): class left(MotionCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): p = r.pos - 1 if p >= 0: r.pos = p @@ -287,7 +288,7 @@ class right(MotionCommand): def do(self): r = self.reader b = r.buffer - for i in range(r.get_arg()): + for _i in range(r.get_arg()): p = r.pos + 1 if p <= len(b): r.pos = p @@ -302,7 +303,6 @@ def do(self): class end_of_line(MotionCommand): def do(self): - r = self.reader self.reader.pos = self.reader.eol() @@ -319,14 +319,14 @@ def do(self): class forward_word(MotionCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): r.pos = r.eow() class backward_word(MotionCommand): def do(self): r = self.reader - for i in range(r.get_arg()): + for _i in range(r.get_arg()): r.pos = r.bow() @@ -364,7 +364,7 @@ class backspace(EditCommand): def do(self): r = self.reader b = r.buffer - for i in range(r.get_arg()): + for _i in range(r.get_arg()): if r.pos > 0: r.pos -= 1 del b[r.pos] @@ -385,7 +385,7 @@ def do(self): r.update_screen() r.console.finish() raise EOFError - for i in range(r.get_arg()): + for _i in range(r.get_arg()): if r.pos != len(b): del b[r.pos] r.dirty = 1 @@ -423,15 +423,12 @@ def do(self): r = self.reader pending = r.console.getpending().data - disp = disp_str((self.event + pending))[0] + disp = disp_str(self.event + pending)[0] r.insert(disp * r.get_arg()) r.pop_input_trans() -from pyrepl import input - - -class QITrans(object): +class QITrans: def push(self, evt): self.evt = evt diff --git a/pyrepl/completer.py b/pyrepl/completer.py index 3c21c34..9a65d49 100644 --- a/pyrepl/completer.py +++ b/pyrepl/completer.py @@ -79,7 +79,7 @@ def attr_matches(self, text): n = len(attr) for word in words: if word[:n] == attr and word != "__builtins__": - matches.append("%s.%s" % (expr, word)) + matches.append(f"{expr}.{word}") return matches diff --git a/pyrepl/completing_reader.py b/pyrepl/completing_reader.py index 34ed675..aba3808 100644 --- a/pyrepl/completing_reader.py +++ b/pyrepl/completing_reader.py @@ -86,7 +86,7 @@ def build_menu(cons, wordlist, start, use_brackets, sort_in_column): i = start for r in range(rows): row = [] - for col in range(cols): + for _col in range(cols): row.append(item % left_align(wordlist[i], maxlen)) i += 1 if i >= len(wordlist): @@ -222,10 +222,10 @@ class CompletingReader(Reader): sort_in_column = False def collect_keymap(self): - return super(CompletingReader, self).collect_keymap() + ((r"\t", "complete"),) + return super().collect_keymap() + ((r"\t", "complete"),) def __init__(self, console): - super(CompletingReader, self).__init__(console) + super().__init__(console) self.cmpltn_menu = ["[ menu 1 ]", "[ menu 2 ]"] self.cmpltn_menu_vis = 0 self.cmpltn_menu_end = 0 @@ -234,12 +234,12 @@ def __init__(self, console): self.commands[c.__name__.replace("_", "-")] = c def after_command(self, cmd): - super(CompletingReader, self).after_command(cmd) + super().after_command(cmd) if not isinstance(cmd, (complete, self_insert)): self.cmpltn_reset() def calc_screen(self): - screen = super(CompletingReader, self).calc_screen() + screen = super().calc_screen() if self.cmpltn_menu_vis: ly = self.lxy[1] screen[ly:ly] = self.cmpltn_menu @@ -248,7 +248,7 @@ def calc_screen(self): return screen def finish(self): - super(CompletingReader, self).finish() + super().finish() self.cmpltn_reset() def cmpltn_reset(self): diff --git a/pyrepl/console.py b/pyrepl/console.py index 95bc78d..41617f2 100644 --- a/pyrepl/console.py +++ b/pyrepl/console.py @@ -18,7 +18,7 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -class Event(object): +class Event: """An Event. `evt' is 'key' or somesuch.""" __slots__ = "evt", "data", "raw" @@ -29,7 +29,7 @@ def __init__(self, evt, data, raw=""): self.raw = raw def __repr__(self): - return "Event(%r, %r)" % (self.evt, self.data) + return "Event({self.evt}, {self.data})" def __eq__(self, other): return ( @@ -37,7 +37,7 @@ def __eq__(self, other): ) -class Console(object): +class Console: """Attributes: screen, diff --git a/pyrepl/historical_reader.py b/pyrepl/historical_reader.py index 1ea436c..97bae94 100644 --- a/pyrepl/historical_reader.py +++ b/pyrepl/historical_reader.py @@ -43,7 +43,7 @@ ) if "c" in globals(): - del c + del c # noqa: F821 ISEARCH_DIRECTION_NONE = "" ISEARCH_DIRECTION_BACKWARDS = "r" @@ -71,11 +71,10 @@ def do(self): class restore_history(commands.Command): def do(self): r = self.reader - if r.historyi != len(r.history): - if r.get_unicode() != r.history[r.historyi]: - r.buffer = list(r.history[r.historyi]) - r.pos = len(r.buffer) - r.dirty = 1 + if r.historyi != len(r.history) and r.get_unicode() != r.history[r.historyi]: + r.buffer = list(r.history[r.historyi]) + r.pos = len(r.buffer) + r.dirty = 1 class first_history(commands.Command): @@ -111,10 +110,7 @@ def do(self): return w = words[a] b = r.buffer - if r.yank_arg_i > 0: - o = len(r.yank_arg_yanked) - else: - o = 0 + o = len(r.yank_arg_yanked) if r.yank_arg_i > 0 else 0 b[r.pos - o : r.pos] = list(w) r.yank_arg_yanked = w r.pos += len(w) - o @@ -212,7 +208,7 @@ class HistoricalReader(R): """ def collect_keymap(self): - return super(HistoricalReader, self).collect_keymap() + ( + return super().collect_keymap() + ( (r"\C-n", "next-history"), (r"\C-p", "previous-history"), (r"\C-o", "operate-and-get-next"), @@ -225,7 +221,7 @@ def collect_keymap(self): ) def __init__(self, console): - super(HistoricalReader, self).__init__(console) + super().__init__(console) self.history = [] self.historyi = 0 self.transient_history = {} @@ -274,7 +270,7 @@ def get_item(self, i): return self.transient_history.get(i, self.get_unicode()) def prepare(self): - super(HistoricalReader, self).prepare() + super().prepare() try: self.transient_history = {} if self.next_history is not None and self.next_history < len(self.history): @@ -292,9 +288,9 @@ def prepare(self): def get_prompt(self, lineno, cursor_on_line): if cursor_on_line and self.isearch_direction != ISEARCH_DIRECTION_NONE: d = "rf"[self.isearch_direction == ISEARCH_DIRECTION_FORWARDS] - return "(%s-search `%s') " % (d, self.isearch_term) + return f"({d}-search `{self.isearch_term}') " else: - return super(HistoricalReader, self).get_prompt(lineno, cursor_on_line) + return super().get_prompt(lineno, cursor_on_line) def isearch_next(self): st = self.isearch_term @@ -303,10 +299,7 @@ def isearch_next(self): s = self.get_unicode() forwards = self.isearch_direction == ISEARCH_DIRECTION_FORWARDS while 1: - if forwards: - p = s.find(st, p + 1) - else: - p = s.rfind(st, 0, p + len(st) - 1) + p = s.find(st, p + 1) if forwards else s.rfind(st, 0, p + len(st) - 1) if p != -1: self.select_item(i) self.pos = p @@ -325,7 +318,7 @@ def isearch_next(self): p = len(s) def finish(self): - super(HistoricalReader, self).finish() + super().finish() ret = self.get_unicode() for i, t in list(self.transient_history.items()): if i < len(self.history) and i != self.historyi: diff --git a/pyrepl/input.py b/pyrepl/input.py index 5180c5f..16de45b 100644 --- a/pyrepl/input.py +++ b/pyrepl/input.py @@ -40,7 +40,7 @@ from .trace import trace -class InputTranslator(object): +class InputTranslator: def push(self, evt): pass diff --git a/pyrepl/keymap.py b/pyrepl/keymap.py index e13c929..85f701e 100644 --- a/pyrepl/keymap.py +++ b/pyrepl/keymap.py @@ -182,10 +182,7 @@ def _parse_key1(key, s): if len(ret) > 1: raise KeySpecError("\\C- must be followed by a character") ret = chr(ord(ret) & 0x1F) # curses.ascii.ctrl() - if meta: - ret = ["\033", ret] - else: - ret = [ret] + ret = ["\x1b", ret] if meta else [ret] return ret, s @@ -201,16 +198,13 @@ def parse_keys(key): def compile_keymap(keymap, empty=b""): r = {} for key, value in list(keymap.items()): - if isinstance(key, bytes): - first = key[:1] - else: - first = key[0] + first = key[:1] if isinstance(key, bytes) else key[0] r.setdefault(first, {})[key[1:]] = value for key, value in list(r.items()): if empty in value: if len(value) != 1: raise KeySpecError( - "key definitions for %s clash" % (list(value.values()),) + f"key definitions for {list(value.values())} clash" ) else: r[key] = value[empty] diff --git a/pyrepl/keymaps.py b/pyrepl/keymaps.py index e9294e0..98bdf00 100644 --- a/pyrepl/keymaps.py +++ b/pyrepl/keymaps.py @@ -134,5 +134,3 @@ "vi-insert": reader_vi_insert_keymap, "vi-command": reader_vi_command_keymap, } - -del c # from the listcomps diff --git a/pyrepl/pygame_console.py b/pyrepl/pygame_console.py index 50febbb..846c340 100644 --- a/pyrepl/pygame_console.py +++ b/pyrepl/pygame_console.py @@ -25,7 +25,7 @@ # during command execution and zap the executor process. Making this # work on non-Unix is expected to be even more entertaining. -import types +# ruff: noqa: F405, F403 import pygame from pygame.locals import * @@ -226,7 +226,7 @@ def getheightwidth(self): ) def tr_event(self, pyg_event): - shift = bool(pyg_event.mod & KMOD_SHIFT) + bool(pyg_event.mod & KMOD_SHIFT) ctrl = bool(pyg_event.mod & KMOD_CTRL) meta = bool(pyg_event.mod & (KMOD_ALT | KMOD_META)) @@ -326,8 +326,8 @@ def repaint(self): # perhaps we should consolidate grobs? self.pygame_screen.fill(colors.bg) self.paint_margin() - for (y, x), surf, text in self.grobs: - if surf and 0 < y + self.scroll: + for (y, x), surf, _text in self.grobs: + if surf and y + self.scroll > 0: self.pygame_screen.blit(surf, (lmargin + x, tmargin + y + self.scroll)) pygame.display.update() diff --git a/pyrepl/pygame_keymap.py b/pyrepl/pygame_keymap.py index f74d1bd..8d1d049 100644 --- a/pyrepl/pygame_keymap.py +++ b/pyrepl/pygame_keymap.py @@ -36,6 +36,8 @@ # XXX it's actually possible to test this module, so it should have a # XXX test suite. +# ruff: noqa: F405, F403 + from pygame.locals import * _escapes = { @@ -186,7 +188,7 @@ def _compile_keymap(keymap): if () in value: if len(value) != 1: raise KeySpecError( - "key definitions for %s clash" % (list(value.values()),) + f"key definitions for {list(value.values())} clash" ) else: r[key] = value[()] @@ -242,11 +244,11 @@ def unparse_key(keyseq): elif c in _unescapes: p = _unescapes[c] elif ord(c) < ord(" "): - p = "\\C-%s" % (chr(ord(c) + 96),) + p = f"\\C-{chr(ord(c) + 96)}" elif ord(" ") <= ord(c) <= ord("~"): p = c else: - p = "\\%03o" % (ord(c),) + p = f"\\{ord(c):03o}" return p + unparse_key(r) @@ -268,11 +270,11 @@ def _unparse_keyf(keyseq): elif c in _unescapes: p = _unescapes[c] elif ord(c) < ord(" "): - p = "C-%s" % (chr(ord(c) + 96),) + p = f"C-{chr(ord(c) + 96)}" elif ord(" ") <= ord(c) <= ord("~"): p = c else: - p = "\\%03o" % (ord(c),) + p = f"\\{ord(c):03o}" return [p] + _unparse_keyf(r) diff --git a/pyrepl/python_reader.py b/pyrepl/python_reader.py index 73285db..8072313 100644 --- a/pyrepl/python_reader.py +++ b/pyrepl/python_reader.py @@ -31,16 +31,10 @@ import traceback import warnings -from pyrepl import (commands, completer, completing_reader, module_lister, - reader) +from pyrepl import commands, completer, completing_reader, module_lister, reader from pyrepl.completing_reader import CompletingReader from pyrepl.historical_reader import HistoricalReader -try: - str -except: - str = str - try: imp.find_module("twisted") except ImportError: @@ -56,21 +50,10 @@ def eat_it(*args): pass -if sys.version_info >= (3, 0): - - def _reraise(cls, val, tb): - __tracebackhide__ = True - assert hasattr(val, "__traceback__") - raise val - -else: - exec( - """ def _reraise(cls, val, tb): __tracebackhide__ = True - raise cls, val, tb -""" - ) + assert hasattr(val, "__traceback__") + raise val class maybe_accept(commands.Command): @@ -101,20 +84,20 @@ def saver(reader=reader): fp.write( b"\n".join(item.encode("unicode_escape") for item in reader.history) ) - except IOError as e: + except OSError as e: print(e) pass class PythonicReader(CompletingReader, HistoricalReader): def collect_keymap(self): - return super(PythonicReader, self).collect_keymap() + ( + return super().collect_keymap() + ( (r"\n", "maybe-accept"), (r"\M-\n", "insert-nl"), ) def __init__(self, console, locals, compiler=None): - super(PythonicReader, self).__init__(console) + super().__init__(console) self.completer = completer.Completer(locals) st = self.syntax_table for c in "._0123456789": @@ -124,18 +107,17 @@ def __init__(self, console, locals, compiler=None): self.compiler = CommandCompiler() else: self.compiler = compiler + try: - file = open(os.path.expanduser("~/.pythoni.hist"), "rb") - except IOError: + with open(os.path.expanduser("~/.pythoni.hist"), "rb") as fh: + lines = fh.readlines() + self.history = [ + line.rstrip(b"\n").decode("unicode_escape") for line in lines + ] + except FileNotFoundError: self.history = [] - else: - try: - lines = file.readlines() - self.history = [x.rstrip(b"\n").decode("unicode_escape") for x in lines] - except: - self.history = [] - self.historyi = len(self.history) - file.close() + self.historyi = len(self.history) + atexit.register(lambda: saver(self)) for c in [maybe_accept]: self.commands[c.__name__] = c @@ -194,7 +176,7 @@ def run_user_init_file(self): else: return try: - with open(initfile, "r") as f: + with open(initfile) as f: exec(compile(f.read(), initfile, "exec"), self.locals, self.locals) except: etype, value, tb = sys.exc_info() @@ -381,9 +363,8 @@ def main( ): si, se, so = sys.stdin, sys.stderr, sys.stdout try: - if 0 and use_pygame_console: # pygame currently borked - from pyrepl.pygame_console import (FakeStdin, FakeStdout, - PyGameConsole) + if False: # pygame currently borked + from pyrepl.pygame_console import FakeStdin, FakeStdout, PyGameConsole con = PyGameConsole() sys.stderr = sys.stdout = FakeStdout(con) diff --git a/pyrepl/reader.py b/pyrepl/reader.py index c79ba66..3812278 100644 --- a/pyrepl/reader.py +++ b/pyrepl/reader.py @@ -168,11 +168,7 @@ def make_default_syntax_table(): ] ) -if "c" in globals(): # only on python 2.x - del c # from the listcomps - - -class Reader(object): +class Reader: """The Reader class implements the bare bones of a command reader, handling such details as editing and cursor motion. What it does not support are such things as completion or history support - @@ -576,10 +572,7 @@ def handle1(self, block=1): else: translate = False - if translate: - cmd = self.input_trans.get() - else: - cmd = event.evt, event.data + cmd = self.input_trans.get() if translate else (event.evt, event.data) if cmd is None: if block: @@ -624,7 +617,7 @@ def get_buffer(self, encoding=None): def get_unicode(self): """Return the current buffer as a unicode string.""" - return str("").join(self.buffer) + return "".join(self.buffer) def test(): diff --git a/pyrepl/readline.py b/pyrepl/readline.py index a4869df..23ba864 100644 --- a/pyrepl/readline.py +++ b/pyrepl/readline.py @@ -26,6 +26,7 @@ extensions for multiline input. """ +import contextlib import os import sys @@ -67,7 +68,7 @@ # ____________________________________________________________ -class ReadlineConfig(object): +class ReadlineConfig: readline_completer = None completer_delims = dict.fromkeys(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?") @@ -135,17 +136,15 @@ def get_trimmed_history(self, maxlength): more_lines = None def collect_keymap(self): - return super(ReadlineAlikeReader, self).collect_keymap() + ( - (r"\n", "maybe-accept"), - ) + return super().collect_keymap() + ((r"\n", "maybe-accept"),) def __init__(self, console): - super(ReadlineAlikeReader, self).__init__(console) + super().__init__(console) self.commands["maybe_accept"] = maybe_accept self.commands["maybe-accept"] = maybe_accept def after_command(self, cmd): - super(ReadlineAlikeReader, self).after_command(cmd) + super().after_command(cmd) if self.more_lines is None: # Force single-line input if we are in raw_input() mode. # Although there is no direct way to add a \n in this mode, @@ -177,7 +176,7 @@ def do(self): self.finish = 1 -class _ReadlineWrapper(object): +class _ReadlineWrapper: reader = None saved_history_length = -1 startup_hook = None @@ -202,7 +201,7 @@ def get_reader(self): self.reader.config = self.config return self.reader - def raw_input(self, prompt=""): + def raw_input(self, prompt="") -> str: try: reader = self.get_reader() except _error: @@ -220,11 +219,7 @@ def raw_input(self, prompt=""): self.stderr.flush() ret = reader.readline(startup_hook=self.startup_hook) - if not PY3: - return ret - # Unicode/str is required for Python 3 (3.5.2). - # Ref: https://bitbucket.org/pypy/pyrepl/issues/20/#comment-30647029 return str(ret, ENCODING) def multiline_input(self, more_lines, ps1, ps2, returns_unicode=False): @@ -259,15 +254,8 @@ def get_completer_delims(self): chars.sort() return "".join(chars) - def _histline(self, line): - line = line.rstrip("\n") - if PY3: - return line - - try: - return str(line, ENCODING) - except UnicodeDecodeError: # bah, silently fall back... - return str(line, "utf-8", "replace") + def _histline(self, line: str): + return line.rstrip("\n") def get_history_length(self): return self.saved_history_length @@ -284,39 +272,30 @@ 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)) as f: + 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) def write_history_file(self, filename="~/.history"): maxlength = self.saved_history_length history = self.get_reader().get_trimmed_history(maxlength) entries = "" for entry in history: - # if we are on py3k, we don't need to encode strings before - # writing it to a file - if isinstance(entry, str) and sys.version_info < (3,): - entry = entry.encode("utf-8") entry = entry.replace("\n", "\r\n") # multiline history support entries += entry + "\n" fname = os.path.expanduser(filename) - if PY3: - f = open(fname, "w", encoding="utf-8") - else: - f = open(fname, "w") - f.write(entries) - f.close() + with open(fname, "w", encoding="utf-8") as f: + f.write(entries) def clear_history(self): del self.get_reader().history[:] @@ -325,8 +304,8 @@ def get_history_item(self, index): history = self.get_reader().history if 1 <= index <= len(history): return history[index - 1] - else: - return None # blame readline.c for not raising + + return None # blame readline.c for not raising def remove_history_item(self, index): history = self.get_reader().history @@ -351,9 +330,7 @@ def set_startup_hook(self, function=None): self.startup_hook = function def get_line_buffer(self): - if PY3: - return self.get_reader().get_unicode() - return self.get_reader().get_buffer() + return self.get_reader().get_unicode() def _get_idxs(self): start = cursor = self.get_reader().pos @@ -430,6 +407,7 @@ def stub(*args, **kwds): def _setup(): + # TODO: is the raw_input logic still required? global _old_raw_input if _old_raw_input is not None: return @@ -455,10 +433,8 @@ def _old_raw_input(prompt=""): # should not really fail in _wrapper.raw_input(). If it still # does, then we will just cancel the redirection and call again # the built-in raw_input(). - try: + with contextlib.suppress(AttributeError): del sys.__raw_input__ - except AttributeError: - pass return input(prompt) sys.__raw_input__ = _wrapper.raw_input diff --git a/pyrepl/simple_interact.py b/pyrepl/simple_interact.py index bb3e1ce..068c411 100644 --- a/pyrepl/simple_interact.py +++ b/pyrepl/simple_interact.py @@ -47,11 +47,7 @@ def run_multiline_interactive_console(mainmodule=None, future_flags=0): console.compile.compiler.flags |= future_flags def more_lines(unicodetext): - if sys.version_info < (3,): - # ooh, look at the hack: - src = "#coding:utf-8\n" + unicodetext.encode("utf-8") - else: - src = unicodetext + src = unicodetext try: code = console.compile(src, "", "single") except (OverflowError, SyntaxError, ValueError): diff --git a/pyrepl/trace.py b/pyrepl/trace.py index f141660..5c95724 100644 --- a/pyrepl/trace.py +++ b/pyrepl/trace.py @@ -2,10 +2,7 @@ trace_filename = os.environ.get("PYREPL_TRACE") -if trace_filename is not None: - trace_file = open(trace_filename, "a") -else: - trace_file = None +trace_file = open(trace_filename, "a") if trace_filename is not None else None def trace(line, *k, **kw): diff --git a/pyrepl/unix_console.py b/pyrepl/unix_console.py index b7fb3e6..b87a6c5 100644 --- a/pyrepl/unix_console.py +++ b/pyrepl/unix_console.py @@ -19,6 +19,7 @@ # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import contextlib import errno import os import re @@ -157,7 +158,7 @@ def __init__(self, f_in=0, f_out=1, term=None, encoding=None): ## work out how we're going to sling the cursor around # hpa don't work in windows telnet :-( - if 0 and self._hpa: + if False: self.__move_x = self.__move_x_hpa elif self._cub and self._cuf: self.__move_x = self.__move_x_cub_cuf @@ -232,7 +233,7 @@ def refresh(self, screen, c_xy): self.__hide_cursor() self.__write_code(self._cup, 0, 0) self.__posxy = 0, old_offset - for i in range(old_offset - offset): + for _ in range(old_offset - offset): self.__write_code(self._ri) oldscr.pop(-1) oldscr.insert(0, "") @@ -240,7 +241,7 @@ def refresh(self, screen, c_xy): self.__hide_cursor() self.__write_code(self._cup, self.height - 1, 0) self.__posxy = 0, old_offset + self.height - 1 - for i in range(offset - old_offset): + for _ in range(offset - old_offset): self.__write_code(self._ind) oldscr.pop(0) oldscr.append("") @@ -413,10 +414,8 @@ def prepare(self): self.__maybe_write_code(self._smkx) - try: + with contextlib.suppress(ValueError): self.old_sigwinch = signal.signal(signal.SIGWINCH, self.__sigwinch) - except ValueError: - pass def restore(self): self.__maybe_write_code(self._rmkx) @@ -447,7 +446,7 @@ def get_event(self, block=1): # All hail Unix! try: self.push_char(os.read(self.input_fd, 1)) - except (IOError, OSError) as err: + except OSError as err: if err.errno == errno.EINTR: if not self.event_queue.empty(): return self.event_queue.get() diff --git a/pyrepl/unix_eventqueue.py b/pyrepl/unix_eventqueue.py index 9f3356f..39e81b8 100644 --- a/pyrepl/unix_eventqueue.py +++ b/pyrepl/unix_eventqueue.py @@ -30,12 +30,6 @@ from .trace import trace -try: - str -except NameError: - str = str - - _keynames = { "delete": "kdch1", "down": "kcud1", @@ -89,13 +83,13 @@ def EventQueue(fd, encoding): keycodes = general_keycodes() if os.isatty(fd): backspace = tcgetattr(fd)[6][VERASE] - keycodes[backspace] = str("backspace") + keycodes[backspace] = "backspace" k = keymap.compile_keymap(keycodes) trace("keymap {k!r}", k=k) return EncodedQueue(k, encoding) -class EncodedQueue(object): +class EncodedQueue: def __init__(self, keymap, encoding): self.k = self.ck = keymap self.events = deque() diff --git a/pythoni b/pythoni index 4c11eba..2d95ea1 100755 --- a/pythoni +++ b/pythoni @@ -19,18 +19,21 @@ # CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -import locale, pdb, sys +import locale +import pdb +import sys + # I forget exactly why this is necessary: try: - locale.setlocale(locale.LC_ALL, '') + locale.setlocale(locale.LC_ALL, "") except locale.Error: - pass # oh well + pass # oh well -from pyrepl.python_reader import main from pyrepl import cmdrepl +from pyrepl.python_reader import main # whizzy feature: graft pyrepl support onto pdb -#pdb.Pdb = cmdrepl.replize(pdb.Pdb, 1) +# pdb.Pdb = cmdrepl.replize(pdb.Pdb, 1) -main(use_pygame_console=('pg' in sys.argv)) +main(use_pygame_console=("pg" in sys.argv)) diff --git a/pythoni1 b/pythoni1 index ee5f289..4dde86e 100755 --- a/pythoni1 +++ b/pythoni1 @@ -10,10 +10,10 @@ import sys from pyrepl import readline from pyrepl.simple_interact import run_multiline_interactive_console -sys.modules['readline'] = readline +sys.modules["readline"] = readline -if os.getenv('PYTHONSTARTUP'): - exec(open(os.getenv('PYTHONSTARTUP')).read()) +if os.getenv("PYTHONSTARTUP"): + exec(open(os.getenv("PYTHONSTARTUP")).read()) -print('Python', sys.version) +print("Python", sys.version) run_multiline_interactive_console() diff --git a/tests/infrastructure.py b/tests/infrastructure.py index 2a7016e..7557538 100644 --- a/tests/infrastructure.py +++ b/tests/infrastructure.py @@ -22,7 +22,7 @@ from pyrepl.reader import Reader -class EqualsAnything(object): +class EqualsAnything: def __eq__(self, other): return True @@ -42,10 +42,8 @@ def __init__(self, events, verbose=False): def refresh(self, screen, xy): if self.next_screen is not None: - assert screen == self.next_screen, "[ %s != %s after %r ]" % ( - screen, - self.next_screen, - self.last_event_name, + assert screen == self.next_screen, ( + f"[ {screen} != {self.next_screen}" "after {self.last_event_name} ]" ) def get_event(self, block=1): diff --git a/tests/test_functional.py b/tests/test_functional.py index a599316..bb01ea9 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -13,7 +13,7 @@ try: import pexpect except ImportError as exc: - pytest.skip("could not import pexpect: {}".format(exc), allow_module_level=True) + pytest.skip(f"could not import pexpect: {exc}", allow_module_level=True) @pytest.fixture @@ -27,10 +27,7 @@ def start_child_func(env_update=None): if env_update: env.update(env_update) child = pexpect.spawn(sys.executable, timeout=5, env=env) - if sys.version_info >= (3,): - child.logfile = sys.stdout.buffer - else: - child.logfile = sys.stdout + child.logfile = sys.stdout.buffer child.expect_exact(">>> ") child.sendline("from pyrepl.python_reader import main") ret_childs.append(child) diff --git a/tests/test_readline.py b/tests/test_readline.py index 6cf4a38..16b8411 100644 --- a/tests/test_readline.py +++ b/tests/test_readline.py @@ -1,6 +1,5 @@ import os import pty -import sys import pytest from pyrepl.readline import _ReadlineWrapper @@ -38,12 +37,8 @@ def test_raw_input(): os.write(master, b"input\n") result = readline_wrapper.raw_input("prompt:") - if sys.version_info < (3,): - assert result == b"input" - assert isinstance(result, bytes) - else: - assert result == "input" - assert isinstance(result, str) + assert result == "input" + assert isinstance(result, str) def test_read_history_file(readline_wrapper, tmp_path): @@ -70,7 +65,7 @@ def test_write_history_file(readline_wrapper, tmp_path): readline_wrapper.write_history_file(str(histfile)) - with open(str(histfile), "r") as f: + with open(str(histfile)) as f: assert f.readlines() == ["foo\n", "bar\n"] @@ -84,7 +79,7 @@ def test_write_history_file_with_exception(readline_wrapper, tmp_path): class BadEntryException(Exception): pass - class BadEntry(object): + class BadEntry: @classmethod def replace(cls, *args): raise BadEntryException @@ -95,5 +90,5 @@ def replace(cls, *args): with pytest.raises(BadEntryException): readline_wrapper.write_history_file(str(histfile)) - with open(str(histfile), "r") as f: + with open(str(histfile)) as f: assert f.readlines() == ["foo\n", "bar\n"]