1+ from __future__ import annotations
2+
3+ from pathlib import Path
4+ from typing import Any , Mapping
5+ from faker import Faker
6+
7+ from clevertools import configure , log , read_json , read_toml , write_json , write_toml
8+ from ..paths import PATHS
9+
10+
11+ def _deep_merge (base : dict [str , Any ], incoming : Mapping [str , Any ]) -> dict [str , Any ]:
12+ for key , value in incoming .items ():
13+ current = base .get (key )
14+
15+ if isinstance (current , dict ) and isinstance (value , Mapping ):
16+ base [key ] = _deep_merge (dict (current ), value )
17+ continue
18+
19+ if isinstance (value , Mapping ):
20+ base [key ] = _deep_merge ({}, value )
21+ continue
22+
23+ base [key ] = value
24+
25+ return base
26+
27+
28+ class ConfigView :
29+ def __init__ (self , data : Mapping [str , Any ]) -> None :
30+ self ._data = dict (data )
31+
32+ def __getattr__ (self , name : str ) -> Any :
33+ try :
34+ value = self ._data [name ]
35+ except KeyError as exc :
36+ raise AttributeError (f"Config key not found: { name } " ) from exc
37+ return self ._wrap (value )
38+
39+ def get (self , path : str , default : Any = None ) -> Any :
40+ current : Any = self
41+
42+ for part in path .split ("." ):
43+ if not part :
44+ return default
45+
46+ if isinstance (current , ConfigView ):
47+ if part not in current ._data :
48+ return default
49+ current = current ._data [part ]
50+ current = self ._wrap (current )
51+ continue
52+
53+ if isinstance (current , Mapping ):
54+ if part not in current :
55+ return default
56+ current = current [part ]
57+ continue
58+
59+ return default
60+
61+ return current
62+
63+ @staticmethod
64+ def _wrap (value : Any ) -> Any :
65+ if isinstance (value , Mapping ):
66+ return ConfigView (value )
67+ return value
68+
69+
70+ def load_config_files (* file_paths : Path | str ) -> ConfigView :
71+ merged : dict [str , Any ] = {}
72+
73+ for file_path in file_paths :
74+ loaded = read_toml (file_path , on_error = "raise" )
75+ if loaded is None :
76+ continue
77+ merged = _deep_merge (merged , loaded )
78+
79+ return ConfigView (merged )
80+
81+
82+ class StaticTestRunner :
83+ def __init__ (self ) -> None :
84+ self .fake = Faker ("de_DE" )
85+ self .tmp_settings_toml : Path = PATHS .CACHE_FOLDER / "settings.toml"
86+ self .tmp_content_toml : Path = PATHS .CACHE_FOLDER / "content.toml"
87+ self .tmp_json : Path = PATHS .CACHE_FOLDER / "users.json"
88+
89+ def configure_logger (self ) -> None :
90+ configure (
91+ error_mode = "log" ,
92+ logger_overrides = {
93+ "name" : "ClevertoolsStaticTest" ,
94+ "level" : "INFO" ,
95+ "format_preset" : "datetime" ,
96+ "file_logging_enabled" : True ,
97+ "file_log_path" : PATHS .CACHE_FOLDER / "clevertools_static_test.log" ,
98+ "use_colors" : True
99+ },
100+ )
101+ log .info ("Logger configured for static IO test run." )
102+
103+ def build_settings_payload (self ) -> dict [str , Any ]:
104+ log .info ("Building settings TOML payload for configuration test data." )
105+ payload = {
106+ "program" : {
107+ "enviroment" : "release" ,
108+ "wait_for_enter" : True ,
109+ },
110+ "logger" : {
111+ "name" : "ClevertoolsStaticTest" ,
112+ "level" : "INFO" ,
113+ "format_preset" : "datetime" ,
114+ "file_logging_enabled" : True ,
115+ "file_log_path" : str (PATHS .CACHE_FOLDER / "clevertools_static_test.log" ),
116+ },
117+ "pipelines" : {
118+ "ai" : {
119+ "enabled" : True ,
120+ "cleanup_temp" : True ,
121+ }
122+ },
123+ }
124+ log .info ("Settings TOML payload prepared successfully." )
125+ return payload
126+
127+ def build_content_payload (self ) -> dict [str , Any ]:
128+ log .info ("Building content TOML payload for configuration merge test." )
129+ payload = {
130+ "program" : {
131+ "paths" : [
132+ str (PATHS .CACHE_FOLDER / "hello" ),
133+ str (PATHS .CACHE_FOLDER / "world" ),
134+ str (PATHS .CACHE_FOLDER / "my" ),
135+ str (PATHS .CACHE_FOLDER / "name" ),
136+ str (PATHS .CACHE_FOLDER / "is" ),
137+ str (PATHS .CACHE_FOLDER / "b7binw13" ),
138+ str (PATHS .CACHE_FOLDER / "yayxD" ),
139+ ],
140+ },
141+ "pipelines" : {
142+ "ai" : {
143+ "ai_model" : "gpt-oss:20B" ,
144+ "valid_local_ai_models" : [
145+ "gpt-oss:20B" ,
146+ "mistral-small3.1:24b" ,
147+ ],
148+ }
149+ },
150+ }
151+ log .info (f"Content TOML payload prepared with { len (payload ['program' ]['paths' ])} configured paths." )
152+ return payload
153+
154+ def generate_user (self ) -> dict [str , Any ]:
155+ return {
156+ "name" : self .fake .name (),
157+ "email" : self .fake .email (),
158+ "contacts" : {
159+ self .fake .user_name (): {
160+ "nickname" : self .fake .first_name (),
161+ "email" : self .fake .email (),
162+ "phone" : self .fake .phone_number (),
163+ }
164+ },
165+ }
166+
167+ def build_users_payload (self , count : int = 10 ) -> list [dict [str , Any ]]:
168+ log .info (f"Generating JSON payload with { count } fake users." )
169+ users = [self .generate_user () for _ in range (count )]
170+ log .info (f"JSON payload prepared with { len (users )} generated users." )
171+ return users
172+
173+ def run (self ) -> None :
174+ self .configure_logger ()
175+ log .info ("Starting static IO test run." )
176+ log .info (
177+ f"Using test files SETTINGS={ self .tmp_settings_toml } , CONTENT={ self .tmp_content_toml } , JSON={ self .tmp_json } ."
178+ )
179+
180+ settings_payload = self .build_settings_payload ()
181+ content_payload = self .build_content_payload ()
182+ users_payload = self .build_users_payload ()
183+
184+ log .info (f"Writing settings TOML test data to { self .tmp_settings_toml } ." )
185+ write_toml (
186+ self .tmp_settings_toml ,
187+ settings_payload ,
188+ create_if_missing = True ,
189+ on_error = "raise" ,
190+ )
191+ log .info (f"Settings TOML test data written successfully to { self .tmp_settings_toml } ." )
192+
193+ log .info (f"Writing content TOML test data to { self .tmp_content_toml } ." )
194+ write_toml (
195+ self .tmp_content_toml ,
196+ content_payload ,
197+ create_if_missing = True ,
198+ on_error = "raise" ,
199+ )
200+ log .info (f"Content TOML test data written successfully to { self .tmp_content_toml } ." )
201+
202+ log .info ("Loading merged configuration from both TOML files." )
203+ config = load_config_files (self .tmp_settings_toml , self .tmp_content_toml )
204+ log .info (
205+ "Merged config loaded: pipelines.ai.enabled=%s, pipelines.ai.ai_model=%s" ,
206+ config .pipelines .ai .enabled ,
207+ config .pipelines .ai .ai_model ,
208+ )
209+
210+ log .info (f"Writing JSON test data to { self .tmp_json } ." )
211+ write_json (self .tmp_json , users_payload , create_if_missing = True , on_error = "raise" )
212+ log .info (f"JSON test data written successfully to { self .tmp_json } ." )
213+
214+ log .info (f"Reading JSON test data from { self .tmp_json } ." )
215+ read_json (self .tmp_json , on_error = "raise" )
216+ log .info (f"JSON test data read successfully from { self .tmp_json } ." )
217+
218+ log .info ("Static IO test run finished successfully." )
219+
220+
221+ if __name__ == "__main__" :
222+ StaticTestRunner ().run ()
0 commit comments