11import asyncio
2- import json
32import os
4- import pathlib
53from dataclasses import dataclass
64from functools import cached_property
7- from typing import TYPE_CHECKING , Any , Literal
5+ from typing import TYPE_CHECKING
86
9- from aoc_main import _logging , _solvers , _types
7+ from aoc_main import _cmake_presets , _logging , _solvers , _types
108
119if TYPE_CHECKING :
10+ import pathlib
1211 from collections .abc import Iterable
1312
1413_logger = _logging .logger
@@ -57,51 +56,31 @@ def __init__(self, target: str, returncode: int) -> None:
5756
5857
5958class _CMakeConfigResolver :
60- @cached_property
61- def configure_preset_name (self ) -> str :
62- return self ._resolve_configure_preset ()
59+ """Selects which CMake presets to use, then defers parsing to ``CMakePresets``.
60+
61+ The *selection* (which configure or workflow preset to use, read from
62+ environment variables) lives here; the *parsing* of the preset files lives
63+ in :mod:`aoc_main._cmake_presets`.
64+ """
6365
6466 @cached_property
6567 def solver_root_dir (self ) -> pathlib .Path :
6668 return _solvers .get_solver_root_dir (_solvers .Solver .Cpp )
6769
6870 @cached_property
69- def binary_dir (self ) -> pathlib . Path :
70- return self . _resolve_binary_dir ( )
71+ def _presets (self ) -> _cmake_presets . CMakePresets :
72+ return _cmake_presets . CMakePresets ( self . solver_root_dir )
7173
7274 @cached_property
73- def _cmake_user_presets (self ) -> dict [str , Any ]:
74- return self ._load_cmake_preset_file (
75- self .solver_root_dir / "CMakeUserPresets.json"
76- )
75+ def configure_preset_name (self ) -> str :
76+ return self ._resolve_configure_preset ()
7777
7878 @cached_property
79- def _cmake_presets (self ) -> dict [str , Any ]:
80- return self ._load_cmake_preset_file (self .solver_root_dir / "CMakePresets.json" )
81-
82- @staticmethod
83- def _load_cmake_preset_file (preset_file : pathlib .Path ) -> dict [str , Any ]:
84- if not preset_file .exists ():
85- return {}
86- return json .loads (preset_file .read_text ())
87-
88- def _get_preset (
89- self ,
90- preset_type : Literal ["build" , "configure" , "workflow" ],
91- name : str ,
92- ) -> Any | None : # noqa: ANN401
93- for presets in (self ._cmake_user_presets , self ._cmake_presets ):
94- preset = next (
95- (
96- preset
97- for preset in presets .get (f"{ preset_type } Presets" , {})
98- if preset ["name" ] == name
99- ),
100- None ,
101- )
102- if preset is not None :
103- return preset
104- return None
79+ def binary_dir (self ) -> pathlib .Path :
80+ try :
81+ return self ._presets .binary_dir (self .configure_preset_name )
82+ except _cmake_presets .CMakePresetError as e :
83+ raise _CppSolverConfigureError (str (e )) from e
10584
10685 def _resolve_configure_preset (self ) -> str :
10786 configure_preset_name = os .environ .get (_ENV_PRESET_CONFIGURE )
@@ -117,57 +96,16 @@ def _resolve_configure_preset(self) -> str:
11796 return _DEFAULT_CONFIGURE_PRESET
11897
11998 _logger .debug ("Using workflow preset: %s" , workflow_preset_name )
120- workflow_preset = self ._get_preset ("workflow" , workflow_preset_name )
121- if workflow_preset is None :
122- msg = f"Requested workflow preset not found: { workflow_preset_name } "
123- raise _CppSolverConfigureError (msg )
124-
12599 try :
126- configure_preset_name = next (
127- step ["name" ]
128- for step in workflow_preset ["steps" ]
129- if step ["type" ] == "configure"
100+ configure_preset_name = self ._presets .workflow_configure_preset_name (
101+ workflow_preset_name
130102 )
131- except KeyError as e :
132- msg = (
133- f"Invalid CMake Preset json for workflow preset: { workflow_preset_name } "
134- )
135- raise _CppSolverConfigureError (msg ) from e
136- except StopIteration :
137- msg = f"No configure step found for workflow: { workflow_preset_name } "
138- raise _CppSolverConfigureError (msg ) from None
103+ except _cmake_presets .CMakePresetError as e :
104+ raise _CppSolverConfigureError (str (e )) from e
139105
140106 _logger .debug ("Using configure preset: %s" , configure_preset_name )
141- assert configure_preset_name is not None
142107 return configure_preset_name
143108
144- def _resolve_binary_dir (self ) -> pathlib .Path :
145- configure_preset_names = [self .configure_preset_name ]
146- while configure_preset_names :
147- configure_preset_name = configure_preset_names .pop (0 )
148- configure_preset = self ._get_preset ("configure" , configure_preset_name )
149- if configure_preset is None :
150- msg = f"Configure preset not found: { configure_preset_name } "
151- raise _CppSolverConfigureError (msg )
152-
153- binary_dir = configure_preset .get ("binaryDir" )
154- if binary_dir is not None :
155- _logger .debug (
156- "Found binaryDir from preset %s: %s" ,
157- configure_preset_name ,
158- binary_dir ,
159- )
160- return pathlib .Path (binary_dir )
161-
162- _logger .debug (
163- "Binary dir not found for preset %s. Checking inherited presets" ,
164- configure_preset_name ,
165- )
166- configure_preset_names .extend (configure_preset .get ("inherits" , []))
167-
168- error = f"binaryDir not found for configure preset { self .configure_preset_name } "
169- raise _CppSolverConfigureError (error )
170-
171109
172110class SolverCpp :
173111 def __init__ (self , solver_ids : Iterable [_solvers .SolverId ]) -> None :
0 commit comments