Coverage for vibefpmgui/fpm_args.py: 94%
35 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-01 20:51 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-01 20:51 +0000
1"""fpm's command line: link flags, and the test runner the app puts in."""
3from __future__ import annotations
5import os
6import sys
8from .compat import join_args
10# The wrapper each test or program runs in (marks where it starts and ends).
11TEST_RUNNER = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_runner.py")
14def with_link_flag(args: list[str], flag: str) -> list[str]:
15 """fpm arguments with ``flag`` added to the link flags (to the user's own
16 --link-flag, if there's one: fpm would take only one of two)."""
17 out = list(args)
18 for i, arg in enumerate(out):
19 if arg == "--link-flag" and i + 1 < len(out):
20 out[i + 1] = f"{out[i + 1]} {flag}"
21 return out
22 if arg.startswith("--link-flag="): 22 ↛ 18line 22 didn't jump to line 18 because the condition on line 22 was always true
23 out[i] = f"{arg} {flag}"
24 return out
25 return out + ["--link-flag", flag]
28def split_runner(args: list[str]) -> tuple[list[str], str]:
29 """Take "--runner CMD" / "--runner=CMD" out of an fpm argument list."""
30 rest, runner = [], ""
31 i = 0
32 while i < len(args):
33 if args[i] == "--runner" and i + 1 < len(args):
34 runner = args[i + 1]
35 i += 2
36 continue
37 if args[i].startswith("--runner="): 37 ↛ 38line 37 didn't jump to line 38 because the condition on line 37 was never true
38 runner = args[i].split("=", 1)[1]
39 else:
40 rest.append(args[i])
41 i += 1
42 return rest, runner
45def runner_command(collect: bool = False) -> str:
46 """The command fpm should put in front of each test executable (with
47 ``collect``: one that only prints the test's command line)."""
48 parts = [sys.executable, "-I", TEST_RUNNER] + (["--collect"] if collect else [])
49 return join_args(parts) # quoted for the platform's shell
52# Valgrind's memory check, as fpm's runner: the leaks that are lost (not the
53# libraries' own, still reachable at exit), where an uninitialised value came
54# from, optimised code's bit tricks not taken for uninitialised values, deep
55# stacks, and exit code 1 when it finds an error.
56VALGRIND_RUNNER = ("valgrind --leak-check=full --show-leak-kinds=definite,possible --track-origins=yes "
57 "--expensive-definedness-checks=yes --num-callers=30 --error-exitcode=1")
60def with_runner(args: list[str], runner: str) -> list[str]:
61 """fpm's ``args`` with ``--runner runner`` (before any program arguments)."""
62 cut = args.index("--") if "--" in args else len(args)
63 return args[:cut] + ["--runner", runner] + args[cut:]