""" API routes for the pydoc translation service. FastAPI-compatible route structure implemented in Flask. """ from flask import Blueprint, request, jsonify from modules.doc_extractor import DocExtractor from modules.translator import TranslationService from modules.cache import CacheService from modules.module_list import ModuleList from modules.course_scraper import CourseScraper api_bp = Blueprint('api', __name__, url_prefix='') # Initialize services (singleton pattern) doc_extractor = DocExtractor() translator = TranslationService() cache = CacheService() module_list = ModuleList() @api_bp.route('/docs', methods=['GET']) def get_docs(): """ Get documentation for a Python object with optional translation. Query parameters: object: Python object name (e.g., 'dict.update', 'os.path') lang: Target language code (e.g., 'de', 'fr', 'es'). Optional. Returns: JSON response with: - original: Original English documentation - translated: Translated documentation (if lang provided) - object_name: Name of the object - object_type: Type of object - signature: Function signature if applicable - error: Error message if any - cached: Whether the result was served from cache """ object_name = request.args.get('object') target_lang = request.args.get('lang') if not object_name: return jsonify({ 'error': 'Missing required parameter: object', 'original': None, 'translated': None }), 400 # Check cache first if language is specified cached_result = None if target_lang: cached_result = cache.get(object_name, target_lang) if cached_result: # Verify cached result matches the requested object if cached_result.get('object_name') == object_name: cached_result['cached'] = True return jsonify(cached_result) else: # Cache mismatch - clear it and continue print(f"Cache mismatch for {object_name}: got {cached_result.get('object_name')}") # Extract documentation doc_data = doc_extractor.extract_doc(object_name) if doc_data.get('error'): return jsonify({ 'error': doc_data['error'], 'original': None, 'translated': None, 'object_name': object_name }), 404 # Always translate if language is specified (auto-translate) translated = None if target_lang and doc_data.get('original'): try: translated = translator.translate(doc_data['original'], target_lang) if not translated: # If translation fails, try to return original with error note translated = None except Exception as e: import traceback print(f"Translation error: {e}") print(traceback.format_exc()) translated = None # Prepare response response = { 'original': doc_data['original'], 'translated': translated, 'object_name': doc_data['object_name'], 'object_type': doc_data['object_type'], 'signature': doc_data['signature'], 'error': doc_data['error'], 'cached': False } # Cache the result if translation was successful if target_lang and translated: cache.set(object_name, target_lang, response, ttl=86400) # Cache for 24 hours return jsonify(response) @api_bp.route('/modules', methods=['GET']) def get_modules(): """ Get list of available Python modules. Query parameters: module: Optional module name to get contents of that module Returns: List of available modules or module contents """ module_name = request.args.get('module') if module_name: # Get contents of specific module contents = module_list.get_module_contents(module_name) return jsonify({ 'module': module_name, 'contents': contents }) else: # Get list of standard modules modules = module_list.get_standard_modules() builtins = module_list.get_builtin_objects() return jsonify({ 'modules': modules, 'builtins': builtins }) @api_bp.route('/course', methods=['GET']) def get_course(): """ Get Python course content. Returns: Course structure and content """ scraper = CourseScraper() course_data = scraper.scrape_course_content() return jsonify(course_data) @api_bp.route('/health', methods=['GET']) def health(): """Health check endpoint.""" return jsonify({ 'status': 'healthy', 'service': 'pydoc-translation-service' })