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

1"""fpm's command line: link flags, and the test runner the app puts in.""" 

2 

3from __future__ import annotations 

4 

5import os 

6import sys 

7 

8from .compat import join_args 

9 

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

12 

13 

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] 

26 

27 

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 

43 

44 

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 

50 

51 

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

58 

59 

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:]