""" Configuration command presenters. Handles output formatting and display for configuration management commands. """ import json from datetime import datetime from pathlib import Path from typing import Dict, Any, List, Optional from config import MarkitectConfig from .formatters import OutputFormatter class ConfigPresenter: """Presenter for configuration management commands.""" def show_error(self, message: str) -> None: """Display error message.""" OutputFormatter.error(message) def show_configuration(self, config: MarkitectConfig, status: Dict[str, Any], show_sensitive: bool = False) -> None: """Display current configuration values.""" OutputFormatter.header("πŸ”§ Configuration Status") # Basic configuration OutputFormatter.section("Core Configuration") self._show_config_table(config, show_sensitive) # Configuration sources OutputFormatter.section("Configuration Sources") self._show_config_sources(status) # Workspace status OutputFormatter.section("Workspace Information") self._show_workspace_info(config) def show_validation_results(self, results: List[Dict[str, Any]], verbose: bool = False) -> None: """Display configuration validation results.""" OutputFormatter.header("βœ… Configuration Validation") # Count results by status success_count = sum(1 for r in results if r['status'] == 'success') warning_count = sum(1 for r in results if r['status'] == 'warning') error_count = sum(1 for r in results if r['status'] == 'error') # Summary total = len(results) print(f"πŸ“Š Summary: {success_count}/{total} checks passed") if warning_count > 0: print(f"⚠️ {warning_count} warnings") if error_count > 0: print(f"❌ {error_count} errors") print() # Show results for result in results: status_icon = { 'success': 'βœ…', 'warning': '⚠️', 'error': '❌' }[result['status']] print(f"{status_icon} {result['check']}") print(f" {result['message']}") if result['status'] != 'success' and 'suggestion' in result: print(f" πŸ’‘ {result['suggestion']}") if verbose or result['status'] == 'error': print() def show_troubleshooting_results(self, config: Optional[MarkitectConfig], status: Optional[Dict[str, Any]], diagnostics: Dict[str, Any]) -> None: """Display comprehensive troubleshooting information.""" OutputFormatter.header("πŸ” Configuration Troubleshooting") if config: print("βœ… Configuration loaded successfully") print() # Environment diagnostics if 'environment' in diagnostics: OutputFormatter.section("Environment Diagnostics") self._show_environment_diagnostics(diagnostics['environment']) # File system diagnostics if 'filesystem' in diagnostics: OutputFormatter.section("File System Diagnostics") self._show_filesystem_diagnostics(diagnostics['filesystem']) # Configuration files diagnostics if 'config_files' in diagnostics: OutputFormatter.section("Configuration Files") self._show_config_files_diagnostics(diagnostics['config_files']) # Git repository diagnostics if 'git_repository' in diagnostics: OutputFormatter.section("Git Repository") self._show_git_diagnostics(diagnostics['git_repository']) # Network diagnostics if 'network' in diagnostics: OutputFormatter.section("Network Connectivity") self._show_network_diagnostics(diagnostics['network']) # Show configuration if available if config and status: OutputFormatter.section("Current Configuration") self._show_config_table(config, show_sensitive=False) # Recommendations self._show_troubleshooting_recommendations(diagnostics) def show_config_file_status(self, file_checks: Dict[str, Any]) -> None: """Display configuration file status.""" OutputFormatter.header("πŸ“ Configuration Files Status") for filename, info in file_checks.items(): status_icon = "βœ…" if info['exists'] else "❌" print(f"{status_icon} {filename}") if info['exists']: print(f" πŸ“ Path: {info['path']}") print(f" πŸ“ Size: {info['size']} bytes") if info['readable']: print(" πŸ”“ Readable: Yes") else: print(" πŸ”’ Readable: No") # Show parsed variables for .env files if 'parsed_variables' in info: if info['parse_error']: print(f" ❌ Parse error: {info['parse_error']}") else: print(f" πŸ”§ Variables: {info['parsed_variables']}") if info.get('modified'): modified_time = datetime.fromtimestamp(info['modified']) print(f" πŸ•’ Modified: {modified_time.strftime('%Y-%m-%d %H:%M:%S')}") else: print(f" πŸ“ Expected path: {info['path']}") print(" ❌ File not found") print() def _show_config_table(self, config: MarkitectConfig, show_sensitive: bool = False) -> None: """Show configuration in table format.""" config_items = [ ("Gitea URL", config.gitea_url), ("Repository Owner", config.repo_owner), ("Repository Name", config.repo_name), ("Workspace Directory", config.workspace_dir), ("Database Path", getattr(config, 'database_path', 'Default')), ] # Add sensitive information if requested if show_sensitive: import os token = os.getenv('GITEA_API_TOKEN') or os.getenv('GITHUB_TOKEN') if token: masked_token = f"{token[:8]}...{token[-4:]}" if len(token) > 12 else "***" config_items.append(("Auth Token", masked_token)) max_key_length = max(len(key) for key, _ in config_items) for key, value in config_items: print(f" {key:<{max_key_length}} : {value or 'Not set'}") print() def _show_config_sources(self, status: Dict[str, Any]) -> None: """Show configuration sources information.""" if not status: print(" ❌ Configuration status not available") return sources = status.get('sources', {}) for source_name, source_info in sources.items(): if source_info.get('loaded'): print(f" βœ… {source_name}: {source_info.get('path', 'System')}") else: print(f" ⏸️ {source_name}: Not loaded") print() def _show_workspace_info(self, config: MarkitectConfig) -> None: """Show workspace information.""" workspace_path = Path(config.workspace_dir) print(f" πŸ“ Workspace: {workspace_path}") print(f" πŸ“ Exists: {'Yes' if workspace_path.exists() else 'No'}") if workspace_path.exists(): try: items = list(workspace_path.iterdir()) print(f" πŸ“„ Items: {len(items)}") except PermissionError: print(" ❌ Permission denied") print() def _show_environment_diagnostics(self, env_info: Dict[str, Any]) -> None: """Show environment diagnostics.""" print(f" 🐍 Python: {env_info['python_version'].split()[0]}") print(f" πŸ“ Executable: {env_info['python_executable']}") print(f" πŸ“ Current Dir: {env_info['current_directory']}") print() print(" Environment Variables:") env_vars = env_info['environment_variables'] for var_name, var_info in env_vars.items(): if var_info['set']: icon = "βœ…" if 'TOKEN' in var_name: value_display = f"Set ({var_info['length']} chars)" else: value_display = var_info['value'] else: icon = "❌" value_display = "Not set" print(f" {icon} {var_name}: {value_display}") print() def _show_filesystem_diagnostics(self, fs_info: Dict[str, Any]) -> None: """Show filesystem diagnostics.""" for dir_type, dir_info in fs_info.items(): print(f" πŸ“ {dir_type.replace('_', ' ').title()}:") print(f" πŸ“ Path: {dir_info['path']}") print(f" βœ… Exists: {dir_info['exists']}") print(f" πŸ”“ Readable: {dir_info['readable']}") print(f" ✏️ Writable: {dir_info['writable']}") print() def _show_config_files_diagnostics(self, files_info: Dict[str, Any]) -> None: """Show configuration files diagnostics.""" for filename, file_info in files_info.items(): status_icon = "βœ…" if file_info['exists'] else "❌" print(f" {status_icon} {filename}") if file_info['exists']: print(f" πŸ“ Size: {file_info['size']} bytes") print(f" πŸ”“ Readable: {file_info['readable']}") if 'parsed_variables' in file_info: if file_info['parse_error']: print(f" ❌ Parse error: {file_info['parse_error']}") else: print(f" πŸ”§ Variables: {file_info['parsed_variables']}") print() def _show_git_diagnostics(self, git_info: Dict[str, Any]) -> None: """Show git repository diagnostics.""" if git_info['is_git_repository']: print(" βœ… Git repository detected") if 'remote_origin' in git_info: print(f" 🌐 Remote origin: {git_info['remote_origin']}") if 'current_branch' in git_info: print(f" 🌿 Current branch: {git_info['current_branch']}") if git_info.get('git_command_available', True): print(" βœ… Git command available") else: print(" ❌ Git command not available") else: print(" ❌ Not a git repository") print() def _show_network_diagnostics(self, network_info: Dict[str, Any]) -> None: """Show network connectivity diagnostics.""" if 'gitea_connectivity' in network_info: conn_info = network_info['gitea_connectivity'] if conn_info['reachable']: print(f" βœ… {conn_info['url']} - Reachable (HTTP {conn_info['status_code']})") else: print(f" ❌ {conn_info['url']} - Not reachable") print(f" Error: {conn_info['error']}") print() def _show_troubleshooting_recommendations(self, diagnostics: Dict[str, Any]) -> None: """Show troubleshooting recommendations based on diagnostics.""" OutputFormatter.section("πŸ’‘ Recommendations") recommendations = [] # Check for missing .env.tddai config_files = diagnostics.get('config_files', {}) if not config_files.get('.env.tddai', {}).get('exists'): recommendations.append( "Create .env.tddai file with your configuration:\n" " TDDAI_GITEA_URL=https://your-git-platform.com\n" " TDDAI_REPO_OWNER=your-username\n" " TDDAI_REPO_NAME=your-repo" ) # Check for missing environment variables env_vars = diagnostics.get('environment', {}).get('environment_variables', {}) missing_required = [] for var in ['TDDAI_GITEA_URL', 'TDDAI_REPO_OWNER', 'TDDAI_REPO_NAME']: if not env_vars.get(var, {}).get('set'): missing_required.append(var) if missing_required: recommendations.append( f"Set missing required environment variables: {', '.join(missing_required)}" ) # Check for missing auth token if not env_vars.get('GITEA_API_TOKEN', {}).get('set') and \ not env_vars.get('GITHUB_TOKEN', {}).get('set'): recommendations.append( "Set authentication token for API access:\n" " export GITEA_API_TOKEN=your-token\n" " or\n" " export GITHUB_TOKEN=your-token" ) # Check git repository git_info = diagnostics.get('git_repository', {}) if not git_info.get('is_git_repository'): recommendations.append( "Initialize git repository:\n" " git init\n" " git remote add origin " ) # Network connectivity issues network_info = diagnostics.get('network', {}) gitea_conn = network_info.get('gitea_connectivity', {}) if gitea_conn and not gitea_conn.get('reachable'): recommendations.append( "Check network connectivity and firewall settings\n" "Verify the Gitea URL is correct and accessible" ) if recommendations: for i, rec in enumerate(recommendations, 1): print(f"{i}. {rec}") print() else: print("βœ… No issues detected! Configuration looks good.") print()