Priyanshi Saxena commited on
Commit
fb7643a
Β·
1 Parent(s): 06a2cb8

fix: Add comprehensive syntax validation and debugging

Browse files

- Fix unterminated f-string literals in app.py exception handlers
- Add validate_startup.py script for comprehensive pre-startup validation
- Add dev_check.sh script for development-time syntax checking
- Integrate startup validation into Docker container
- Validate Python syntax, imports, configuration, and environment
- Prevent syntax errors from reaching production deployment

Fixes:
- Unterminated f-string in asyncio.TimeoutError exception handler
- Unterminated f-string in general Exception handler
- Add comprehensive error prevention system

Files changed (4) hide show
  1. Dockerfile +2 -0
  2. app.py +2 -16
  3. dev_check.sh +48 -0
  4. validate_startup.py +177 -0
Dockerfile CHANGED
@@ -78,6 +78,8 @@ echo "βœ… Model llama3.1:8b ready!"\n\
78
  \n\
79
  # Start the main application\n\
80
  echo "🌐 Starting Web3 Research Co-Pilot web application..."\n\
 
 
81
  python app.py &\n\
82
  APP_PID=$!\n\
83
  \n\
 
78
  \n\
79
  # Start the main application\n\
80
  echo "🌐 Starting Web3 Research Co-Pilot web application..."\n\
81
+ echo "πŸ” Running startup validation..."\n\
82
+ python validate_startup.py || exit 1\n\
83
  python app.py &\n\
84
  APP_PID=$!\n\
85
  \n\
app.py CHANGED
@@ -517,28 +517,14 @@ async def process_query_stream(request: QueryRequest):
517
  logger.error(f"Query processing timed out after {processing_time:.1f}s")
518
 
519
  # Send timeout result with available data
520
- yield f"data: {json.dumps({'type': 'result', 'data': {
521
- 'success': False,
522
- 'response': 'Analysis timed out, but tools successfully gathered data. The system collected cryptocurrency prices, DeFi protocol information, and blockchain data. Please try a simpler query or try again.',
523
- 'sources': [],
524
- 'metadata': {'timeout': True, 'processing_time': processing_time},
525
- 'visualizations': [],
526
- 'error': 'Processing timeout'
527
- }.copy(), 'progress': 100})}\n\n"
528
 
529
  except Exception as query_error:
530
  processing_time = (datetime.now() - start_time).total_seconds()
531
  logger.error(f"Query processing failed: {query_error}")
532
 
533
  # Send error result
534
- yield f"data: {json.dumps({'type': 'result', 'data': {
535
- 'success': False,
536
- 'response': f'Analysis failed: {str(query_error)}. The system was able to gather some data but encountered an error during final processing.',
537
- 'sources': [],
538
- 'metadata': {'error': True, 'processing_time': processing_time},
539
- 'visualizations': [],
540
- 'error': str(query_error)
541
- }.copy(), 'progress': 100})}\n\n"
542
 
543
  # Send completion signal
544
  yield f"data: {json.dumps({'type': 'complete'})}\n\n"
 
517
  logger.error(f"Query processing timed out after {processing_time:.1f}s")
518
 
519
  # Send timeout result with available data
520
+ yield f"data: {json.dumps({'type': 'result', 'data': {'success': False, 'response': 'Analysis timed out, but tools successfully gathered data. The system collected cryptocurrency prices, DeFi protocol information, and blockchain data. Please try a simpler query or try again.', 'sources': [], 'metadata': {'timeout': True, 'processing_time': processing_time}, 'visualizations': [], 'error': 'Processing timeout'}, 'progress': 100})}\n\n"
 
 
 
 
 
 
 
521
 
522
  except Exception as query_error:
523
  processing_time = (datetime.now() - start_time).total_seconds()
524
  logger.error(f"Query processing failed: {query_error}")
525
 
526
  # Send error result
527
+ yield f"data: {json.dumps({'type': 'result', 'data': {'success': False, 'response': f'Analysis failed: {str(query_error)}. The system was able to gather some data but encountered an error during final processing.', 'sources': [], 'metadata': {'error': True, 'processing_time': processing_time}, 'visualizations': [], 'error': str(query_error)}, 'progress': 100})}\n\n"
 
 
 
 
 
 
 
528
 
529
  # Send completion signal
530
  yield f"data: {json.dumps({'type': 'complete'})}\n\n"
dev_check.sh ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Development syntax checker script
3
+
4
+ echo "πŸ” Running development syntax check..."
5
+
6
+ # Check Python syntax using built-in compile
7
+ echo "1️⃣ Python syntax validation..."
8
+ find . -name "*.py" -not -path "./__pycache__/*" -not -path "./.*" | while read file; do
9
+ python -m py_compile "$file" 2>/dev/null
10
+ if [ $? -eq 0 ]; then
11
+ echo " βœ… $file"
12
+ else
13
+ echo " ❌ $file - SYNTAX ERROR"
14
+ python -m py_compile "$file"
15
+ exit 1
16
+ fi
17
+ done
18
+
19
+ echo ""
20
+ echo "2️⃣ Running comprehensive validation..."
21
+ python validate_startup.py
22
+
23
+ echo ""
24
+ echo "3️⃣ Quick import test..."
25
+ python -c "
26
+ try:
27
+ import app
28
+ print(' βœ… app.py imports successfully')
29
+ except Exception as e:
30
+ print(f' ❌ app.py import failed: {e}')
31
+ exit(1)
32
+
33
+ try:
34
+ from src.agent.research_agent import Web3ResearchAgent
35
+ print(' βœ… research_agent.py imports successfully')
36
+ except Exception as e:
37
+ print(f' ❌ research_agent.py import failed: {e}')
38
+ exit(1)
39
+ "
40
+
41
+ if [ $? -eq 0 ]; then
42
+ echo ""
43
+ echo "πŸŽ‰ All syntax checks passed! Ready for deployment."
44
+ else
45
+ echo ""
46
+ echo "❌ Syntax check failed. Please fix errors before deploying."
47
+ exit 1
48
+ fi
validate_startup.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Comprehensive startup validation script for Web3 Research Co-Pilot
4
+ Validates syntax, imports, and configurations before application startup
5
+ """
6
+
7
+ import ast
8
+ import sys
9
+ import os
10
+ import json
11
+ import importlib.util
12
+ from pathlib import Path
13
+ from typing import List, Dict, Any, Tuple
14
+
15
+ def validate_python_syntax(file_path: str) -> Tuple[bool, str]:
16
+ """Validate Python file syntax."""
17
+ try:
18
+ with open(file_path, 'r', encoding='utf-8') as f:
19
+ source = f.read()
20
+
21
+ ast.parse(source)
22
+ return True, "OK"
23
+ except SyntaxError as e:
24
+ return False, f"Syntax error at line {e.lineno}: {e.msg}"
25
+ except Exception as e:
26
+ return False, f"Parse error: {str(e)}"
27
+
28
+ def validate_imports(file_path: str) -> Tuple[bool, List[str]]:
29
+ """Validate that all imports in a Python file can be resolved."""
30
+ issues = []
31
+ try:
32
+ with open(file_path, 'r', encoding='utf-8') as f:
33
+ source = f.read()
34
+
35
+ tree = ast.parse(source)
36
+
37
+ for node in ast.walk(tree):
38
+ if isinstance(node, ast.Import):
39
+ for alias in node.names:
40
+ try:
41
+ importlib.import_module(alias.name)
42
+ except ImportError:
43
+ issues.append(f"Cannot import: {alias.name}")
44
+
45
+ elif isinstance(node, ast.ImportFrom):
46
+ if node.module:
47
+ try:
48
+ importlib.import_module(node.module)
49
+ except ImportError:
50
+ issues.append(f"Cannot import module: {node.module}")
51
+
52
+ return len(issues) == 0, issues
53
+ except Exception as e:
54
+ return False, [f"Import validation error: {str(e)}"]
55
+
56
+ def validate_json_files() -> Tuple[bool, List[str]]:
57
+ """Validate JSON configuration files."""
58
+ issues = []
59
+ json_files = [
60
+ "pyproject.toml", # Will skip if not JSON
61
+ "app_config.yaml" # Will skip if not JSON
62
+ ]
63
+
64
+ for file_path in json_files:
65
+ if os.path.exists(file_path) and file_path.endswith('.json'):
66
+ try:
67
+ with open(file_path, 'r') as f:
68
+ json.load(f)
69
+ except json.JSONDecodeError as e:
70
+ issues.append(f"Invalid JSON in {file_path}: {str(e)}")
71
+ except Exception as e:
72
+ issues.append(f"Error reading {file_path}: {str(e)}")
73
+
74
+ return len(issues) == 0, issues
75
+
76
+ def validate_environment_variables() -> Tuple[bool, List[str]]:
77
+ """Validate required environment variables."""
78
+ issues = []
79
+ optional_vars = [
80
+ "CRYPTOCOMPARE_API_KEY",
81
+ "ETHERSCAN_API_KEY",
82
+ "COINGECKO_API_KEY"
83
+ ]
84
+
85
+ for var in optional_vars:
86
+ if not os.getenv(var):
87
+ issues.append(f"Optional environment variable {var} not set (will use free tier)")
88
+
89
+ return True, issues # All env vars are optional
90
+
91
+ def main():
92
+ """Run comprehensive startup validation."""
93
+ print("πŸ” Starting comprehensive validation...")
94
+
95
+ # Get all Python files
96
+ python_files = []
97
+ for root, dirs, files in os.walk("."):
98
+ # Skip __pycache__ directories
99
+ dirs[:] = [d for d in dirs if d != "__pycache__"]
100
+
101
+ for file in files:
102
+ if file.endswith(".py"):
103
+ python_files.append(os.path.join(root, file))
104
+
105
+ print(f"πŸ“ Found {len(python_files)} Python files to validate")
106
+
107
+ all_valid = True
108
+
109
+ # 1. Syntax validation
110
+ print("\n1️⃣ Validating Python syntax...")
111
+ syntax_issues = []
112
+ for file_path in python_files:
113
+ is_valid, message = validate_python_syntax(file_path)
114
+ if not is_valid:
115
+ syntax_issues.append(f"{file_path}: {message}")
116
+ all_valid = False
117
+ else:
118
+ print(f" βœ… {file_path}")
119
+
120
+ if syntax_issues:
121
+ print("❌ Syntax Issues Found:")
122
+ for issue in syntax_issues:
123
+ print(f" - {issue}")
124
+
125
+ # 2. Critical imports validation (only for main files)
126
+ print("\n2️⃣ Validating critical imports...")
127
+ critical_files = ["app.py", "src/agent/research_agent.py"]
128
+ import_issues = []
129
+
130
+ for file_path in critical_files:
131
+ if os.path.exists(file_path):
132
+ is_valid, issues = validate_imports(file_path)
133
+ if not is_valid:
134
+ for issue in issues:
135
+ import_issues.append(f"{file_path}: {issue}")
136
+ else:
137
+ print(f" βœ… {file_path}")
138
+
139
+ # Show non-critical import issues as warnings
140
+ if import_issues:
141
+ print("⚠️ Import Warnings (may use fallbacks):")
142
+ for issue in import_issues:
143
+ print(f" - {issue}")
144
+
145
+ # 3. JSON validation
146
+ print("\n3️⃣ Validating configuration files...")
147
+ json_valid, json_issues = validate_json_files()
148
+ if not json_valid:
149
+ print("οΏ½οΏ½ Configuration Issues:")
150
+ for issue in json_issues:
151
+ print(f" - {issue}")
152
+ all_valid = False
153
+ else:
154
+ print(" βœ… Configuration files valid")
155
+
156
+ # 4. Environment validation
157
+ print("\n4️⃣ Validating environment...")
158
+ env_valid, env_issues = validate_environment_variables()
159
+ if env_issues:
160
+ print("ℹ️ Environment Info:")
161
+ for issue in env_issues:
162
+ print(f" - {issue}")
163
+ else:
164
+ print(" βœ… Environment configured")
165
+
166
+ # Final result
167
+ print(f"\n{'πŸŽ‰' if all_valid else '❌'} Validation {'PASSED' if all_valid else 'FAILED'}")
168
+
169
+ if not all_valid:
170
+ print("\nπŸ› οΈ Please fix the issues above before starting the application")
171
+ sys.exit(1)
172
+ else:
173
+ print("\nβœ… All critical validations passed - ready to start!")
174
+ sys.exit(0)
175
+
176
+ if __name__ == "__main__":
177
+ main()