# file_utils.py - File handling utilities import os import json from typing import Tuple, Optional class FileHandler: """Class for handling uploaded files""" @staticmethod def read_uploaded_file(file_input, filename_for_error: str = "file") -> Tuple[Optional[str], Optional[str]]: """ Universal method for reading uploaded files from different Gradio versions Returns: Tuple[content, error_message] - content if successful, error_message if error """ if file_input is None: return None, f"❌ File {filename_for_error} not uploaded" # Debug information debug_enabled = os.getenv("LOG_PROMPTS", "false").lower() == "true" if debug_enabled: print(f"🔍 Debug {filename_for_error}: type={type(file_input)}, value={repr(file_input)[:100]}...") try: # Try 1: filepath (type="filepath") if isinstance(file_input, str): if debug_enabled: print(f"📁 Reading as filepath: {file_input}") with open(file_input, 'r', encoding='utf-8') as f: return f.read(), None # Try 2: file-like object with read method elif hasattr(file_input, 'read'): if debug_enabled: print(f"📄 Reading as file-like object") content = file_input.read() if isinstance(content, bytes): content = content.decode('utf-8') return content, None # Try 3: bytes object elif isinstance(file_input, bytes): if debug_enabled: print(f"🔢 Читаємо як bytes object") return file_input.decode('utf-8'), None # Try 4: dict with path (some Gradio versions) elif isinstance(file_input, dict) and 'name' in file_input: if debug_enabled: print(f"📚 Читаємо як dict з name: {file_input['name']}") with open(file_input['name'], 'r', encoding='utf-8') as f: return f.read(), None # Try 5: dict with other keys elif isinstance(file_input, dict): if debug_enabled: print(f"📖 Dict keys: {list(file_input.keys())}") for key in ['path', 'file', 'filepath', 'tmp_file']: if key in file_input: with open(file_input[key], 'r', encoding='utf-8') as f: return f.read(), None return None, f"❌ Не знайдено шлях до файлу в dict для {filename_for_error}" else: return None, f"❌ Непідтримуваний тип файлу для {filename_for_error}: {type(file_input)}" except Exception as e: if debug_enabled: import traceback print(f"❌ Exception при читанні {filename_for_error}: {traceback.format_exc()}") return None, f"❌ Помилка читання {filename_for_error}: {str(e)}" @staticmethod def parse_json_file(content: str, filename: str) -> Tuple[Optional[dict], Optional[str]]: """ Парсить JSON контент з обробкою помилок Returns: Tuple[parsed_data, error_message] """ try: return json.loads(content), None except json.JSONDecodeError as e: return None, f"❌ Помилка парсингу {filename}: {str(e)}"