Skip to content

Commit b6689c9

Browse files
refactor(cli): improve user messaging and code documentation
Update config validation error message to be path-agnostic since users can pass config files from any location via command line, not just ini/run_ini/. Remove emojis from user-facing error messages in run_gui and run_train for cleaner output. Update TODO entries to clarify that GUI and multi-processing features need full implementation. Standardize docstring formatting across all CLI modules for consistency. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 79b4fca commit b6689c9

9 files changed

Lines changed: 92 additions & 55 deletions

File tree

fusion/cli/TODO.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
- **Solution**: Create custom CLI error module with specific exception types (SimulationError, ConfigurationError, ResourceError, ValidationError) and user-friendly error messages
99

1010
### GUI Interface Development
11-
- **Issue**: GUI parameter system needs expansion (`parameters/gui.py:26`)
12-
- **Missing**: Window sizing, themes, display options, interactive controls, real-time monitoring
13-
- **Solution**: Design and implement GUI-specific argument structure integrated with existing parameter system
11+
- **Issue**: GUI is not supported at this time and needs to be fully developed
12+
- **Missing**: Complete GUI implementation including window sizing, themes, display options, interactive controls, real-time monitoring, parameter configuration interface
13+
- **Solution**: Design and implement complete GUI system with parameter management integrated with existing CLI infrastructure
1414

1515
### CLI Argument Validation Enhancement
1616
- **Issue**: Need comprehensive CLI argument validation
@@ -21,3 +21,8 @@
2121
- **Issue**: CLI needs improved user experience features
2222
- **Missing**: Tab completion, interactive help, example suggestions, configuration file completion
2323
- **Solution**: Research and implement CLI completion framework with interactive help system
24+
25+
### Multi-Processing Support
26+
- **Issue**: Multi-processing functionality is no longer supported in the current implementation
27+
- **Impact**: Users cannot run parallel simulations across multiple processes, limiting scalability for large-scale experiments
28+
- **Solution**: Re-implement multi-processing support with proper process management, configuration handling, and result aggregation

fusion/cli/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
"""fusion.cli: Command-line interface entry points and argument parsing.
1+
"""
2+
fusion.cli: Command-line interface entry points and argument parsing.
23
34
Provides a clean CLI architecture following the FUSION refactor plan with
45
modern Python practices, comprehensive error handling, and maintainable code

fusion/cli/config_setup.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333

3434

3535
def normalize_config_path(config_path: str) -> str:
36-
"""Normalize the config file path.
36+
"""
37+
Normalize the config file path.
3738
3839
:param config_path: Path to config file (relative or absolute)
3940
:type config_path: str
@@ -55,7 +56,8 @@ def normalize_config_path(config_path: str) -> str:
5556

5657

5758
def setup_config_from_cli(args: Any) -> dict[str, Any]:
58-
"""Set up configuration from command line input.
59+
"""
60+
Set up configuration from command line input.
5961
6062
:param args: Parsed command line arguments
6163
:type args: Any
@@ -163,8 +165,8 @@ def _validate_config_structure(config: ConfigParser) -> None:
163165
if not config.has_section(REQUIRED_SECTION):
164166
create_directory(CONFIG_DIR_PATH)
165167
raise ConfigParseError(
166-
f"Missing '{REQUIRED_SECTION}' section in config file. "
167-
"Ensure config.ini exists in ini/run_ini/."
168+
f"Missing required '{REQUIRED_SECTION}' section in config file. "
169+
"Ensure your config file exists and contains all required options."
168170
)
169171

170172

@@ -192,7 +194,8 @@ def _resolve_config_path(config_path: str | None) -> str:
192194
def load_config(
193195
config_path: str | None, args_dict: dict[str, Any] | None = None
194196
) -> dict[str, Any]:
195-
"""Load an existing config from a config file.
197+
"""
198+
Load an existing config from a config file.
196199
197200
This function handles the complete configuration loading process:
198201
1. Resolves and validates the config file path
@@ -313,7 +316,8 @@ def _find_category(
313316

314317

315318
def load_and_validate_config(args: Any) -> dict[str, Any]:
316-
"""Load and validate configuration from CLI arguments.
319+
"""
320+
Load and validate configuration from CLI arguments.
317321
318322
:param args: Parsed command line arguments
319323
:type args: Any
@@ -325,15 +329,17 @@ def load_and_validate_config(args: Any) -> dict[str, Any]:
325329

326330

327331
class ConfigManager:
328-
"""Centralized configuration management for FUSION simulator.
332+
"""
333+
Centralized configuration management for FUSION simulator.
329334
330335
Provides a unified interface for accessing configuration from both
331336
INI files and command-line arguments, with proper validation and
332337
error handling. Supports multi-threaded configuration sections.
333338
"""
334339

335340
def __init__(self, config_dict: dict[str, Any], args: Any) -> None:
336-
"""Initialize ConfigManager with configuration dictionary and arguments.
341+
"""
342+
Initialize ConfigManager with configuration dictionary and arguments.
337343
338344
:param config_dict: Parsed configuration dictionary
339345
:type config_dict: Dict[str, Any]
@@ -352,7 +358,8 @@ def _validate_config(self) -> None:
352358

353359
@classmethod
354360
def from_args(cls, args: Any) -> "ConfigManager":
355-
"""Load arguments from command line input.
361+
"""
362+
Load arguments from command line input.
356363
357364
:param args: Parsed command line arguments
358365
:type args: Any
@@ -373,7 +380,8 @@ def from_args(cls, args: Any) -> "ConfigManager":
373380
def from_file(
374381
cls, config_path: str, args_dict: dict[str, Any] | None = None
375382
) -> "ConfigManager":
376-
"""Create ConfigManager from config file path.
383+
"""
384+
Create ConfigManager from config file path.
377385
378386
:param config_path: Path to configuration file
379387
:type config_path: str
@@ -388,15 +396,17 @@ def from_file(
388396
return cls(config_dict, args)
389397

390398
def as_dict(self) -> dict[str, Any]:
391-
"""Get config as dict.
399+
"""
400+
Get config as dict.
392401
393402
:return: Configuration dictionary
394403
:rtype: Dict[str, Any]
395404
"""
396405
return self._config
397406

398407
def get(self, thread: str = DEFAULT_THREAD_NAME) -> dict[str, Any]:
399-
"""Return a single config thread.
408+
"""
409+
Return a single config thread.
400410
401411
:param thread: Thread identifier, defaults to 's1'
402412
:type thread: str
@@ -409,7 +419,8 @@ def get(self, thread: str = DEFAULT_THREAD_NAME) -> dict[str, Any]:
409419
def get_value(
410420
self, key: str, thread: str = DEFAULT_THREAD_NAME, default: Any = None
411421
) -> Any:
412-
"""Get a specific configuration value.
422+
"""
423+
Get a specific configuration value.
413424
414425
:param key: Configuration key
415426
:type key: str
@@ -424,7 +435,8 @@ def get_value(
424435
return thread_config.get(key, default)
425436

426437
def has_thread(self, thread: str) -> bool:
427-
"""Check if a thread exists in configuration.
438+
"""
439+
Check if a thread exists in configuration.
428440
429441
:param thread: Thread identifier
430442
:type thread: str
@@ -434,15 +446,17 @@ def has_thread(self, thread: str) -> bool:
434446
return thread in self._config
435447

436448
def get_threads(self) -> list[str]:
437-
"""Get list of all configured threads.
449+
"""
450+
Get list of all configured threads.
438451
439452
:return: List of thread identifiers
440453
:rtype: List[str]
441454
"""
442455
return list(self._config.keys())
443456

444457
def get_args(self) -> Any:
445-
"""Get args.
458+
"""
459+
Get args.
446460
447461
:return: Command line arguments
448462
:rtype: Any

fusion/cli/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
"""CLI-specific constants for FUSION command-line interfaces.
1+
"""
2+
CLI-specific constants for FUSION command-line interfaces.
23
34
Provides shared constants used across CLI entry points including exit codes,
45
argument configurations, and common CLI settings to ensure consistency

fusion/cli/main_parser.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222

2323
def build_main_argument_parser() -> ArgumentParser:
24-
"""Build the main CLI argument parser with all subcommands configured.
24+
"""
25+
Build the main CLI argument parser with all subcommands configured.
2526
2627
Creates the primary argument parser that handles all CLI interactions
2728
for the FUSION simulator, including subcommands for different operations
@@ -34,7 +35,8 @@ def build_main_argument_parser() -> ArgumentParser:
3435

3536

3637
def create_training_argument_parser() -> Namespace:
37-
"""Create and parse arguments for training simulations (RL or ML).
38+
"""
39+
Create and parse arguments for training simulations (RL or ML).
3840
3941
Builds a specialized argument parser configured for machine learning
4042
and reinforcement learning training workflows. Includes all necessary
@@ -57,7 +59,8 @@ def create_training_argument_parser() -> Namespace:
5759

5860

5961
def create_gui_argument_parser() -> Namespace:
60-
"""Create and parse arguments for GUI-based simulator interface.
62+
"""
63+
Create and parse arguments for GUI-based simulator interface.
6164
6265
Builds a specialized argument parser configured for graphical user
6366
interface operations. Includes GUI-specific settings, debug options,
@@ -75,7 +78,8 @@ def create_gui_argument_parser() -> Namespace:
7578

7679
# Backward compatibility functions
7780
def build_parser() -> ArgumentParser:
78-
"""Legacy function name for building main argument parser.
81+
"""
82+
Legacy function name for building main argument parser.
7983
8084
:return: Configured main parser
8185
:rtype: ArgumentParser
@@ -85,7 +89,8 @@ def build_parser() -> ArgumentParser:
8589

8690

8791
def get_train_args() -> Namespace:
88-
"""Legacy function name for creating training argument parser.
92+
"""
93+
Legacy function name for creating training argument parser.
8994
9095
:return: Parsed arguments for training
9196
:rtype: Namespace
@@ -95,7 +100,8 @@ def get_train_args() -> Namespace:
95100

96101

97102
def get_gui_args() -> Namespace:
98-
"""Legacy function name for creating GUI argument parser.
103+
"""
104+
Legacy function name for creating GUI argument parser.
99105
100106
:return: Parsed arguments for GUI
101107
:rtype: Namespace

fusion/cli/run_gui.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
"""CLI entry point for launching the FUSION GUI interface.
1+
"""
2+
CLI entry point for launching the FUSION GUI interface.
23
34
This module provides the command-line interface for launching the graphical
45
user interface. It handles GUI dependency validation, display configuration,
@@ -15,7 +16,8 @@
1516

1617

1718
def main() -> int:
18-
"""Launch the FUSION GUI interface.
19+
"""
20+
Launch the FUSION GUI interface.
1921
2022
Parses command line arguments and delegates GUI launch operations
2123
to the appropriate GUI pipeline module. Handles user interruptions
@@ -32,21 +34,21 @@ def main() -> int:
3234

3335
except KeyboardInterrupt:
3436
logger.info("GUI launch interrupted by user")
35-
print("\n🛑 GUI launch interrupted by user") # User-facing message
37+
print("\nGUI launch interrupted by user") # User-facing message
3638
return INTERRUPT_EXIT_CODE
3739
except (ImportError, ModuleNotFoundError) as e:
3840
logger.error(f"Missing GUI dependencies: {e}")
39-
print(f"Missing GUI dependencies: {e}") # User-facing message
40-
print("💡 Try installing GUI dependencies with: pip install -e .[gui]")
41+
print(f"Missing GUI dependencies: {e}") # User-facing message
42+
print("Try installing GUI dependencies with: pip install -e .[gui]")
4143
return ERROR_EXIT_CODE
4244
except (OSError, RuntimeError) as e:
4345
logger.error(f"GUI framework error: {e}")
44-
print(f"GUI framework error: {e}") # User-facing message
45-
print("💡 Check your display settings and GUI framework installation")
46+
print(f"GUI framework error: {e}") # User-facing message
47+
print("Check your display settings and GUI framework installation")
4648
return ERROR_EXIT_CODE
4749
except (ValueError, TypeError) as e:
4850
logger.error(f"Configuration error launching GUI: {e}")
49-
print(f"Configuration error launching GUI: {e}") # User-facing message
51+
print(f"Configuration error launching GUI: {e}") # User-facing message
5052
return ERROR_EXIT_CODE
5153

5254
return SUCCESS_EXIT_CODE

fusion/cli/run_sim.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
"""CLI entry point for running simulations.
1+
"""
2+
CLI entry point for running simulations.
23
34
Follows architecture best practice: entry points should have no logic.
45
"""
@@ -15,7 +16,8 @@
1516

1617

1718
def main(stop_flag: Any = None) -> int:
18-
"""Entry point for running simulations from the command line.
19+
"""
20+
Entry point for running simulations from the command line.
1921
2022
Delegates all logic to appropriate modules following the clean architecture
2123
pattern where entry points contain minimal logic and delegate to pipelines.

fusion/cli/run_train.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
"""CLI entry point for training FUSION agents (RL or ML).
1+
"""
2+
CLI entry point for training FUSION agents (RL or ML).
23
34
This module provides the command-line interface for training machine learning
45
and reinforcement learning agents. It supports multiple training algorithms
@@ -15,7 +16,8 @@
1516

1617

1718
def main() -> int:
18-
"""Train FUSION agents using RL or ML algorithms.
19+
"""
20+
Train FUSION agents using RL or ML algorithms.
1921
2022
Parses command line arguments and delegates training execution to the
2123
appropriate training pipeline module. Supports both reinforcement learning
@@ -32,30 +34,29 @@ def main() -> int:
3234

3335
except KeyboardInterrupt:
3436
logger.info("Training interrupted by user")
35-
print("\n🛑 Training interrupted by user") # User-facing message
36-
print("💾 Training progress has been saved where possible")
37+
print("\nTraining interrupted by user") # User-facing message
38+
print("Training progress has been saved where possible")
3739
return INTERRUPT_EXIT_CODE
3840
except (ImportError, ModuleNotFoundError) as e:
3941
logger.error(f"Missing training dependencies: {e}")
40-
print(f"Missing training dependencies: {e}") # User-facing message
41-
print("💡 Try installing ML/RL dependencies with: pip install -e .[ml,rl]")
42+
print(f"Missing training dependencies: {e}") # User-facing message
43+
print("Try installing ML/RL dependencies with: pip install -e .[ml,rl]")
4244
return ERROR_EXIT_CODE
4345
except OSError as e:
4446
logger.error(f"File system error during training: {e}")
45-
print(f"File system error during training: {e}") # User-facing message
46-
print("💡 Check file permissions and available disk space for model storage")
47+
print(f"File system error during training: {e}") # User-facing message
48+
print("Check file permissions and available disk space for model storage")
4749
return ERROR_EXIT_CODE
4850
except (ValueError, TypeError) as e:
4951
logger.error(f"Training configuration error: {e}")
50-
print(f"Training configuration error: {e}") # User-facing message
51-
print("💡 Check your training parameters and agent configuration")
52+
print(f"Training configuration error: {e}") # User-facing message
53+
print("Check your training parameters and agent configuration")
5254
return ERROR_EXIT_CODE
5355
except (RuntimeError, MemoryError) as e:
5456
logger.error(f"Training runtime error: {e}")
55-
print(f"Training runtime error: {e}") # User-facing message
57+
print(f"Training runtime error: {e}") # User-facing message
5658
print(
57-
"💡 Consider reducing batch size, model complexity, "
58-
"or check system resources"
59+
"Consider reducing batch size, model complexity, or check system resources"
5960
)
6061
return ERROR_EXIT_CODE
6162

0 commit comments

Comments
 (0)