Coverage for apio / __main__.py: 72%
35 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-24 01:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-24 01:53 +0000
1#!venv/bin/python
2"""Apio starting point."""
4import sys
5import os
6import atexit
8# -- Since this module is used also as the entry point for the scons
9# -- subprocess, we don't add here dependency on util.py and use a light
10# -- weight debug env var detection.
11# -- Set APIO_DEBUG=1 to enable.
12debug_enabled = int(os.environ.get("APIO_DEBUG", "0")) > 0
15def on_exit(msg):
16 """Prints a debug message on process exit. The msg string is passed
17 from the handler registrations below.
18 """
19 if debug_enabled: 19 ↛ 20line 19 didn't jump to line 20 because the condition on line 19 was never true
20 print(msg)
23def main():
24 """Apio starting point."""
26 if debug_enabled: 26 ↛ 27line 26 didn't jump to line 27 because the condition on line 26 was never true
27 print(f"Apio main(): original argv: {sys.argv}")
29 # pylint: disable=import-outside-toplevel
31 # -- Handle the case of the scons subprocess. Because we also use
32 # -- pyinstaller, without standard pip packages, we can't simply invoke
33 # -- the 'scons' binary so we invoke the SCons module from the apio main.
34 # -- See more details at:
35 # -- See https://github.com/orgs/pyinstaller/discussions/9023.
36 # --
37 # -- In this case argv goes through these stages
38 # -- Original: <binary> -m apio --scons ...
39 # -- Under python: <binary> --scons ...
40 # -- Under pyinstaller: <binary> -m apio --scons ...
41 # -- After fixing for scons: <binary> ...
42 # --
43 # -- Notice that the -m apio args are automatically removed by the
44 # -- python interpreter but are preserved by the pyinstaller, hence
45 # -- the two cases.
46 python_scons = sys.argv[1:2] == ["--scons"]
47 pyinstaller_scons = sys.argv[1:4] == ["-m", "apio", "--scons"]
49 if debug_enabled: 49 ↛ 50line 49 didn't jump to line 50 because the condition on line 49 was never true
50 print(f"Apio main(): {python_scons=}")
51 print(f"Apio main(): {pyinstaller_scons=}")
53 if python_scons or pyinstaller_scons:
55 if debug_enabled: 55 ↛ 56line 55 didn't jump to line 56 because the condition on line 55 was never true
56 print("Apio main(): this is an scons process")
58 # -- Since scons_main() doesn't return, we use this handler to print
59 # -- an exit message for debugging.
60 atexit.register(on_exit, "Apio main(): scons process exit")
62 # -- Import and initialize scons only when running the scons
63 # -- subprocess.
64 from SCons.Script.Main import main as scons_main
65 from apio.common.common_util import maybe_wait_for_remote_debugger
67 # -- If system env var APIO_SCONS_DEBUGGER is defined, regardless of
68 # -- its value, we wait on a remote debugger to be attached, e.g.
69 # -- from Visual Studio Code.
70 # --
71 # -- You can place a breakpoint for example at SconsHandler.start().
72 maybe_wait_for_remote_debugger("APIO_SCONS_DEBUGGER")
74 # -- Drop the scons trigger args
75 if python_scons: 75 ↛ 82line 75 didn't jump to line 82 because the condition on line 75 was always true
76 # -- Case 1: Using a python interpreter which already dropped
77 # -- the ["-m", "apio"]. Dropping just ["--scons"]
78 sys.argv[1:] = sys.argv[2:]
79 else:
80 # -- Case 2: Using pyinstaller which preserved the ["-m", "apio"].
81 # -- Dropping ["-m", "apio", "--scons"]
82 sys.argv[1:] = sys.argv[4:]
84 if debug_enabled: 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true
85 print(f"Apio main(): scons fixed argv: {sys.argv}")
87 # -- Invoke the scons main function. It gets the modified argv from sys
88 # -- and doesn't return.
89 scons_main()
91 # -- Handle the case of a normal apio invocation.
92 else:
93 if debug_enabled: 93 ↛ 94line 93 didn't jump to line 94 because the condition on line 93 was never true
94 print("Apio main(): this is an apio process")
96 # -- Since apio_top_cli() doesn't return, we use this handler to print
97 # -- an exit message for debugging.
98 atexit.register(on_exit, "Apio main(): apio process exit")
100 # -- Import the apio CLI only when running the apio process
101 # -- (as opposed to the scons sub process).
102 from apio.commands.apio import apio_top_cli
104 # -- Due to the Click decorations of apio_top_cli() and the Click
105 # -- magic, this function is not really invoked but Click dispatches
106 # -- it to its subcommands that was selected by the user command line.
107 # -- This function call doesn't return.
108 apio_top_cli()
111if __name__ == "__main__":
112 main()