e5a142ef76
The generate prompt only received the analyze_requirements summary,
which often compressed the file-by-file DoD into a brief paragraph.
The LLM then produced 1 file instead of the 5-6 specified.
Fix: added {original_prompt} variable to the generate prompt template
so the LLM sees both the architecture analysis AND the original DoD
with explicit file listings. Also strengthened the instruction to
"output ALL files mentioned in the Definition of Done."
Verified: sim10 (CSV Analyzer) now produces 6 files matching DoD
(loader.py, analyzer.py, reporter.py, cli.py, requirements.txt).
187 lines
5.9 KiB
Python
187 lines
5.9 KiB
Python
"""Command-line interface for CSV data analysis tool."""
|
|
|
|
import argparse
|
|
import sys
|
|
import os
|
|
from typing import List, Optional
|
|
|
|
from loader import CSVLoader
|
|
from analyzer import DataAnalyzer
|
|
from reporter import ReportFormatter
|
|
|
|
|
|
def parse_arguments():
|
|
"""Parse command-line arguments."""
|
|
parser = argparse.ArgumentParser(
|
|
description="CSV Data Analysis Tool - Comprehensive statistical analysis of CSV files",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Examples:
|
|
python cli.py --file data.csv
|
|
python cli.py --file data.csv --output report.txt
|
|
python cli.py --file data.csv --columns age,salary,score
|
|
python cli.py --file data.csv --filter "age > 25" "salary >= 50000"
|
|
python cli.py --file data.csv --columns age,salary --filter "age > 18" --output analysis.txt
|
|
"""
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--file', '-f',
|
|
type=str,
|
|
required=True,
|
|
help='Path to the CSV file to analyze'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--columns', '-c',
|
|
type=str,
|
|
help='Comma-separated list of columns to analyze (default: all columns)'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--filter',
|
|
type=str,
|
|
nargs='+',
|
|
help='Filter conditions (e.g., "age > 25" "name contains John"). Supported operators: ==, !=, >, >=, <, <=, contains'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--output', '-o',
|
|
type=str,
|
|
help='Output file path for the report (default: print to console)'
|
|
)
|
|
|
|
return parser.parse_args()
|
|
|
|
|
|
def validate_arguments(args):
|
|
"""Validate command-line arguments."""
|
|
# Check if file exists
|
|
if not os.path.exists(args.file):
|
|
print(f"Error: File '{args.file}' not found.")
|
|
sys.exit(1)
|
|
|
|
# Validate file extension
|
|
if not args.file.lower().endswith(('.csv', '.txt')):
|
|
print("Warning: File does not have a .csv extension. Proceeding anyway...")
|
|
|
|
# Parse columns if provided
|
|
columns = None
|
|
if args.columns:
|
|
columns = [col.strip() for col in args.columns.split(',') if col.strip()]
|
|
if not columns:
|
|
print("Error: Invalid columns specification.")
|
|
sys.exit(1)
|
|
|
|
# Validate output path
|
|
if args.output:
|
|
output_dir = os.path.dirname(os.path.abspath(args.output))
|
|
if not os.path.exists(output_dir):
|
|
print(f"Error: Output directory '{output_dir}' does not exist.")
|
|
sys.exit(1)
|
|
|
|
return columns
|
|
|
|
|
|
def main():
|
|
"""Main function to orchestrate the analysis pipeline."""
|
|
try:
|
|
# Parse and validate arguments
|
|
args = parse_arguments()
|
|
columns = validate_arguments(args)
|
|
|
|
print("CSV Data Analysis Tool")
|
|
print("=" * 50)
|
|
|
|
# Initialize loader
|
|
loader = CSVLoader()
|
|
|
|
# Load CSV file
|
|
print(f"Loading file: {args.file}")
|
|
try:
|
|
df = loader.load_csv(args.file, columns=columns)
|
|
except Exception as e:
|
|
print(f"Error loading CSV file: {e}")
|
|
sys.exit(1)
|
|
|
|
# Apply filters if specified
|
|
if args.filter:
|
|
print(f"Applying filters: {args.filter}")
|
|
try:
|
|
df = loader.apply_filters(df, args.filter)
|
|
if len(df) == 0:
|
|
print("Warning: All rows were filtered out. No data to analyze.")
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
print(f"Error applying filters: {e}")
|
|
sys.exit(1)
|
|
|
|
# Initialize analyzer
|
|
print("Performing statistical analysis...")
|
|
analyzer = DataAnalyzer(df)
|
|
|
|
# Run analysis
|
|
try:
|
|
analysis_results = analyzer.run_full_analysis()
|
|
except Exception as e:
|
|
print(f"Error during analysis: {e}")
|
|
sys.exit(1)
|
|
|
|
# Generate report
|
|
print("Generating report...")
|
|
try:
|
|
formatter = ReportFormatter()
|
|
report_text = formatter.generate_report(
|
|
analysis_results=analysis_results,
|
|
file_path=args.file,
|
|
filters_applied=args.filter
|
|
)
|
|
except Exception as e:
|
|
print(f"Error generating report: {e}")
|
|
sys.exit(1)
|
|
|
|
# Output report
|
|
if args.output:
|
|
try:
|
|
formatter.save_report(report_text, args.output)
|
|
print(f"\nAnalysis complete! Report saved to: {args.output}")
|
|
except Exception as e:
|
|
print(f"Error saving report: {e}")
|
|
sys.exit(1)
|
|
else:
|
|
print("\n" + "=" * 50)
|
|
print(report_text)
|
|
|
|
# Print summary
|
|
basic_info = analysis_results.get('basic_info', {})
|
|
print(f"\nSummary:")
|
|
print(f" Rows analyzed: {basic_info.get('total_rows', 'N/A'):,}")
|
|
print(f" Columns analyzed: {basic_info.get('total_columns', 'N/A')}")
|
|
|
|
if args.filter:
|
|
print(f" Filters applied: {len(args.filter)}")
|
|
|
|
outliers = analysis_results.get('outliers', {})
|
|
total_outliers = sum(info.get('outlier_count', 0) for info in outliers.values()
|
|
if isinstance(info, dict) and 'outlier_count' in info)
|
|
if total_outliers > 0:
|
|
print(f" Total outliers detected: {total_outliers}")
|
|
|
|
correlations = analysis_results.get('correlations', {})
|
|
if isinstance(correlations, dict) and 'strong_correlations' in correlations:
|
|
strong_corr_count = len(correlations['strong_correlations'])
|
|
if strong_corr_count > 0:
|
|
print(f" Strong correlations found: {strong_corr_count}")
|
|
|
|
print("\nAnalysis completed successfully!")
|
|
|
|
except KeyboardInterrupt:
|
|
print("\nOperation cancelled by user.")
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
print(f"Unexpected error: {e}")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |