77(observability, wandb, etc.) into a single pydantic-settings class.
88
99The CLISettings class:
10+
1011- Automatically loads from environment variables
1112- Composes existing settings classes as nested fields
1213- Provides a single source of truth for all CLI configuration
@@ -58,80 +59,115 @@ class CLISettings(BaseSettings):
5859 env_file_encoding = "utf-8" ,
5960 )
6061
61- # Compose existing settings (automatically populated from env vars)
62- # These are NOT loaded from env vars by CLISettings - they load their own
63- # We use default_factory to create fresh instances that read env vars
64- observability : NSSObservabilitySettings = Field (default_factory = NSSObservabilitySettings )
65- wandb : WandbSettings = Field (default_factory = WandbSettings )
62+ observability : NSSObservabilitySettings = Field (
63+ default_factory = NSSObservabilitySettings , description = "Observability sub-settings (log level, format, color)."
64+ )
65+ """Observability sub-settings (log level, format, color).
66+
67+ Loaded from its own environment variables; not populated by ``CLISettings``.
68+ """
69+
70+ wandb : WandbSettings = Field (default_factory = WandbSettings , description = "WandB settings (mode, project, phase)." )
71+ """WandB settings (mode, project, phase).
72+
73+ Loaded from its own environment variables; not populated by ``CLISettings``.
74+ """
6675
67- # CLI-specific settings (paths)
68- # Note: AliasChoices allows both the field name (for CLI kwargs) and env var name to work
6976 url : str | None = Field (default = None , description = "Dataset URL, name, or path to CSV" )
77+ """Dataset URL, name, or path to CSV."""
78+
7079 config_path : str | None = Field (
7180 default = None ,
7281 validation_alias = AliasChoices ("config_path" , "NSS_CONFIG" ),
7382 description = "Path to YAML config file" ,
7483 )
84+ """Path to YAML config file (env variable: ``NSS_CONFIG``)."""
85+
7586 artifact_path : str | None = Field (
7687 default = None ,
7788 validation_alias = AliasChoices ("artifact_path" , "NSS_ARTIFACTS_PATH" ),
7889 description = "Base directory for all runs" ,
7990 )
91+ """Base directory for all runs (env variable: ``NSS_ARTIFACTS_PATH``)."""
92+
8093 run_path : str | None = Field (
8194 default = None ,
8295 description = "Explicit path for this run's output directory" ,
8396 )
97+ """Explicit path for this run's output directory.
98+
99+ When specified, overrides ``artifact_path`` and skips the
100+ ``<project>/<timestamp>`` directory layout.
101+ """
102+
84103 output_file : str | None = Field (
85104 default = None ,
86105 description = "Path to output CSV file" ,
87106 )
107+ """Path to output CSV file, overriding the default workdir location."""
88108
89- # Logging settings (can override observability defaults from CLI)
90109 log_format : Literal ["json" , "plain" ] | None = Field (
91110 default = None ,
92111 validation_alias = AliasChoices ("log_format" , "NSS_LOG_FORMAT" ),
93112 description = "Log format for console output" ,
94113 )
114+ """Log format for console output (env variable: ``NSS_LOG_FORMAT``).
115+
116+ File logging is always JSON regardless of this setting.
117+ """
118+
95119 log_color : bool | None = Field (
96120 default = None ,
97121 description = "Whether to colorize console output" ,
98122 )
123+ """Whether to colorize console output."""
124+
99125 log_file : str | None = Field (
100126 default = None ,
101127 validation_alias = AliasChoices ("log_file" , "NSS_LOG_FILE" ),
102128 description = "Path to log file" ,
103129 )
130+ """Path to log file (env variable: ``NSS_LOG_FILE``)."""
131+
104132 verbose : int = Field (
105133 default = 0 ,
106134 description = "Verbosity level (0=INFO, 1=DEBUG, 2=DEBUG_DEPENDENCIES)" ,
107135 )
136+ """Verbosity level (0=INFO, 1=DEBUG, 2=DEBUG_DEPENDENCIES)."""
108137
109- # WandB settings (can override wandb defaults from CLI)
110138 wandb_mode : WandbMode | None = Field (
111139 default = None ,
112140 description = "WandB mode override" ,
113141 )
142+ """WandB mode override (online, offline, or disabled)."""
143+
114144 wandb_project : str | None = Field (
115145 default = None ,
116146 description = "WandB project override" ,
117147 )
148+ """WandB project name override."""
118149
119- # Synthesis parameter overrides (populated from --data__*, --training__*, etc.)
120150 synthesis_overrides : dict [str , Any ] = Field (
121151 default_factory = dict ,
122152 description = "Nested dict of SafeSynthesizerParameters overrides from CLI" ,
123153 )
154+ """Nested dict of ``SafeSynthesizerParameters`` overrides from CLI.
155+
156+ Populated from ``--data__*``, ``--training__*``, etc. options via
157+ ``parse_overrides``.
158+ """
124159
125160 dataset_registry : str | None = Field (
126161 default = None ,
127162 validation_alias = AliasChoices ("dataset_registry" , "NSS_DATASET_REGISTRY" ),
128163 description = "URL or path to a dataset registry YAML file" ,
129164 )
165+ """URL or path to a dataset registry YAML file (env: ``NSS_DATASET_REGISTRY``)."""
130166
131167 @field_validator ("wandb_mode" , mode = "before" )
132168 @classmethod
133169 def validate_wandb_mode (cls , v : str | WandbMode | None ) -> WandbMode | None :
134- """Convert string to WandbMode enum if needed ."""
170+ """Coerce string or None to `` WandbMode`` enum, passing through enum values unchanged ."""
135171 if v is None :
136172 return None
137173 if isinstance (v , WandbMode ):
@@ -141,7 +177,7 @@ def validate_wandb_mode(cls, v: str | WandbMode | None) -> WandbMode | None:
141177 @field_validator ("verbose" , mode = "before" )
142178 @classmethod
143179 def validate_verbose (cls , v : int | str | None ) -> int :
144- """Ensure verbose is an integer ."""
180+ """Coerce string or None to int, defaulting to 0 ."""
145181 if v is None :
146182 return 0
147183 if isinstance (v , str ):
@@ -167,35 +203,35 @@ def from_cli_kwargs(cls, **kwargs: Any) -> CLISettings:
167203
168204 @property
169205 def effective_artifact_path (self ) -> Path :
170- """The effective artifact path, using default if not set ."""
206+ """Effective artifact path, falling back to ``DEFAULT_ARTIFACTS_PATH`` ."""
171207 if self .artifact_path :
172208 return Path (self .artifact_path )
173209 return DEFAULT_ARTIFACTS_PATH
174210
175211 @property
176212 def effective_log_format (self ) -> Literal ["json" , "plain" ]:
177- """The effective log format, falling back to observability settings."""
213+ """Effective log format, falling back to observability settings."""
178214 if self .log_format is not None :
179215 return self .log_format
180216 return self .observability .nss_log_format or "plain"
181217
182218 @property
183219 def effective_log_color (self ) -> bool :
184- """The effective log color setting, falling back to observability settings."""
220+ """Effective log color setting, falling back to observability settings."""
185221 if self .log_color is not None :
186222 return self .log_color
187223 return self .observability .nss_log_color
188224
189225 @property
190226 def effective_wandb_mode (self ) -> WandbMode :
191- """The effective wandb mode, falling back to wandb settings."""
227+ """Effective wandb mode, falling back to wandb settings."""
192228 if self .wandb_mode is not None :
193229 return self .wandb_mode
194230 return self .wandb .wandb_mode
195231
196232 @property
197233 def effective_wandb_project (self ) -> str | None :
198- """The effective wandb project, falling back to wandb settings."""
234+ """Effective wandb project, falling back to wandb settings."""
199235 if self .wandb_project is not None :
200236 return self .wandb_project
201237 return self .wandb .wandb_project
0 commit comments