11"""A Typer CLI for CPPython interfacing"""
22
3+ import contextlib
4+ from collections .abc import Generator
35from importlib .metadata import entry_points
46from pathlib import Path
57from typing import Annotated
68
79import typer
810from rich import print
11+ from rich .console import Console
912from rich .syntax import Syntax
1013
1114from cppython .configuration import ConfigurationLoader
1215from cppython .console .schema import ConsoleConfiguration , ConsoleInterface
1316from cppython .core .schema import PluginReport , ProjectConfiguration
1417from cppython .project import Project
18+ from cppython .utility .output import OutputSession
1519
1620app = typer .Typer (no_args_is_help = True )
1721
18- info_app = typer .Typer (no_args_is_help = True , help = 'Prints project information including plugin configuration, managed files, and templates.' )
22+ info_app = typer .Typer (
23+ no_args_is_help = True ,
24+ help = 'Prints project information including plugin configuration, managed files, and templates.' ,
25+ )
1926app .add_typer (info_app , name = 'info' )
2027
2128list_app = typer .Typer (no_args_is_help = True , help = 'List project entities.' )
2229app .add_typer (list_app , name = 'list' )
2330
2431
25- def get_enabled_project (context : typer .Context ) -> Project :
26- """Helper to load and validate an enabled Project from CLI context."""
32+ def _get_configuration (context : typer .Context ) -> ConsoleConfiguration :
33+ """Extract the ConsoleConfiguration object from the CLI context.
34+
35+ Raises:
36+ ValueError: If the configuration object is missing
37+ """
2738 configuration = context .find_object (ConsoleConfiguration )
2839 if configuration is None :
2940 raise ValueError ('The configuration object is missing' )
41+ return configuration
42+
43+
44+ def get_enabled_project (context : typer .Context ) -> Project :
45+ """Helper to load and validate an enabled Project from CLI context."""
46+ configuration = _get_configuration (context )
3047
3148 # Use ConfigurationLoader to load and merge all configuration sources
3249 loader = ConfigurationLoader (configuration .project_configuration .project_root )
@@ -44,6 +61,23 @@ def get_enabled_project(context: typer.Context) -> Project:
4461 return project
4562
4663
64+ @contextlib .contextmanager
65+ def _session_project (context : typer .Context ) -> Generator [Project ]:
66+ """Create an enabled Project wrapped in an OutputSession.
67+
68+ Yields the project with its session already attached. The session
69+ (spinner + log file) is torn down when the ``with`` block exits.
70+ """
71+ project = get_enabled_project (context )
72+ configuration = _get_configuration (context )
73+ verbose = configuration .project_configuration .verbosity > 0
74+ console = Console (width = 120 )
75+
76+ with OutputSession (console , verbose = verbose ) as session :
77+ project .session = session
78+ yield project
79+
80+
4781def _parse_groups_argument (groups : str | None ) -> list [str ] | None :
4882 """Parse pip-style dependency groups from command argument.
4983
@@ -208,12 +242,10 @@ def install(
208242 Raises:
209243 ValueError: If the configuration object is missing
210244 """
211- project = get_enabled_project (context )
212-
213- # Parse groups from pip-style syntax
214245 group_list = _parse_groups_argument (groups )
215246
216- project .install (groups = group_list )
247+ with _session_project (context ) as project :
248+ project .install (groups = group_list )
217249
218250
219251@app .command ()
@@ -236,12 +268,10 @@ def update(
236268 Raises:
237269 ValueError: If the configuration object is missing
238270 """
239- project = get_enabled_project (context )
240-
241- # Parse groups from pip-style syntax
242271 group_list = _parse_groups_argument (groups )
243272
244- project .update (groups = group_list )
273+ with _session_project (context ) as project :
274+ project .update (groups = group_list )
245275
246276
247277@list_app .command ()
@@ -292,8 +322,8 @@ def publish(
292322 Raises:
293323 ValueError: If the configuration object is missing
294324 """
295- project = get_enabled_project (context )
296- project .publish ()
325+ with _session_project (context ) as project :
326+ project .publish ()
297327
298328
299329@app .command ()
@@ -312,8 +342,8 @@ def build(
312342 context: The CLI configuration object
313343 configuration: Optional named configuration
314344 """
315- project = get_enabled_project (context )
316- project .build (configuration = configuration )
345+ with _session_project (context ) as project :
346+ project .build (configuration = configuration )
317347
318348
319349@app .command ()
@@ -332,8 +362,8 @@ def test(
332362 context: The CLI configuration object
333363 configuration: Optional named configuration
334364 """
335- project = get_enabled_project (context )
336- project .test (configuration = configuration )
365+ with _session_project (context ) as project :
366+ project .test (configuration = configuration )
337367
338368
339369@app .command ()
@@ -352,8 +382,8 @@ def bench(
352382 context: The CLI configuration object
353383 configuration: Optional named configuration
354384 """
355- project = get_enabled_project (context )
356- project .bench (configuration = configuration )
385+ with _session_project (context ) as project :
386+ project .bench (configuration = configuration )
357387
358388
359389@app .command ()
@@ -377,5 +407,5 @@ def run(
377407 target: The name of the build target to run
378408 configuration: Optional named configuration
379409 """
380- project = get_enabled_project (context )
381- project .run (target , configuration = configuration )
410+ with _session_project (context ) as project :
411+ project .run (target , configuration = configuration )
0 commit comments