Problem
The codebase contains validation methods that use print() statements for error reporting instead of raising proper exceptions. This creates several issues:
Current pattern in aggregation.py:252-278:
def validate_input(self, data: PolarsDataFrame | PandasDataFrame) -> bool:
"""Validate input data format."""
if missing_cols:
print(f"ERROR: Missing required columns: {missing_cols}")
return False
if not TimeframeConfig.validate_timeframe(tf):
print(f"ERROR: Invalid timeframe '{tf}'")
return False
if len(df) < 2:
print(f"ERROR: Insufficient data points ({len(df)} < 2)")
return False
return True
Problems:
- Silent failures: Calling code gets
False but must check stdout for details
- Not testable: Cannot catch/assert on specific error types in tests
- Not production-ready: Library code should never print to stdout
- Poor separation of concerns: Validation logic mixed with I/O
- Not composable: Cannot differentiate between error types programmatically
Proposed Solution
Replace print() + return False pattern with proper exception raising:
def validate_input(self, data: PolarsDataFrame | PandasDataFrame) -> None:
"""Validate input data format.
Raises:
ValueError: If required columns are missing
ValueError: If timeframe values are invalid
ValueError: If insufficient data points
"""
df = self._convert_to_polars(data)
required_cols = IndicatorSchema.get_required_input_columns()
missing_cols = [col for col in required_cols if col not in df.columns]
if missing_cols:
raise ValueError(f"Missing required columns: {missing_cols}")
unique_timeframes = df["timeframe"].unique().to_list()
for tf in unique_timeframes:
if not TimeframeConfig.validate_timeframe(tf):
raise ValueError(f"Invalid timeframe: {tf}")
if len(df) < 2:
raise ValueError(f"Insufficient data points: {len(df)} (minimum: 2)")
Files to Update
Search for all print( statements in production code (excluding tests):
thestrat/aggregation.py:263,270,275
- Any other
print() statements in thestrat/*.py
Docstring examples with print() are fine - only fix actual error handling.
Benefits
- Proper error handling: Calling code can catch specific exceptions
- Better testing: Can assert on exception types and messages
- Production-ready: No stdout pollution in library code
- Type safety: Return type changes from
bool to None (validates or raises)
- Clearer API: Exceptions document failure modes in docstrings
Implementation Notes
- Change return type from
bool to None
- Update all callers to handle exceptions instead of checking boolean
- Add
Raises: section to docstrings documenting exception types
- Consider using custom exception classes if needed (e.g.,
ValidationError)
- Ensure all tests are updated to expect exceptions
Breaking Change
This is a breaking change - callers checking if validate_input(data): will need to update to:
try:
validate_input(data)
except ValueError as e:
# Handle validation error
pass
Problem
The codebase contains validation methods that use
print()statements for error reporting instead of raising proper exceptions. This creates several issues:Current pattern in
aggregation.py:252-278:Problems:
Falsebut must check stdout for detailsProposed Solution
Replace
print()+return Falsepattern with proper exception raising:Files to Update
Search for all
print(statements in production code (excluding tests):thestrat/aggregation.py:263,270,275print()statements inthestrat/*.pyDocstring examples with
print()are fine - only fix actual error handling.Benefits
booltoNone(validates or raises)Implementation Notes
booltoNoneRaises:section to docstrings documenting exception typesValidationError)Breaking Change
This is a breaking change - callers checking
if validate_input(data):will need to update to: