From f83badac1971c67714d826a3717edd89fae8d44a Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:28:18 +0200 Subject: [PATCH 1/8] Bump pre-commit hooks --- .pre-commit-config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4b98e6c..b5d5ad2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,20 +2,20 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.9.0.5 + rev: v0.10.0.1 hooks: - id: shellcheck exclude: examples/|testing/tests/.*\.sh - repo: https://github.com/maxwinterstein/shfmt-py - rev: v3.4.3.1 + rev: v3.7.0.1 hooks: - id: shfmt exclude: examples/t6.sh args: ["-w", "-i", "4", "-ci"] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: trailing-whitespace exclude: ^testing/Baseline @@ -23,13 +23,13 @@ repos: exclude: ^testing/Baseline|examples/.*Baseline.* - repo: https://github.com/asottile/pyupgrade - rev: v3.15.1 + rev: v3.17.0 hooks: - id: pyupgrade args: ["--py37-plus"] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.0 + rev: v0.5.5 hooks: - id: ruff args: [--fix] From 6a31295fea60257bc6b4473c0eb96d4299d75d5d Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:17:27 +0200 Subject: [PATCH 2/8] Move project configuration to `pyproject.toml` This centralizes most project configuration from `setup.py` and `setup.cfg` into the existing `pyproject.toml` so it can be picked up by more tools. --- pyproject.toml | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 7 ----- setup.py | 48 +-------------------------------- 3 files changed, 74 insertions(+), 54 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.cfg diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ffb9432 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,73 @@ +[build-system] +requires = ["setuptools"] + +[project] +name = "btest" +description = "A powerful system testing framework" +readme = "See https://github.com/zeek/btest" +dynamic = ["version"] + +license = { text = "3-clause BSD License" } + +requires-python = ">=3.7" + +keywords=[ + "system", + "tests", + "testing", + "framework", + "baselines", +] + +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "License :: OSI Approved :: BSD License", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python :: 3", + "Topic :: Utilities", +] + +dependencies = [ + # We require the external multiprocess library on Windows due to pickling + # issues with the standard one. + "multiprocess>=0.70.16", +] + +[project.urls] +Repository = "https://github.com/zeek/btest" + +[[project.maintainers]] +name = "The Zeek Team" +email = "info@zeek.org" + +[tool.setuptools] +# When making changes to the following list, remember to keep +# CMakeLists.txt in sync. +script-files = [ + "btest", + "btest-ask-update", + "btest-bg-run", + "btest-bg-run-helper", + "btest-bg-wait", + "btest-diff", + "btest-setsid", + "btest-progress", + "sphinx/btest-diff-rst", + "sphinx/btest-rst-cmd", + "sphinx/btest-rst-include", + "sphinx/btest-rst-pipe", +] + +package-dir = { "" = "sphinx"} + +[tool.flake8] +max_line_length = 100 +# E203: whitespace before ':' (black / flake8 disagreement) +# W503: line break before binary operator (black / flake8 disagreement) +ignore="E203,W503" +# E266: too many leading '#' for block comment +per-file-ignores = """ + btest: E266 +""" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 050d12b..0000000 --- a/setup.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[flake8] -max_line_length = 100 -# E203: whitespace before ':' (black / flake8 disagreement) -# W503: line break before binary operator (black / flake8 disagreement) -ignore=E203,W503 -# E266: too many leading '#' for block comment -per-file-ignores = btest: E266 diff --git a/setup.py b/setup.py index 6321ef9..20dcbbe 100644 --- a/setup.py +++ b/setup.py @@ -1,56 +1,10 @@ -#! /usr/bin/env python +#!/usr/bin/env python from setuptools import setup -import sys - -# When making changes to the following list, remember to keep -# CMakeLists.txt in sync. -scripts = [ - "btest", - "btest-ask-update", - "btest-bg-run", - "btest-bg-run-helper", - "btest-bg-wait", - "btest-diff", - "btest-setsid", - "btest-progress", - "sphinx/btest-diff-rst", - "sphinx/btest-rst-cmd", - "sphinx/btest-rst-include", - "sphinx/btest-rst-pipe", -] py_modules = ["btest-sphinx"] -# We require the external multiprocess library on Windows due to pickling issues -# with the standard one. -if sys.platform == "win32": - install_requires = ["multiprocess"] -else: - install_requires = [] - setup( - name="btest", version="1.1.dev8", # Filled in automatically. - description="A powerful system testing framework", - long_description="See https://github.com/zeek/btest", - author="The Zeek Team", - author_email="info@zeek.org", - url="https://github.com/zeek/btest", - scripts=scripts, - package_dir={"": "sphinx"}, py_modules=py_modules, - license="3-clause BSD License", - keywords="system tests testing framework baselines", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Environment :: Console", - "License :: OSI Approved :: BSD License", - "Operating System :: POSIX :: Linux", - "Operating System :: MacOS :: MacOS X", - "Programming Language :: Python :: 3", - "Topic :: Utilities", - ], - python_requires=">=3.7", - install_requires=install_requires, ) From 502234289b6237f99c5e1ddced53fd6788962026 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:35:25 +0200 Subject: [PATCH 3/8] Use ruff for pyupgrade functionality --- .pre-commit-config.yaml | 6 --- btest | 90 +++++++++++++++++++---------------------- examples/sphinx/conf.py | 11 +++-- pyproject.toml | 3 ++ sphinx/btest-sphinx.py | 20 +++++---- 5 files changed, 58 insertions(+), 72 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5d5ad2..17783a6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,12 +22,6 @@ repos: - id: end-of-file-fixer exclude: ^testing/Baseline|examples/.*Baseline.* -- repo: https://github.com/asottile/pyupgrade - rev: v3.17.0 - hooks: - - id: pyupgrade - args: ["--py37-plus"] - - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.5.5 hooks: diff --git a/btest b/btest index 88769ce..6d85ce8 100755 --- a/btest +++ b/btest @@ -49,7 +49,7 @@ if sys.platform == "win32": " pip install multiprocess\n" "\n" "Also check the following exception output for possible alternate explanations:\n\n" - "{}: {}".format(type(error).__name__, error), + f"{type(error).__name__}: {error}", file=sys.stderr, ) else: @@ -161,7 +161,7 @@ def validate_version_requirement(required: str, present: str): xyz = [int(x) for x in re.split(r"[.-]", v)] except ValueError: error( - "invalid version %s: versions must contain only numeric identifiers" % v + f"invalid version {v}: versions must contain only numeric identifiers" ) return xyz @@ -171,8 +171,7 @@ def validate_version_requirement(required: str, present: str): if v_present < v_required: error( - "%s requires at least BTest %s, this is %s. Please upgrade." - % (Options.config, min_version, VERSION) + f"{Options.config} requires at least BTest {min_version}, this is {VERSION}. Please upgrade." ) @@ -476,9 +475,7 @@ class TestManager(mp_managers.SyncManager): if max_test_ports > port_range_hi - port_range_lo + 1: error( - "PortRange {} cannot satisfy requirement of {} ports in test {}".format( - port_range, max_test_ports, test_with_most_ports.name - ) + f"PortRange {port_range} cannot satisfy requirement of {max_test_ports} ports in test {test_with_most_ports.name}" ) self._ports = self.list([p for p in range(port_range_lo, port_range_hi + 1)]) @@ -524,7 +521,7 @@ class TestManager(mp_managers.SyncManager): try: state = open(StateFile, "w", encoding="utf-8") except OSError: - error("cannot open state file %s" % StateFile) + error(f"cannot open state file {StateFile}") for t in sorted(self._failed_tests): print(t, file=state) @@ -1136,9 +1133,7 @@ class Test: error(f"failed to obtain {count} ports for test {self.name}") warning( - "failed to obtain {} ports for test {}, will try {} more times".format( - count, self.name, attempts - ) + f"failed to obtain {count} ports for test {self.name}, will try {attempts} more times" ) time.sleep(15) @@ -1369,8 +1364,7 @@ class Test: if self.utime_exceeded and not Options.update_times: self.diagmsgs += [ - "'%s' exceeded permitted execution time deviation%s" - % (self.name, self.timePostfix()) + f"'{self.name}' exceeded permitted execution time deviation{self.timePostfix()}" ] self.mgr.testFailed(self) @@ -1431,7 +1425,7 @@ class Test: # This is not quite correct as it does not necessarily need to be # the %INPUT file which we are filtering ... filtered = normalize_path_join( - self.tmpdir, "filtered-%s" % os.path.basename(localfile) + self.tmpdir, f"filtered-{os.path.basename(localfile)}" ) filter = CmdLine( @@ -1489,7 +1483,7 @@ class Test: if cmd.expect_success: return (True, rc) - self.diagmsgs += ["'%s' succeeded unexpectedly (exit code 0)" % cmdline] + self.diagmsgs += [f"'{cmdline}' succeeded unexpectedly (exit code 0)"] return (False, 0) else: @@ -1556,7 +1550,7 @@ class Test: # Otherwise, returns an empty string. def timePostfix(self): if self.utime_base >= 0 and self.utime >= 0: - return " (%+.1f%%)" % self.utime_perc + return f" ({self.utime_perc:+.1f}%)" else: return "" @@ -1763,7 +1757,7 @@ class Standard(OutputHandler): def testStart(self, test): self.output(test, self.threadPrefix(), nl=False) - self.output(test, "%s ..." % test.displayName(), nl=False) + self.output(test, f"{test.displayName()} ...", nl=False) test._std_nl = False def testCommand(self, test, cmdline): @@ -1790,7 +1784,7 @@ class Standard(OutputHandler): def finalMsg(self, test, msg): if test._std_nl: self.output(test, self.threadPrefix(), nl=False) - self.output(test, "%s ..." % test.displayName(), nl=False) + self.output(test, f"{test.displayName()} ...", nl=False) self.output(test, msg) @@ -1825,7 +1819,7 @@ class Console(OutputHandler): def testProgress(self, test, msg): """Called when a test signals having made progress.""" - msg = self.DarkGray + "(%s)" % msg + self.Normal + msg = self.DarkGray + f"({msg})" + self.Normal self.output(test, msg) def testSucceeded(self, test, msg): @@ -1882,7 +1876,7 @@ class CompactConsole(Console): def testProgress(self, test, msg): """Called when a test signals having made progress.""" - msg = " " + self.DarkGray + "(%s)" % msg + self.Normal + msg = " " + self.DarkGray + f"({msg})" + self.Normal self._consoleAugment(test, msg) def testSucceeded(self, test, msg): @@ -1929,13 +1923,13 @@ class CompactConsole(Console): def _consoleAugment(self, test, msg): self._outfile.write(self.EraseToEndOfLine) - self._outfile.write(" %s" % msg.strip()) - self._outfile.write("\r%s" % test.console_last_line) + self._outfile.write(f" {msg.strip()}") + self._outfile.write(f"\r{test.console_last_line}") self._outfile.flush() def _consoleWrite(self, test, msg, sticky): self._outfile.write(chr(27) + "[2K") - self._outfile.write("\r%s" % msg.strip()) + self._outfile.write(f"\r{msg.strip()}") if sticky: self._outfile.write("\n") @@ -1977,7 +1971,7 @@ class Verbose(OutputHandler): def testStart(self, test): self.output(test, self.threadPrefix(), nl=False) - self.output(test, "%s ..." % test.displayName()) + self.output(test, f"{test.displayName()} ...") def testCommand(self, test, cmdline): part = "" @@ -2017,7 +2011,7 @@ class Verbose(OutputHandler): return for line in open(test.verbose): - self.output(test, " > [test-verbose] %s" % line.strip()) + self.output(test, f" > [test-verbose] {line.strip()}") class Diag(OutputHandler): @@ -2125,8 +2119,7 @@ class SphinxOutput(OutputHandler): print("\n.. code-block:: none ", file=out) print( - "\n ERROR executing test '%s' (part %s)\n" - % (test.displayName(), self._part), + f"\n ERROR executing test '{test.displayName()}' (part {self._part})\n", file=out, ) @@ -2144,7 +2137,7 @@ class SphinxOutput(OutputHandler): for line in open( f, newline="\n", encoding="utf-8", errors="backslashreplace" ): - print(" %s" % line.strip(), file=out) + print(f" {line.strip()}", file=out) print(file=out) def testUnstable(self, test, msg): @@ -2412,7 +2405,7 @@ class LinuxTimer(TimerBase): # Make sure it works. (success, rc) = runSubprocess( - "%s stat -o /dev/null true 2>/dev/null" % self.perf, shell=True + f"{self.perf} stat -o /dev/null true 2>/dev/null", shell=True ) return success and rc == 0 @@ -2480,15 +2473,14 @@ def findTests(paths, expand_globs=False): m = RE_PART.match(rpath) if m: error( - "Do not specify files with part numbers directly, use the base test name (%s)" - % rpath + f"Do not specify files with part numbers directly, use the base test name ({rpath})" ) if os.path.isfile(path): tests += readTestFile(path) # See if there are more parts. - for part in glob.glob("%s#*" % rpath): + for part in glob.glob(f"{rpath}#*"): tests += readTestFile(part) elif os.path.isdir(path): @@ -2524,12 +2516,12 @@ def findTests(paths, expand_globs=False): if not found: # See if there are parts. - for part in glob.glob("%s#*" % rpath): + for part in glob.glob(f"{rpath}#*"): tests += readTestFile(part) found = True if not found: - error("cannot read %s" % path) + error(f"cannot read {path}") return tests @@ -2572,7 +2564,7 @@ def readTestFile(filename): try: input = open(filename, encoding="utf-8", newline="") except OSError as e: - error("cannot read test file: %s" % e) + error(f"cannot read test file: {e}") tests = [] files = [] @@ -2631,7 +2623,7 @@ def readTestFile(filename): file = (file[0], file[1] + [line]) else: - error("internal: unknown state %s" % state) + error(f"internal: unknown state {state}") if state == "file": files += [file] @@ -2692,7 +2684,7 @@ def outputDocumentation(tests, fmt): tests = sections[s] if fmt == "rst": - print("%s" % s) + print(f"{s}") print("-" * len(s)) print() @@ -2703,11 +2695,11 @@ def outputDocumentation(tests, fmt): print() if fmt == "md": - print("# %s" % s) + print(f"# {s}") print() for t in tests: - print("* `%s`:" % t.name) + print(f"* `{t.name}`:") for d in doc(t): print(f"{indent(1)}{d}") @@ -2957,7 +2949,7 @@ def parse_options(): options.threads = 1 if not os.path.exists(options.config): - error("configuration file '%s' not found" % options.config) + error(f"configuration file '{options.config}' not found") return options, parsed_args @@ -3040,7 +3032,7 @@ if __name__ == "__main__": # If multiple alternatives set it, we pick the value from the first. def get_env_from_alternative(env, opt, default, transform=None): for tag in Options.alternatives: - value = getOption(env, None, section="environment-%s" % tag) + value = getOption(env, None, section=f"environment-{tag}") if value is not None: if transform: value = transform(value) @@ -3110,21 +3102,21 @@ if __name__ == "__main__": a = Alternative(tag) try: - for name, value in Config.itemsNoDefaults("filter-%s" % tag): + for name, value in Config.itemsNoDefaults(f"filter-{tag}"): a.filters[name] = value except configparser.NoSectionError: pass try: - for name, value in Config.itemsNoDefaults("substitution-%s" % tag): + for name, value in Config.itemsNoDefaults(f"substitution-{tag}"): a.substitutions[name] = value except configparser.NoSectionError: pass try: - for name, value in Config.itemsNoDefaults("environment-%s" % tag): + for name, value in Config.itemsNoDefaults(f"environment-{tag}"): if name.startswith("-") and value.strip(): error( f'expected empty value for "{name}" in section environment-{tag}' @@ -3136,7 +3128,7 @@ if __name__ == "__main__": pass if a.is_empty() and not a.is_default(): - error('alternative "%s" is undefined' % tag) + error(f'alternative "{tag}" is undefined') Alternatives[tag] = a @@ -3235,7 +3227,7 @@ if __name__ == "__main__": (success, tests) = readTestsFile(Options.tests_file) if not success: - warning("cannot read file with tests: %s" % Options.tests_file) + warning(f"cannot read file with tests: {Options.tests_file}") else: tests = Config.configured_tests @@ -3284,11 +3276,11 @@ if __name__ == "__main__": if sys.platform == "win32": # On win32 we have to use a named pipe so that python's multiprocessing # chooses AF_PIPE as the family type. - addr = "\\\\.\\pipe\\btest-pipe-%s" % (os.getpid()) + addr = f"\\\\.\\pipe\\btest-pipe-{os.getpid()}" else: # Building our own path to avoid "error: AF_UNIX path too long" on # some platforms. See BIT-862. - sname = "btest-socket-%s" % (os.getpid()) + sname = f"btest-socket-{os.getpid()}" addr = os.path.join(tempfile.gettempdir(), sname) # Check if the pathname is too long to fit in struct sockaddr_un (the @@ -3321,7 +3313,7 @@ if __name__ == "__main__": # Ctrl-C can lead to broken pipe (e.g. FreeBSD), so include IOError here: except (Abort, KeyboardInterrupt, OSError) as exc: output_handler.finished() - print(str(exc) or "Aborted with %s." % type(exc).__name__, file=sys.stderr) + print(str(exc) or f"Aborted with {type(exc).__name__}.", file=sys.stderr) sys.stderr.flush() # Explicitly shut down sync manager to avoid leaking manager # processes, particularly with --abort-on-failure: diff --git a/examples/sphinx/conf.py b/examples/sphinx/conf.py index 1f7769e..4d56f7c 100644 --- a/examples/sphinx/conf.py +++ b/examples/sphinx/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # BTest-Sphinx Demo documentation build configuration file, created by # sphinx-quickstart on Wed May 8 15:22:37 2013. @@ -49,8 +48,8 @@ master_doc = 'index' # General information about the project. -project = u'BTest-Sphinx Demo' -copyright = u'2013, Foo Bar' +project = 'BTest-Sphinx Demo' +copyright = '2013, Foo Bar' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -190,7 +189,7 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'BTest-SphinxDemo.tex', u'BTest-Sphinx Demo Documentation', u'Foo Bar', 'manual'), + ('index', 'BTest-SphinxDemo.tex', 'BTest-Sphinx Demo Documentation', 'Foo Bar', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -217,7 +216,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [('index', 'btest-sphinxdemo', u'BTest-Sphinx Demo Documentation', [u'Foo Bar'], 1)] +man_pages = [('index', 'btest-sphinxdemo', 'BTest-Sphinx Demo Documentation', ['Foo Bar'], 1)] # If true, show URL addresses after external links. #man_show_urls = False @@ -228,7 +227,7 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'BTest-SphinxDemo', u'BTest-Sphinx Demo Documentation', u'Foo Bar', + ('index', 'BTest-SphinxDemo', 'BTest-Sphinx Demo Documentation', 'Foo Bar', 'BTest-SphinxDemo', 'One line description of project.', 'Miscellaneous'), ] diff --git a/pyproject.toml b/pyproject.toml index ffb9432..6d74fec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,3 +71,6 @@ ignore="E203,W503" per-file-ignores = """ btest: E266 """ + +[tool.ruff.lint] +select = ["UP"] diff --git a/sphinx/btest-sphinx.py b/sphinx/btest-sphinx.py index 2973f2b..c8a7633 100644 --- a/sphinx/btest-sphinx.py +++ b/sphinx/btest-sphinx.py @@ -43,14 +43,12 @@ def init(settings, reporter): raise SphinxError("error: btest_tests not set in config") if not os.path.exists(BTestBase): - raise SphinxError( - "error: btest_base directory '%s' does not exists" % BTestBase - ) + raise SphinxError(f"error: btest_base directory '{BTestBase}' does not exists") joined = os.path.join(BTestBase, BTestTests) if not os.path.exists(joined): - raise SphinxError("error: btest_tests directory '%s' does not exists" % joined) + raise SphinxError(f"error: btest_tests directory '{joined}' does not exists") if not BTestTmp: BTestTmp = os.path.join(App.outdir, ".tmp/rst_output") @@ -77,23 +75,23 @@ def run(self): if self.has_run: return - logger.info("running test %s ..." % darkgreen(self.path)) + logger.info(f"running test {darkgreen(self.path)} ...") - self.rst_output = os.path.join(BTestTmp, "%s" % self.tag) + self.rst_output = os.path.join(BTestTmp, f"{self.tag}") os.environ["BTEST_RST_OUTPUT"] = self.rst_output self.cleanTmps() try: - subprocess.check_call("btest -S %s" % self.path, shell=True) + subprocess.check_call(f"btest -S {self.path}", shell=True) except (OSError, subprocess.CalledProcessError) as e: # Equivalent to Directive.error(); we don't have an # directive object here and can't pass it in because # it doesn't pickle. - logger.warning(red("BTest error: %s" % e)) + logger.warning(red(f"BTest error: {e}")) def cleanTmps(self): - subprocess.call("rm %s#* 2>/dev/null" % self.rst_output, shell=True) + subprocess.call(f"rm {self.rst_output}#* 2>/dev/null", shell=True) class BTestTransform(Transform): @@ -167,7 +165,7 @@ def run(self): out = open(file, "w") for line in self.content: - out.write("%s\n" % line) + out.write(f"{line}\n") out.close() @@ -220,7 +218,7 @@ def run(self): self.options["language"] = "none" self.options["linenos"] = True - self.options["prepend"] = "%s\n" % os.path.basename(self.arguments[0]) + self.options["prepend"] = f"{os.path.basename(self.arguments[0])}\n" self.options["emphasize-lines"] = "1,1" self.options["style"] = "X" From a5c0a6756c0484976a3d66103b70731e17edb11c Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:42:19 +0200 Subject: [PATCH 4/8] Active linter for style around comprehensions --- btest | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/btest b/btest index 6d85ce8..d5f887b 100755 --- a/btest +++ b/btest @@ -478,7 +478,7 @@ class TestManager(mp_managers.SyncManager): f"PortRange {port_range} cannot satisfy requirement of {max_test_ports} ports in test {test_with_most_ports.name}" ) - self._ports = self.list([p for p in range(port_range_lo, port_range_hi + 1)]) + self._ports = self.list(list(range(port_range_lo, port_range_hi + 1))) threads = [] @@ -1378,7 +1378,7 @@ class Test: def finish(self): if self.bound_ports: - self.mgr.returnPorts([p for p in self.bound_ports]) + self.mgr.returnPorts(list(self.bound_ports)) self.bound_ports = [] @@ -2543,7 +2543,7 @@ def mergeTestParts(tests): except KeyError: out[t.name] = t - return sorted([t for t in out.values()], key=key) + return sorted(out.values(), key=key) # Read the given test file and instantiate one or more tests from it. @@ -2576,7 +2576,7 @@ def readTestFile(filename): state = "test" try: - lines = [line for line in input] + lines = list(input) except UnicodeDecodeError as e: # This error is caused by either a test file with an invalid UTF-8 byte # sequence, or if python makes the wrong assumption about the encoding diff --git a/pyproject.toml b/pyproject.toml index 6d74fec..5883783 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,4 +73,4 @@ per-file-ignores = """ """ [tool.ruff.lint] -select = ["UP"] +select = ["C4", "UP"] From b27467caa79877e0f39e883d2cbf0de59c695444 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:45:36 +0200 Subject: [PATCH 5/8] Activate pyflakes linter We previously linted with flake8 so this contains no code changes. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5883783..49670be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,4 +73,4 @@ per-file-ignores = """ """ [tool.ruff.lint] -select = ["C4", "UP"] +select = ["C4", "F", "UP"] From 5668f3379e364877fbc0d7a3dccb02f2ee9f0550 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:45:48 +0200 Subject: [PATCH 6/8] Activate isort linter --- btest | 1 - pyproject.toml | 2 +- sphinx/btest-sphinx.py | 9 +++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/btest b/btest index d5f887b..cefd636 100755 --- a/btest +++ b/btest @@ -29,7 +29,6 @@ import threading import time import uuid import xml.dom.minidom - from datetime import datetime # We require the external multiprocess library on Windows due to pickling issues diff --git a/pyproject.toml b/pyproject.toml index 49670be..5df6ce3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,4 +73,4 @@ per-file-ignores = """ """ [tool.ruff.lint] -select = ["C4", "F", "UP"] +select = ["C4", "F", "I", "UP"] diff --git a/sphinx/btest-sphinx.py b/sphinx/btest-sphinx.py index c8a7633..d6f1d31 100644 --- a/sphinx/btest-sphinx.py +++ b/sphinx/btest-sphinx.py @@ -1,15 +1,16 @@ import os import os.path -import subprocess import re +import subprocess from docutils import nodes, utils -from docutils.parsers.rst import directives, Directive, Parser +from docutils.parsers.rst import Directive, Parser, directives from docutils.transforms import Transform -from sphinx.util.console import darkgreen, red -from sphinx.errors import SphinxError + from sphinx.directives.code import LiteralInclude +from sphinx.errors import SphinxError from sphinx.util import logging +from sphinx.util.console import darkgreen, red logger = logging.getLogger(__name__) From 54a85b5245779421d21fcdc84fe4a04d133daaad Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 20:48:17 +0200 Subject: [PATCH 7/8] Activate flake8-implicit-str-concat linter --- btest | 22 +++++++++++----------- examples/sphinx/conf.py | 2 +- pyproject.toml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/btest b/btest index cefd636..d4e5c91 100755 --- a/btest +++ b/btest @@ -3145,17 +3145,17 @@ if __name__ == "__main__": # Commands as tuple (tag, regexp, more-than-one-is-ok, optional, group-main, group-add) # pylint: disable=bad-whitespace # fmt: off - RE_EXEC = ("exec", re.compile(CommandPrefix + "EXEC(-FAIL)?: *(.*)"), True, False, 2, 1) # noqa - RE_REQUIRES = ("requires", re.compile(CommandPrefix + "REQUIRES: *(.*)"), True, True, 1, -1) # noqa - RE_GROUP = ("group", re.compile(CommandPrefix + "GROUP: *(.*)"), True, True, 1, -1) # noqa - RE_SERIALIZE = ("serialize", re.compile(CommandPrefix + "SERIALIZE: *(.*)"), False, True, 1, -1) # noqa - RE_PORT = ("port", re.compile(CommandPrefix + "PORT: *(.*)"), True, True, 1, -1) # noqa - RE_INCLUDE_ALTERNATIVE = ("alternative", re.compile(CommandPrefix + "ALTERNATIVE: *(.*)"), True, True, 1, -1) # noqa - RE_IGNORE_ALTERNATIVE = ("not-alternative", re.compile(CommandPrefix + "NOT-ALTERNATIVE: *(.*)"), True, True, 1, -1) # noqa - RE_COPY_FILE = ("copy-file", re.compile(CommandPrefix + "COPY-FILE: *(.*)"), True, True, 1, -1) # noqa - RE_KNOWN_FAILURE = ("known-failure", re.compile(CommandPrefix + "KNOWN-FAILURE"), False, True, -1, -1) # noqa - RE_MEASURE_TIME = ("measure-time", re.compile(CommandPrefix + "MEASURE-TIME"), False, True, -1, -1) # noqa - RE_DOC = ("doc", re.compile(CommandPrefix + "DOC: *(.*)"), True, True, 1, -1) # noqa + RE_EXEC = ("exec", re.compile(CommandPrefix + "EXEC(-FAIL)?: *(.*)"), True, False, 2, 1) + RE_REQUIRES = ("requires", re.compile(CommandPrefix + "REQUIRES: *(.*)"), True, True, 1, -1) + RE_GROUP = ("group", re.compile(CommandPrefix + "GROUP: *(.*)"), True, True, 1, -1) + RE_SERIALIZE = ("serialize", re.compile(CommandPrefix + "SERIALIZE: *(.*)"), False, True, 1, -1) + RE_PORT = ("port", re.compile(CommandPrefix + "PORT: *(.*)"), True, True, 1, -1) + RE_INCLUDE_ALTERNATIVE = ("alternative", re.compile(CommandPrefix + "ALTERNATIVE: *(.*)"), True, True, 1, -1) + RE_IGNORE_ALTERNATIVE = ("not-alternative", re.compile(CommandPrefix + "NOT-ALTERNATIVE: *(.*)"), True, True, 1, -1) + RE_COPY_FILE = ("copy-file", re.compile(CommandPrefix + "COPY-FILE: *(.*)"), True, True, 1, -1) + RE_KNOWN_FAILURE = ("known-failure", re.compile(CommandPrefix + "KNOWN-FAILURE"), False, True, -1, -1) + RE_MEASURE_TIME = ("measure-time", re.compile(CommandPrefix + "MEASURE-TIME"), False, True, -1, -1) + RE_DOC = ("doc", re.compile(CommandPrefix + "DOC: *(.*)"), True, True, 1, -1) # fmt: on # pylint: enable=bad-whitespace diff --git a/examples/sphinx/conf.py b/examples/sphinx/conf.py index 4d56f7c..a7248d9 100644 --- a/examples/sphinx/conf.py +++ b/examples/sphinx/conf.py @@ -10,7 +10,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys sys.path.append("../../sphinx") sys.path.append("../../../sphinx") diff --git a/pyproject.toml b/pyproject.toml index 5df6ce3..cd3d1b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,4 +73,4 @@ per-file-ignores = """ """ [tool.ruff.lint] -select = ["C4", "F", "I", "UP"] +select = ["C4", "F", "I", "ISC", "UP"] From c31e6a40315215f4cf4d21bdff9cea8283b6d662 Mon Sep 17 00:00:00 2001 From: Benjamin Bannier Date: Tue, 30 Jul 2024 21:22:38 +0200 Subject: [PATCH 8/8] ci: Drop python-3.7, add python-3.12 Even though python-3.7 remains our minimal Python version it is not support by GH actions anymore so this commit drops it from CI. We also add a setup for the now released python-3.12. --- .github/workflows/btest.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/btest.yml b/.github/workflows/btest.yml index 1d37b9f..b34480a 100644 --- a/.github/workflows/btest.yml +++ b/.github/workflows/btest.yml @@ -12,7 +12,7 @@ jobs: Run-BTest: strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] os: [macos-latest, ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} @@ -53,7 +53,7 @@ jobs: Test-SetupPY: strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] os: [ubuntu-latest] runs-on: ${{ matrix.os }}