docs: add CLI modularization analysis and common error handling utilities
Some checks failed
CLI Tests / test-cli (push) Failing after 12s
Cross-Node Transaction Testing / transaction-test (push) Successful in 4s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Documentation Validation / validate-docs (push) Failing after 11s
Documentation Validation / validate-policies-strict (push) Successful in 4s
Security Scanning / security-scan (push) Successful in 31s
Some checks failed
CLI Tests / test-cli (push) Failing after 12s
Cross-Node Transaction Testing / transaction-test (push) Successful in 4s
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Documentation Validation / validate-docs (push) Failing after 11s
Documentation Validation / validate-policies-strict (push) Successful in 4s
Security Scanning / security-scan (push) Successful in 31s
- Analyze blockchain.py (1,388 lines) and agent.py (793 lines) structure - Correct size estimates from analysis (not 55k/26k lines) - Both files already well-organized with logical command groupings - Create common error handling utilities module for CLI - Add CLIError base class and specialized exceptions - Add handle_cli_error and handle_async_cli_error decorators - Add validation utilities for URLs, addresses, and required fields
This commit is contained in:
181
cli/utils/error_handling.py
Normal file
181
cli/utils/error_handling.py
Normal file
@@ -0,0 +1,181 @@
|
||||
"""
|
||||
Common error handling utilities for AITBC CLI
|
||||
Provides standardized error handling patterns and utilities for CLI commands
|
||||
"""
|
||||
|
||||
import sys
|
||||
from typing import Optional, Callable, Any
|
||||
from functools import wraps
|
||||
from . import error, warning, info
|
||||
|
||||
|
||||
class CLIError(Exception):
|
||||
"""Base exception for CLI errors"""
|
||||
def __init__(self, message: str, exit_code: int = 1):
|
||||
self.message = message
|
||||
self.exit_code = exit_code
|
||||
super().__init__(self.message)
|
||||
|
||||
|
||||
class NetworkError(CLIError):
|
||||
"""Network-related errors"""
|
||||
def __init__(self, message: str):
|
||||
super().__init__(f"Network error: {message}", exit_code=2)
|
||||
|
||||
|
||||
class ConfigurationError(CLIError):
|
||||
"""Configuration-related errors"""
|
||||
def __init__(self, message: str):
|
||||
super().__init__(f"Configuration error: {message}", exit_code=3)
|
||||
|
||||
|
||||
class ValidationError(CLIError):
|
||||
"""Validation errors for user input"""
|
||||
def __init__(self, message: str):
|
||||
super().__init__(f"Validation error: {message}", exit_code=4)
|
||||
|
||||
|
||||
class APIError(CLIError):
|
||||
"""API-related errors"""
|
||||
def __init__(self, message: str, status_code: Optional[int] = None):
|
||||
msg = f"API error: {message}"
|
||||
if status_code:
|
||||
msg += f" (HTTP {status_code})"
|
||||
super().__init__(msg, exit_code=5)
|
||||
|
||||
|
||||
def handle_cli_error(func: Callable) -> Callable:
|
||||
"""
|
||||
Decorator to standardize error handling in CLI commands.
|
||||
|
||||
Catches common exceptions and displays user-friendly error messages.
|
||||
|
||||
Args:
|
||||
func: Function to wrap with error handling
|
||||
|
||||
Returns:
|
||||
Wrapped function with standardized error handling
|
||||
"""
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except CLIError as e:
|
||||
error(e.message)
|
||||
sys.exit(e.exit_code)
|
||||
except KeyboardInterrupt:
|
||||
warning("\nOperation cancelled by user")
|
||||
sys.exit(130)
|
||||
except Exception as e:
|
||||
error(f"Unexpected error: {e}")
|
||||
sys.exit(1)
|
||||
return wrapper
|
||||
|
||||
|
||||
def handle_async_cli_error(func: Callable) -> Callable:
|
||||
"""
|
||||
Decorator to standardize error handling in async CLI commands.
|
||||
|
||||
Args:
|
||||
func: Async function to wrap with error handling
|
||||
|
||||
Returns:
|
||||
Wrapped async function with standardized error handling
|
||||
"""
|
||||
@wraps(func)
|
||||
async def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return await func(*args, **kwargs)
|
||||
except CLIError as e:
|
||||
error(e.message)
|
||||
sys.exit(e.exit_code)
|
||||
except KeyboardInterrupt:
|
||||
warning("\nOperation cancelled by user")
|
||||
sys.exit(130)
|
||||
except Exception as e:
|
||||
error(f"Unexpected error: {e}")
|
||||
sys.exit(1)
|
||||
return wrapper
|
||||
|
||||
|
||||
def safe_execute(
|
||||
operation: Callable,
|
||||
error_message: str = "Operation failed",
|
||||
default_return: Any = None,
|
||||
raise_on_error: bool = False
|
||||
) -> Any:
|
||||
"""
|
||||
Safely execute an operation with standardized error handling.
|
||||
|
||||
Args:
|
||||
operation: Function to execute
|
||||
error_message: Custom error message prefix
|
||||
default_return: Value to return on error (if not raising)
|
||||
raise_on_error: Whether to raise exception on error
|
||||
|
||||
Returns:
|
||||
Operation result or default_return on error
|
||||
|
||||
Raises:
|
||||
Exception: If raise_on_error is True and operation fails
|
||||
"""
|
||||
try:
|
||||
return operation()
|
||||
except Exception as e:
|
||||
if raise_on_error:
|
||||
raise
|
||||
error(f"{error_message}: {e}")
|
||||
return default_return
|
||||
|
||||
|
||||
def validate_required_fields(data: dict, required_fields: list) -> None:
|
||||
"""
|
||||
Validate that required fields are present in data dictionary.
|
||||
|
||||
Args:
|
||||
data: Dictionary to validate
|
||||
required_fields: List of required field names
|
||||
|
||||
Raises:
|
||||
ValidationError: If any required field is missing
|
||||
"""
|
||||
missing_fields = [field for field in required_fields if field not in data or data[field] is None]
|
||||
if missing_fields:
|
||||
raise ValidationError(f"Missing required fields: {', '.join(missing_fields)}")
|
||||
|
||||
|
||||
def validate_url(url: str) -> bool:
|
||||
"""
|
||||
Validate URL format.
|
||||
|
||||
Args:
|
||||
url: URL string to validate
|
||||
|
||||
Returns:
|
||||
True if valid, False otherwise
|
||||
"""
|
||||
import re
|
||||
url_pattern = re.compile(
|
||||
r'^https?://' # http:// or https://
|
||||
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain...
|
||||
r'localhost|' # localhost...
|
||||
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|[/?]\S+)$', re.IGNORECASE)
|
||||
return bool(url_pattern.match(url))
|
||||
|
||||
|
||||
def validate_address(address: str) -> bool:
|
||||
"""
|
||||
Validate Ethereum address format.
|
||||
|
||||
Args:
|
||||
address: Ethereum address string
|
||||
|
||||
Returns:
|
||||
True if valid, False otherwise
|
||||
"""
|
||||
import re
|
||||
# Basic Ethereum address validation (0x followed by 40 hex characters)
|
||||
address_pattern = re.compile(r'^0x[a-fA-F0-9]{40}$')
|
||||
return bool(address_pattern.match(address))
|
||||
127
docs/CLI_MODULARIZATION_ANALYSIS_2026-05-09.md
Normal file
127
docs/CLI_MODULARIZATION_ANALYSIS_2026-05-09.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# CLI Command Modularization Analysis
|
||||
|
||||
**Date:** 2026-05-09
|
||||
**Purpose:** Analyze CLI command structure for modularization opportunities
|
||||
|
||||
---
|
||||
|
||||
## blockchain.py Analysis
|
||||
|
||||
**File Size:** 1,388 lines (not 55k as initially estimated)
|
||||
**Commands:** 17 blockchain commands
|
||||
**Structure:** Well-organized with single command group
|
||||
|
||||
### Current Commands:
|
||||
1. blocks - List recent blocks across chains
|
||||
2. block - Get details of a specific block
|
||||
3. transaction - Get transaction details
|
||||
4. transactions - Get latest transactions on a chain
|
||||
5. status - Get blockchain node status
|
||||
6. sync_status - Get blockchain synchronization status
|
||||
7. peers - List connected peers
|
||||
8. info - Get blockchain information
|
||||
9. supply - Get token supply information
|
||||
10. validators - List blockchain validators
|
||||
11. genesis - Get the genesis block
|
||||
12. head - Get the head block
|
||||
13. send - Send a transaction
|
||||
14. balance - Get account balance
|
||||
15. verify_genesis - Verify genesis block integrity
|
||||
16. genesis_hash - Get genesis hash
|
||||
17. state - Get chain state
|
||||
|
||||
### Modularization Opportunities:
|
||||
**Status:** Already well-organized. Single command group with focused commands. No immediate modularization needed.
|
||||
|
||||
**Recommendation:** Keep as-is. The file size is manageable and commands are logically grouped.
|
||||
|
||||
---
|
||||
|
||||
## agent.py Analysis
|
||||
|
||||
**File Size:** 793 lines (not 26k as initially estimated)
|
||||
**Commands:** 20 commands across 7 command groups
|
||||
**Structure:** Well-organized with logical subgroups
|
||||
|
||||
### Command Groups:
|
||||
1. **agent** (main group)
|
||||
- create - Create a new AI agent workflow
|
||||
- list - List agents
|
||||
- execute - Execute an agent
|
||||
- status - Get execution status
|
||||
- receipt - Get execution receipt
|
||||
|
||||
2. **network** (subgroup)
|
||||
- create - Create agent network
|
||||
- execute - Execute network task
|
||||
- status - Get network status
|
||||
- optimize - Optimize network
|
||||
|
||||
3. **zk** (subgroup)
|
||||
- generate_proof - Generate zero-knowledge proof
|
||||
- verify_proof - Verify zero-knowledge proof
|
||||
- create_receipt - Create cryptographic receipt
|
||||
|
||||
4. **knowledge** (subgroup)
|
||||
- create - Create knowledge graph
|
||||
- add_node - Add node to graph
|
||||
|
||||
5. **bounty** (subgroup)
|
||||
- create - Create bounty
|
||||
- list - List bounties
|
||||
|
||||
6. **dispute** (subgroup)
|
||||
- file - File dispute
|
||||
- vote - Vote on dispute
|
||||
|
||||
7. **learning** (subgroup)
|
||||
- enable - Enable learning
|
||||
- train - Train agent
|
||||
- progress - Get training progress
|
||||
- export - Export model
|
||||
|
||||
8. **contribution** (standalone)
|
||||
- submit_contribution - Submit contribution
|
||||
|
||||
### Modularization Opportunities:
|
||||
**Status:** Already well-organized with logical command groups. Each subgroup handles a specific domain.
|
||||
|
||||
**Recommendation:** Keep as-is. The file structure is already modular with clear separation of concerns.
|
||||
|
||||
---
|
||||
|
||||
## Other CLI Commands
|
||||
|
||||
**Total command files:** 62 command files in `/opt/aitbc/cli/commands/`
|
||||
|
||||
### Large Command Files to Review:
|
||||
- `admin.py`
|
||||
- `advanced_analytics.py`
|
||||
- `ai_trading.py`
|
||||
- `marketplace_advanced.py`
|
||||
- `multi_region_load_balancer.py`
|
||||
|
||||
### Modularization Recommendations:
|
||||
|
||||
**Immediate Actions:**
|
||||
1. Review files > 500 lines for potential modularization
|
||||
2. Ensure consistent error handling patterns across all command files
|
||||
3. Create common utilities for repeated patterns
|
||||
|
||||
**Medium-term Actions:**
|
||||
1. Consider extracting common patterns into utility modules
|
||||
2. Create base classes for similar command structures
|
||||
3. Implement plugin system for extensible commands
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
The initial analysis estimated blockchain.py at 55k lines and agent.py at 26k lines, but actual sizes are:
|
||||
- blockchain.py: 1,388 lines
|
||||
- agent.py: 793 lines
|
||||
|
||||
Both files are already well-organized with logical command groupings and do not require immediate modularization. The focus should shift to:
|
||||
1. Standardizing error handling across all 62 command files
|
||||
2. Creating common utilities for repeated patterns
|
||||
3. Reviewing other large command files for actual modularization needs
|
||||
Reference in New Issue
Block a user