1+ import json
2+ import os
3+ import shutil
4+ import subprocess
5+ import sys
6+ from pathlib import Path
7+ from typing import List , Tuple
8+
9+ from codeflash .cli_cmds .console import logger , paneled_text
10+ from codeflash .version import __version__ as version
11+
12+
13+ def run_doctor () -> None :
14+ """Run comprehensive setup verification for Codeflash."""
15+ paneled_text (
16+ "🩺 Codeflash Doctor - Diagnosing your setup..." ,
17+ panel_args = {"title" : "Setup Verification" , "expand" : False },
18+ text_args = {"style" : "bold blue" }
19+ )
20+
21+ checks = [
22+ ("Python Environment" , check_python_environment ),
23+ ("Codeflash Installation" , check_codeflash_installation ),
24+ ("VS Code Python Extension" , check_vscode_python_extension ),
25+ ("LSP Server Connection" , check_lsp_server_connection ),
26+ ("Git Repository" , check_git_repository ),
27+ ("Project Configuration" , check_project_configuration ),
28+ ]
29+
30+ results = []
31+ all_passed = True
32+
33+ for check_name , check_func in checks :
34+ logger .info (f"Checking { check_name } ..." )
35+ success , message = check_func ()
36+ results .append ((check_name , success , message ))
37+ if not success :
38+ all_passed = False
39+
40+ print_results (results , all_passed )
41+
42+
43+ def check_python_environment () -> Tuple [bool , str ]:
44+ """Check Python version and environment."""
45+ try :
46+ python_version = f"{ sys .version_info .major } .{ sys .version_info .minor } .{ sys .version_info .micro } "
47+ if sys .version_info < (3 , 8 ):
48+ return False , f"Python { python_version } found. Python 3.8+ required."
49+ return True , f"Python { python_version } ✓"
50+ except Exception as e :
51+ return False , f"Failed to check Python version: { e } "
52+
53+
54+ def check_codeflash_installation () -> Tuple [bool , str ]:
55+ """Verify Codeflash is properly installed."""
56+ try :
57+ return True , f"Codeflash { version } installed ✓"
58+ except Exception as e :
59+ return False , f"Codeflash installation check failed: { e } "
60+
61+
62+ def check_vscode_python_extension () -> Tuple [bool , str ]:
63+ """Check if VS Code Python extension is installed."""
64+ try :
65+ code_cmd = shutil .which ("code" )
66+ if not code_cmd :
67+ return False , "VS Code 'code' command not found in PATH"
68+
69+ result = subprocess .run (
70+ [code_cmd , "--list-extensions" ],
71+ capture_output = True ,
72+ text = True ,
73+ timeout = 10
74+ )
75+
76+ if result .returncode != 0 :
77+ return False , f"Failed to list VS Code extensions: { result .stderr } "
78+
79+ extensions = result .stdout .strip ().split ('\n ' )
80+ python_extensions = [ext for ext in extensions if 'python' in ext .lower ()]
81+
82+ if not python_extensions :
83+ return False , "Python extension not found. Install the Python extension for VS Code."
84+
85+ return True , f"VS Code Python extension found: { ', ' .join (python_extensions )} ✓"
86+
87+ except subprocess .TimeoutExpired :
88+ return False , "VS Code extension check timed out"
89+ except Exception as e :
90+ return False , f"VS Code extension check failed: { e } "
91+
92+
93+ def check_lsp_server_connection () -> Tuple [bool , str ]:
94+ """Test LSP server connectivity."""
95+ try :
96+ from codeflash .lsp .server import CodeflashLanguageServer
97+
98+ # Test that we can instantiate the server (basic smoke test)
99+ server_class = CodeflashLanguageServer
100+ if hasattr (server_class , 'initialize_optimizer' ):
101+ return True , "LSP server available ✓"
102+ else :
103+ return True , "LSP server module loaded successfully ✓"
104+
105+ except ImportError as e :
106+ return False , f"LSP server import failed: { e } "
107+ except Exception as e :
108+ return False , f"LSP server check failed: { e } "
109+
110+
111+ def check_git_repository () -> Tuple [bool , str ]:
112+ """Check if running in a git repository."""
113+ try :
114+ result = subprocess .run (
115+ ["git" , "rev-parse" , "--git-dir" ],
116+ capture_output = True ,
117+ text = True ,
118+ timeout = 5
119+ )
120+
121+ if result .returncode == 0 :
122+ return True , "Git repository detected ✓"
123+ else :
124+ return False , "No git repository found. Initialize with 'git init'"
125+
126+ except subprocess .TimeoutExpired :
127+ return False , "Git check timed out"
128+ except FileNotFoundError :
129+ return False , "Git not found in PATH"
130+ except Exception as e :
131+ return False , f"Git check failed: { e } "
132+
133+
134+ def check_project_configuration () -> Tuple [bool , str ]:
135+ """Check for project configuration files."""
136+ try :
137+ config_files = ["pyproject.toml" , "setup.py" , "requirements.txt" , "setup.cfg" ]
138+ found_configs = []
139+
140+ for config_file in config_files :
141+ if Path (config_file ).exists ():
142+ found_configs .append (config_file )
143+
144+ if found_configs :
145+ return True , f"Project configuration found: { ', ' .join (found_configs )} ✓"
146+ else :
147+ return False , "No project configuration files found (pyproject.toml, setup.py, etc.)"
148+
149+ except Exception as e :
150+ return False , f"Project configuration check failed: { e } "
151+
152+
153+ def print_results (results : List [Tuple [str , bool , str ]], all_passed : bool ) -> None :
154+ """Print the diagnostic results in a formatted way."""
155+ print ("\n " + "=" * 60 )
156+ print ("🩺 CODEFLASH SETUP DIAGNOSIS RESULTS" )
157+ print ("=" * 60 )
158+
159+ for check_name , success , message in results :
160+ status = "✅ PASS" if success else "❌ FAIL"
161+ print (f"{ status :8} | { check_name :25} | { message } " )
162+
163+ print ("=" * 60 )
164+
165+ if all_passed :
166+ paneled_text (
167+ "🎉 Your Codeflash setup is perfect! 🎉\n \n "
168+ "All checks passed successfully. You're ready to optimize your code!\n \n "
169+ "Next steps:\n "
170+ "• Run 'codeflash init' to initialize a project\n "
171+ "• Use 'codeflash --file <filename>' to optimize a specific file\n "
172+ "• Try 'codeflash --verify-setup' for an end-to-end test" ,
173+ panel_args = {"title" : "✅ SUCCESS" , "expand" : False },
174+ text_args = {"style" : "bold green" }
175+ )
176+ else :
177+ failed_checks = [name for name , success , _ in results if not success ]
178+ paneled_text (
179+ f"⚠️ Setup Issues Detected\n \n "
180+ f"The following checks failed:\n "
181+ f"• { chr (10 ).join (failed_checks )} \n \n "
182+ f"Please address these issues and run 'codeflash doctor' again.\n \n "
183+ f"For help, visit: https://codeflash.ai/docs" ,
184+ panel_args = {"title" : "❌ ISSUES FOUND" , "expand" : False },
185+ text_args = {"style" : "bold yellow" }
186+ )
187+ sys .exit (1 )
0 commit comments