Coverage for apio/__main__.py: 89%
35 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-23 03:53 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-23 03:53 +0000
1#!venv/bin/python
2"""Apio starting point."""
4import sys
5import atexit
6from apio.common.debug_util import is_debug
8# -- IMPORTANT: This module is an entry point for both the Apio
9# -- process and the Scons process (when using under pyinstaller) and
10# -- therefore can depend only on common functionality under
11# -- apio.common.
14debug_enabled = is_debug(1)
17def on_exit(msg):
18 """Prints a debug message on process exit. The msg string is passed
19 from the handler registrations below.
20 """
21 if debug_enabled:
22 print(msg)
25def main():
26 """Apio starting point."""
28 if debug_enabled:
29 print(f"Apio main(): original argv: {sys.argv}")
31 # pylint: disable=import-outside-toplevel
33 # -- Handle the case of the scons subprocess. Because we also use
34 # -- pyinstaller, without standard pip packages, we can't simply invoke
35 # -- the 'scons' binary so we invoke the SCons module from the apio main.
36 # -- See more details at:
37 # -- See https://github.com/orgs/pyinstaller/discussions/9023.
38 # --
39 # -- In this case argv goes through these stages
40 # -- Original: <binary> -m apio --scons ...
41 # -- Under python: <binary> --scons ...
42 # -- Under pyinstaller: <binary> -m apio --scons ...
43 # -- After fixing for scons: <binary> ...
44 # --
45 # -- Notice that the -m apio args are automatically removed by the
46 # -- python interpreter but are preserved by the pyinstaller, hence
47 # -- the two cases.
48 python_scons = sys.argv[1:2] == ["--scons"]
49 pyinstaller_scons = sys.argv[1:4] == ["-m", "apio", "--scons"]
51 if debug_enabled:
52 print(f"Apio main(): {python_scons=}")
53 print(f"Apio main(): {pyinstaller_scons=}")
55 if python_scons or pyinstaller_scons:
57 if debug_enabled: 57 ↛ 58line 57 didn't jump to line 58 because the condition on line 57 was never true
58 print("Apio main(): this is an scons process")
60 # -- Since scons_main() doesn't return, we use this handler to print
61 # -- an exit message for debugging.
62 atexit.register(on_exit, "Apio main(): scons process exit")
64 # -- Import and initialize scons only when running the scons
65 # -- subprocess.
66 from SCons.Script.Main import main as scons_main
67 from apio.common.common_util import maybe_wait_for_remote_debugger
69 # -- If system env var APIO_SCONS_DEBUGGER is defined, regardless of
70 # -- its value, we wait on a remote debugger to be attached, e.g.
71 # -- from Visual Studio Code.
72 # --
73 # -- You can place a breakpoint for example at SconsHandler.start().
74 maybe_wait_for_remote_debugger("APIO_SCONS_DEBUGGER")
76 # -- Drop the scons trigger args
77 if python_scons: 77 ↛ 84line 77 didn't jump to line 84 because the condition on line 77 was always true
78 # -- Case 1: Using a python interpreter which already dropped
79 # -- the ["-m", "apio"]. Dropping just ["--scons"]
80 sys.argv[1:] = sys.argv[2:]
81 else:
82 # -- Case 2: Using pyinstaller which preserved the ["-m", "apio"].
83 # -- Dropping ["-m", "apio", "--scons"]
84 sys.argv[1:] = sys.argv[4:]
86 if debug_enabled: 86 ↛ 87line 86 didn't jump to line 87 because the condition on line 86 was never true
87 print(f"Apio main(): scons fixed argv: {sys.argv}")
89 # -- Invoke the scons main function. It gets the modified argv from sys
90 # -- and doesn't return.
91 scons_main()
93 # -- Handle the case of a normal apio invocation.
94 else:
95 if debug_enabled:
96 print("Apio main(): this is an apio process")
98 # -- Since apio_top_cli() doesn't return, we use this handler to print
99 # -- an exit message for debugging.
100 atexit.register(on_exit, "Apio main(): apio process exit")
102 # -- Import the apio CLI only when running the apio process
103 # -- (as opposed to the scons sub process).
104 from apio.commands.apio import apio_top_cli
106 # -- Due to the Click decorations of apio_top_cli() and the Click
107 # -- magic, this function is not really invoked but Click dispatches
108 # -- it to its subcommands that was selected by the user command line.
109 # -- This function call doesn't return.
110 apio_top_cli()
113if __name__ == "__main__":
114 main()