diff --git a/share/tools/deroff.py b/share/tools/deroff.py index 7178adc27..1f7017901 100755 --- a/share/tools/deroff.py +++ b/share/tools/deroff.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -""" Deroff.py, ported to Python from the venerable deroff.c """ +"""Deroff.py, ported to Python from the venerable deroff.c""" import sys, re, string diff --git a/tests/littlecheck.py b/tests/littlecheck.py index 5ae44c667..8c025e20b 100755 --- a/tests/littlecheck.py +++ b/tests/littlecheck.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -""" Command line test driver. """ +"""Command line test driver.""" from __future__ import unicode_literals from __future__ import print_function @@ -36,6 +36,7 @@ VARIABLE_OVERRIDE_RE = re.compile(r"\w+=.*") SKIP = object() + def find_command(program): import os @@ -49,6 +50,7 @@ def find_command(program): return None + class Config(object): def __init__(self): # Whether to have verbose output. @@ -59,7 +61,7 @@ class Config(object): self.progress = False def colors(self): - """ Return a dictionary mapping color names to ANSI escapes """ + """Return a dictionary mapping color names to ANSI escapes""" def ansic(n): return "\033[%dm" % n if self.colorize else "" @@ -130,7 +132,7 @@ class CheckerError(Exception): class Line(object): - """ A line that remembers where it came from. """ + """A line that remembers where it came from.""" def __init__(self, text, number, file): self.text = text @@ -158,7 +160,7 @@ class Line(object): raise NotImplementedError def subline(self, text): - """ Return a substring of our line with the given text, preserving number and file. """ + """Return a substring of our line with the given text, preserving number and file.""" return Line(text, self.number, self.file) @staticmethod @@ -230,7 +232,7 @@ class TestFailure(object): if self.signal: fmtstrs += [ " Process was killed by signal {BOLD}" + self.signal + "{RESET}", - "" + "", ] if self.line and self.check: fmtstrs += [ @@ -351,7 +353,7 @@ class TestFailure(object): return "\n".join(fmtstrs).format(**fields) def print_message(self): - """ Print our message to stdout. """ + """Print our message to stdout.""" print(self.message()) @@ -381,7 +383,7 @@ def perform_substitution(input_str, subs): def runproc(cmd): - """ Wrapper around subprocess.Popen to save typing """ + """Wrapper around subprocess.Popen to save typing""" PIPE = subprocess.PIPE proc = subprocess.Popen( cmd, @@ -446,7 +448,7 @@ class TestRun(object): # SCREENFULS of text. # So we truncate the check list. if len(usedchecks) > len(usedlines): - usedchecks = usedchecks[:len(usedlines) + 5] + usedchecks = usedchecks[: len(usedlines) + 5] # Do a SequenceMatch! This gives us a diff-like thing. diff = SequenceMatcher(a=usedlines, b=usedchecks, autojunk=False) @@ -474,13 +476,16 @@ class TestRun(object): return None def run(self): - """ Run the command. Return a TestFailure, or None. """ + """Run the command. Return a TestFailure, or None.""" def split_by_newlines(s): """Decode a string and split it by newlines only, retaining the newlines. """ - return [s + "\n" for s in s.decode("utf-8", errors="backslashreplace").split("\n")] + return [ + s + "\n" + for s in s.decode("utf-8", errors="backslashreplace").split("\n") + ] if self.config.verbose: print(self.subbed_command) @@ -491,7 +496,13 @@ class TestRun(object): # most likely when the last command in a shell script doesn't exist. # So we check if the command *we execute* exists, and complain then. status = proc.returncode - cmd = next((word for word in shlex.split(self.subbed_command) if not VARIABLE_OVERRIDE_RE.match(word))) + cmd = next( + ( + word + for word in shlex.split(self.subbed_command) + if not VARIABLE_OVERRIDE_RE.match(word) + ) + ) if status == 127 and not find_command(cmd): raise CheckerError("Command could not be found: " + cmd) if status == 126 and not find_command(cmd): @@ -522,6 +533,7 @@ class TestRun(object): # Process was killed by a signal and failed, # add a message. import signal + # Unfortunately strsignal only exists in python 3.8+, # and signal.signals is 3.5+. if hasattr(signal, "Signals"): @@ -624,6 +636,7 @@ class CheckCmd(object): class Checker(object): def __init__(self, name, lines): self.name = name + # Helper to yield subline containing group1 from all matching lines. def group1s(regex): for line in lines: @@ -656,7 +669,7 @@ class Checker(object): def check_file(input_file, name, subs, config, failure_handler): - """ Check a single file. Return a True on success, False on error. """ + """Check a single file. Return a True on success, False on error.""" success = True lines = Line.readfile(input_file, name) checker = Checker(name, lines) @@ -664,9 +677,7 @@ def check_file(input_file, name, subs, config, failure_handler): # Run all the REQUIRES lines first, # if any of them fail it's a SKIP for reqcmd in checker.requirecmds: - proc = runproc( - perform_substitution(reqcmd.args, subs) - ) + proc = runproc(perform_substitution(reqcmd.args, subs)) proc.communicate() if proc.returncode > 0: return SKIP @@ -710,7 +721,7 @@ def parse_subs(subs): def get_argparse(): - """ Return a littlecheck argument parser. """ + """Return a littlecheck argument parser.""" parser = argparse.ArgumentParser( description="littlecheck: command line tool tester." ) diff --git a/tests/pexpect_helper.py b/tests/pexpect_helper.py index 85c0bab6c..5a8e4f3f4 100644 --- a/tests/pexpect_helper.py +++ b/tests/pexpect_helper.py @@ -43,7 +43,8 @@ SANITIZE_FOR_PRINTING_RE = re.compile( | \x1b> | \x1b\].*?\x07 """, - re.VERBOSE) + re.VERBOSE, +) def get_prompt_re(counter): @@ -129,10 +130,12 @@ class Message(object): """Return a output message with the given text.""" return Message(Message.DIR_OUTPUT, text, when) + # Sequences for moving the cursor below the commandline. This happens before executing. MOVE_TO_END: str = r"(?:\r\n|\x1b\[2 q|)" -TO_END: str = MOVE_TO_END + r"[^\n]*" -TO_END_SUFFIX: str = r"[^\n]*" + MOVE_TO_END +TO_END: str = MOVE_TO_END + r"[^\n]*" +TO_END_SUFFIX: str = r"[^\n]*" + MOVE_TO_END + class SpawnedProc(object): """A process, talking to our ptty. This wraps pexpect.spawn. @@ -160,6 +163,7 @@ class SpawnedProc(object): env: a string->string dictionary, describing the environment variables. """ import shlex + if name not in env: raise ValueError("'%s' variable not found in environment" % name) exe_path = env.get(name) @@ -176,7 +180,7 @@ class SpawnedProc(object): self.spawn.delaybeforesend = None self.prompt_counter = 0 if env.get("TERM") != "dumb": - self.spawn.send('\x1b[?123c') # Primary Device Attribute + self.spawn.send("\x1b[?123c") # Primary Device Attribute def time_since_first_message(self): """Return a delta in seconds since the first message, or 0 if this is the first.""" @@ -270,7 +274,11 @@ class SpawnedProc(object): failtype = pexpect_error_type(err) # If we get an EOF, we check if the process exited with a signal. # This shows us e.g. if it crashed - if failtype == 'EOF' and self.spawn.signalstatus is not None and self.spawn.signalstatus != 0: + if ( + failtype == "EOF" + and self.spawn.signalstatus is not None + and self.spawn.signalstatus != 0 + ): failtype = "SIGNAL " + Signals(self.spawn.signalstatus).name fmtkeys = {"failtype": failtype, "pat": escape(pat)} @@ -300,12 +308,14 @@ class SpawnedProc(object): print("") print("{CYAN}When written to the tty, this looks like:{RESET}".format(**colors)) print("{CYAN}<-------{RESET}".format(**colors)) - sys.stdout.write(SANITIZE_FOR_PRINTING_RE.sub('', self.spawn.before)) + sys.stdout.write(SANITIZE_FOR_PRINTING_RE.sub("", self.spawn.before)) sys.stdout.flush() - maybe_nl="" + maybe_nl = "" if not self.spawn.before.endswith("\n"): - maybe_nl="\n{CYAN}(no trailing newline)".format(**colors) - print("{RESET}{maybe_nl}{CYAN}------->{RESET}".format(maybe_nl=maybe_nl, **colors)) + maybe_nl = "\n{CYAN}(no trailing newline)".format(**colors) + print( + "{RESET}{maybe_nl}{CYAN}------->{RESET}".format(maybe_nl=maybe_nl, **colors) + ) print("") @@ -372,22 +382,24 @@ class SpawnedProc(object): def control(char: str) -> str: - """ Returns the char sent when control is pressed along the given key. """ + """Returns the char sent when control is pressed along the given key.""" assert len(char) == 1 char = char.lower() if ord("a") <= ord(char) <= ord("z"): return chr(ord(char) - ord("a") + 1) - return chr({ - "@": 0, - "`": 0, - "[": 27, - "{": 27, - "\\": 28, - "|": 28, - "]": 29, - "}": 29, - "^": 30, - "~": 30, - "_": 31, - "?": 127, - }[char]) + return chr( + { + "@": 0, + "`": 0, + "[": 27, + "{": 27, + "\\": 28, + "|": 28, + "]": 29, + "}": 29, + "^": 30, + "~": 30, + "_": 31, + "?": 127, + }[char] + ) diff --git a/tests/pexpects/abbrs.py b/tests/pexpects/abbrs.py index c3f9131ee..fdd91f232 100644 --- a/tests/pexpects/abbrs.py +++ b/tests/pexpects/abbrs.py @@ -168,16 +168,19 @@ sendline(r"""true; and builtin echo foo """) expect_prompt("bar") sendline(r"""abbr fruit --command={git,hg,svn} banana""") expect_prompt() -sendline(r"""function git; echo git $argv; end; function hg; echo hg $argv; end; function svn; echo svn $argv; end""") +sendline( + r"""function git; echo git $argv; end; function hg; echo hg $argv; end; function svn; echo svn $argv; end""" +) expect_prompt() sendline(r"""git fruit""") expect_prompt("git banana") sendline(r"""abbr""") -expect_prompt("abbr -a --position anywhere --command git --command hg --command svn -- fruit banana") +expect_prompt( + "abbr -a --position anywhere --command git --command hg --command svn -- fruit banana" +) sendline(r"""function banana; echo I am a banana; end""") expect_prompt() sendline(r"""abbr fruit --command={git,hg,svn,} banana""") expect_prompt() sendline(r"""fruit foo""") expect_prompt("I am a banana") - diff --git a/tests/pexpects/bind.py b/tests/pexpects/bind.py index c8169c1e5..456fae6cf 100644 --- a/tests/pexpects/bind.py +++ b/tests/pexpects/bind.py @@ -44,7 +44,9 @@ expect_prompt("") # Start by testing with no delay. This should transpose the words. send("echo abc def") send("\033t\r") -expect_prompt(TO_END + "def abc\r\n") # emacs transpose words, default timeout: no delay +expect_prompt( + TO_END + "def abc\r\n" +) # emacs transpose words, default timeout: no delay # Now test with a delay > 0 and < the escape timeout. This should transpose # the words. @@ -76,7 +78,8 @@ expect_prompt() # Go through a prompt cycle to let fish catch up, it may be slow due to ASAN sendline("echo success: default escape timeout") expect_prompt( - TO_END + "success: default escape timeout", unmatched="prime vi mode, default timeout" + TO_END + "success: default escape timeout", + unmatched="prime vi mode, default timeout", ) send("echo fail: default escape timeout") @@ -284,7 +287,8 @@ send("echo abc def") send("\033") send("t\r") expect_prompt( - TO_END + "def abc\r\n", unmatched="emacs transpose words fail, 200ms timeout: no delay" + TO_END + "def abc\r\n", + unmatched="emacs transpose words fail, 200ms timeout: no delay", ) # Verify special characters, such as \cV, are not intercepted by the kernel @@ -364,23 +368,24 @@ expect_prompt(TO_END + "b c d") # Check that ctrl-z can be bound sendline('bind ctrl-z "echo bound ctrl-z"') expect_prompt() -send("\x1A") +send("\x1a") expect_str("bound ctrl-z") -send('echo foobar') -send('\x02\x02\x02') # ctrl-b, backward-char -sendline('\x1bu') # alt+u, upcase word +send("echo foobar") +send("\x02\x02\x02") # ctrl-b, backward-char +sendline("\x1bu") # alt+u, upcase word expect_prompt("fooBAR") -sendline('bind ctrl-z history-prefix-search-backward') +sendline("bind ctrl-z history-prefix-search-backward") expect_prompt() sendline("echo this continues") expect_prompt() -send("\x1A") +send("\x1a") sendline(" with this text") expect_prompt("this continues with this text") -sendline(""" +sendline( + """ bind ctrl-g " commandline --insert 'echo foo ar' commandline -f backward-word @@ -389,10 +394,11 @@ sendline(""" commandline -f backward-char commandline -f delete-char " -""".strip()) +""".strip() +) expect_prompt() -send('\x07') # ctrl-g -send('\r') +send("\x07") # ctrl-g +send("\r") expect_prompt("foobar") # This should do nothing instead of crash @@ -407,7 +413,7 @@ expect_prompt() # (for obvious reasons this MUST BE LAST) sendline("function myexit; echo exit; exit; end; bind ctrl-z myexit") expect_prompt() -send("\x1A") +send("\x1a") expect_str("exit") for t in range(0, 50): diff --git a/tests/pexpects/commandline.py b/tests/pexpects/commandline.py index 0d0130080..a3ccec121 100644 --- a/tests/pexpects/commandline.py +++ b/tests/pexpects/commandline.py @@ -15,19 +15,21 @@ expect_prompt() # Test --showing-suggestion before we dirty the history sendline("echo hello") expect_prompt() -sendline("function debug; commandline --showing-suggestion; set -g cmd_status $status; end") +sendline( + "function debug; commandline --showing-suggestion; set -g cmd_status $status; end" +) expect_prompt() -sendline("bind ctrl-p debug"); +sendline("bind ctrl-p debug") expect_prompt() send("echo hell") -sleep(0.1) # wait for suggestion to appear under CI +sleep(0.1) # wait for suggestion to appear under CI send(control("p")) sendline("") expect_prompt("hell") sendline("echo cmd_status: $cmd_status") expect_prompt("cmd_status: 0") send("echo goodb") -sleep(0.1) # wait for suggestion to appear under CI +sleep(0.1) # wait for suggestion to appear under CI send(control("p")) sendline("") expect_prompt("goodb") diff --git a/tests/pexpects/fg.py b/tests/pexpects/fg.py index 50af50625..2034f830d 100644 --- a/tests/pexpects/fg.py +++ b/tests/pexpects/fg.py @@ -19,11 +19,11 @@ expect_prompt() # (but also does so under /bin/sh) testproc = "sleep 500" if platform.system() != "NetBSD" else "cat" sendline(testproc) -sendline("set -l foo 'bar'1; echo $foo") # ignored because sleep is in fg +sendline("set -l foo 'bar'1; echo $foo") # ignored because sleep is in fg sleep(1.2) # ctrl-z - send job to background -send("\x1A") +send("\x1a") sleep(1.2) expect_prompt() sendline("set -l foo 'bar'2; echo $foo") @@ -49,7 +49,7 @@ sendline("sleep 1") sleep(0.1) # ctrl-z - send job to background -send("\x1A") +send("\x1a") sleep(0.2) expect_prompt("has stopped") @@ -65,7 +65,7 @@ expect_prompt("jobs: There are no jobs") # Ensure we can do it again. sendline("sleep 5") sleep(0.2) -send("\x1A") +send("\x1a") sleep(0.1) expect_prompt("has stopped") sendline("fg") @@ -78,6 +78,7 @@ expect_prompt("jobs: There are no jobs") if not os.environ.get("fish_test_helper", ""): import sys + sys.exit(127) # Regression test for #2214: foregrounding from a key binding works! @@ -86,14 +87,14 @@ expect_prompt() sendline("$fish_test_helper print_stop_cont") sleep(0.2) -send("\x1A") # ctrl-z +send("\x1a") # ctrl-z expect_prompt("SIGTSTP") sleep(0.1) send("\x12") # ctrl-r, placing fth in foreground expect_str("SIGCONT") # Do it again. -send("\x1A") +send("\x1a") expect_str("SIGTSTP") sleep(0.1) send("\x12") diff --git a/tests/pexpects/fkr.py b/tests/pexpects/fkr.py index 4864d9200..15383fc47 100644 --- a/tests/pexpects/fkr.py +++ b/tests/pexpects/fkr.py @@ -31,7 +31,7 @@ expect_str("bind ctrl-g 'do something'\r\n") # Is a non-ASCII UTF-8 sequence prefaced by an escape char handled correctly? sleep(0.020) -send("\x1B") +send("\x1b") expect_str("# decoded from: \\e\r\n") expect_str("bind escape 'do something'\r\n") send("รถ") diff --git a/tests/pexpects/histfile.py b/tests/pexpects/histfile.py index 7739064a8..be03a6879 100644 --- a/tests/pexpects/histfile.py +++ b/tests/pexpects/histfile.py @@ -23,6 +23,7 @@ env_histfile = "xdg_data_home/fish/env_history" def grephistfile(line, file): sendline("grep '^" + line + "' " + file) + # Verify that if we spawn fish with no fish_history env var it uses the # default file. expect_prompt() diff --git a/tests/pexpects/history.py b/tests/pexpects/history.py index 6034c1ddf..492066a63 100644 --- a/tests/pexpects/history.py +++ b/tests/pexpects/history.py @@ -111,7 +111,9 @@ expect_re("history delete -p 'echo hello'" + TO_END_SUFFIX) expect_re("\\[1\\] echo hello AGAIN" + TO_END_SUFFIX) expect_re("\\[2\\] echo hello again" + TO_END_SUFFIX) expect_re("Enter nothing to cancel the delete, or\r\n") -expect_re("Enter one or more of the entry IDs or ranges like '5..12', separated by a space.\r\n") +expect_re( + "Enter one or more of the entry IDs or ranges like '5..12', separated by a space.\r\n" +) expect_re("For example '7 10..15 35 788..812'.\r\n") expect_re("Enter 'all' to delete all the matching entries.\r\n") expect_re("Delete which entries\\? ") @@ -120,14 +122,10 @@ expect_prompt('Deleting history entry 1: "echo hello AGAIN"\r\n') # Verify that the deleted history entry is gone and the other one that matched # the prefix search above is still there. -sendline( - "echo count AGAIN (history search -e -C 'echo hello AGAIN' | count)" -) +sendline("echo count AGAIN (history search -e -C 'echo hello AGAIN' | count)") expect_prompt("count AGAIN 0\r\n") -sendline( - "echo count again (history search -e -C 'echo hello again' | count)" -) +sendline("echo count again (history search -e -C 'echo hello again' | count)") expect_prompt("count again 1\r\n") # Verify that the $history var has the expected content. @@ -182,7 +180,9 @@ expect_prompt() # Check history filtering # We store anything that starts with "echo ephemeral". -sendline("function fish_should_add_to_history; string match -q 'echo ephemeral*' -- $argv; and return 2; return 0; end") +sendline( + "function fish_should_add_to_history; string match -q 'echo ephemeral*' -- $argv; and return 2; return 0; end" +) expect_prompt("") # Check that matching the line works # (fish_should_add_to_history is itself stored in history so we match "ephemeral!" to avoid it) diff --git a/tests/pexpects/pipeline.py b/tests/pexpects/pipeline.py index a1f74d2a1..10a99afa2 100644 --- a/tests/pexpects/pipeline.py +++ b/tests/pexpects/pipeline.py @@ -16,6 +16,7 @@ expect_prompt() if not os.environ.get("fish_test_helper", ""): import sys + sys.exit(127) for i in range(5): diff --git a/tests/pexpects/prompt_redraw_loop.py b/tests/pexpects/prompt_redraw_loop.py index 45aad38ea..438dbd893 100644 --- a/tests/pexpects/prompt_redraw_loop.py +++ b/tests/pexpects/prompt_redraw_loop.py @@ -17,14 +17,22 @@ expect_prompt() # If a process in the prompt exits with a status that would cause a message to be printed, # don't trigger another prompt execution which would result in an infinite loop. sendline("sh -c 'kill -ABRT $$'") -expect_prompt(re.escape("fish: Job 1, 'sh -c 'kill -ABRT $$'' terminated by signal SIGABRT (Abort)")) +expect_prompt( + re.escape( + "fish: Job 1, 'sh -c 'kill -ABRT $$'' terminated by signal SIGABRT (Abort)" + ) +) # Copy current prompt so we can reuse it. sendline("functions --copy fish_prompt fish_prompt_orig") expect_prompt() sendline("function fish_prompt; sh -c 'kill -ABRT $$'; fish_prompt_orig; end") -expect_prompt(re.escape("fish: Job 1, 'sh -c 'kill -ABRT $$'' terminated by signal SIGABRT (Abort)")) +expect_prompt( + re.escape( + "fish: Job 1, 'sh -c 'kill -ABRT $$'' terminated by signal SIGABRT (Abort)" + ) +) sendline("echo still alive!") expect_prompt("still alive!") diff --git a/tests/pexpects/stdin_nonblocking.py b/tests/pexpects/stdin_nonblocking.py index 06f5dec22..6855a52fc 100644 --- a/tests/pexpects/stdin_nonblocking.py +++ b/tests/pexpects/stdin_nonblocking.py @@ -14,6 +14,7 @@ send, sendline, expect_prompt, expect_str, sleep = ( if not os.environ.get("fish_test_helper", ""): import sys + sys.exit(127) # Launch fish_test_helper. @@ -24,7 +25,7 @@ sendline(exe_path + " stdin_make_nonblocking") expect_str("stdin was blocking") sleep(0.1) -send("\x1A") # ctrl-Z +send("\x1a") # ctrl-Z expect_prompt("has stopped") # We don't "restore" non-blocking state when continuing a stopped job. diff --git a/tests/pexpects/terminal.py b/tests/pexpects/terminal.py index 5e05abb61..7683c890c 100644 --- a/tests/pexpects/terminal.py +++ b/tests/pexpects/terminal.py @@ -61,6 +61,7 @@ expect_prompt("0") # TODO import sys + sys.exit(0) # HACK: This fails on FreeBSD, macOS and NetBSD for some reason, maybe # a pexpect issue? diff --git a/tests/pexpects/undo.py b/tests/pexpects/undo.py index 369001f0a..934d48afe 100644 --- a/tests/pexpects/undo.py +++ b/tests/pexpects/undo.py @@ -26,7 +26,9 @@ expect_str("echo") send("Redo\r") expect_prompt("echo word") -sendline("bind x begin-undo-group 'commandline -i \"+ \"' 'commandline -i 3' end-undo-group") +sendline( + "bind x begin-undo-group 'commandline -i \"+ \"' 'commandline -i 3' end-undo-group" +) expect_prompt() send("math 2 x\r") expect_prompt("5") @@ -36,8 +38,8 @@ send("Undo1\r") expect_prompt("41") send("math 5 x") -send("\x02") # c-b, moving before the 3 +send("\x02") # c-b, moving before the 3 send("Undo") send("Redo") -send("9\r") # 5 + 93 +send("9\r") # 5 + 93 expect_prompt("98") diff --git a/tests/test_driver.py b/tests/test_driver.py index 3a5b02f35..80c856ed8 100755 --- a/tests/test_driver.py +++ b/tests/test_driver.py @@ -122,14 +122,14 @@ def main(): ) argparser.add_argument("fish", nargs=1, help="Fish to test") argparser.add_argument("file", nargs="*", help="Tests to run") - args=argparser.parse_args() + args = argparser.parse_args() fishdir = Path(args.fish[0]).absolute() if not fishdir.is_dir(): fishdir = fishdir.parent failcount = 0 - failed=[] + failed = [] passcount = 0 skipcount = 0 def_subs = {"%": "%"} @@ -247,7 +247,7 @@ def main(): if passcount + failcount + skipcount > 1: print(f"{passcount} / {passcount + failcount} passed ({skipcount} skipped)") if failcount: - failstr = '\n '.join(failed) + failstr = "\n ".join(failed) print(f"{RED}Failed tests{RESET}: \n {failstr}") if passcount == 0 and failcount == 0 and skipcount: return 125