Reformat with black.

This commit is contained in:
Łukasz Wieczorek 2025-02-06 16:08:01 +01:00 committed by David Adam
parent d32c455269
commit 82750bbaec
16 changed files with 135 additions and 86 deletions

View File

@ -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

View File

@ -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."
)

View File

@ -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]
)

View File

@ -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")

View File

@ -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):

View File

@ -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")

View File

@ -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")

View File

@ -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("ö")

View File

@ -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()

View File

@ -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)

View File

@ -16,6 +16,7 @@ expect_prompt()
if not os.environ.get("fish_test_helper", ""):
import sys
sys.exit(127)
for i in range(5):

View File

@ -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!")

View File

@ -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.

View File

@ -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?

View File

@ -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")

View File

@ -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