import asyncio import websockets import json # Replace with your actual Space URL # For Hugging Face Spaces, use wss://.hf.space/ws WS_URL = "wss://Srevarshan1502-collaborative-python-executor.hf.space/ws" async def run_python_code(code_to_execute: str): try: async with websockets.connect(WS_URL) as websocket: print("Connected to WebSocket.") # Send the Python code await websocket.send(json.dumps({"type": "code", "content": code_to_execute})) print(f"Sent code:\n---\n{code_to_execute}\n---") full_output = "" execution_complete = False while not execution_complete: try: # Keep waiting for messages until execution_complete # Increased timeout to 60 seconds as per your last script message = await asyncio.wait_for(websocket.recv(), timeout=60) data = json.loads(message) if data["type"] == "output": full_output += data["content"] print(f"Received output chunk: {data['content'].strip()}") elif data["type"] == "input_request": print("\n--- Input Requested ---") user_input = input("Please enter input for the script: ") # IMPORTANT: Add newline character for the server's readline() to process it as a complete line await websocket.send(json.dumps({"type": "input", "content": user_input + "\n"})) print(f"Sent input: {user_input}") elif data["type"] == "execution_complete": print("\n--- Execution Complete ---") # The 'result' field from the server's execution_complete message server_result = data['result'] print(f"Result details from server: {server_result}") # Consolidate output from the server_result as well if server_result.get('output'): full_output += server_result['output'] if server_result.get('error'): # Prepend "Error:" if it's the first error message if "Error from server:" not in full_output: full_output += "\nError from server:\n" full_output += server_result['error'] execution_complete = True elif data["type"] == "pong": # print("Received pong.") # Optional: uncomment to see pongs pass else: print(f"Received unknown message type: {data['type']} - {data.get('content')}") except asyncio.TimeoutError: print("Timeout: No message received from server for 60 seconds. Disconnecting.") break except websockets.exceptions.ConnectionClosedOK: print("Connection closed by server (OK).") # If it closes OK before execution_complete, it's an issue if not execution_complete: print("WARNING: Connection closed OK before execution_complete message was received!") break except websockets.exceptions.ConnectionClosedError as e: print(f"Connection closed with error: {e}") break except json.JSONDecodeError: print(f"Received invalid JSON: {message}") break except Exception as e: print(f"An unexpected error occurred during message reception: {e}") break print("\n--- Final Consolidated Output ---") print(full_output) return full_output except websockets.exceptions.InvalidURI as e: print(f"Invalid WebSocket URI: {e}") except ConnectionRefusedError: print("Connection refused. Is the server running and accessible?") except Exception as e: print(f"Could not connect to WebSocket: {e}") return None if __name__ == "__main__": # Test 1: Simple print statement (Matches the current app.py test 1) print("\n=== Running Test 1: Simple Print ===") asyncio.run(run_python_code(code_to_execute = "print('Hello, Space!')")) # Test 2: Code with interactive input (corrected syntax) print("\n=== Running Test 2: Interactive Input ===") interactive_code = """ name = input("Enter your name: ") age = int(input("How old are you? ")) print(f"Hello, {name}! You are {age} years old.") """ # For app.py's Test 2 (where exec is not yet active) # asyncio.run(run_python_code(code_to_execute="DUMMY_CODE_FOR_TESTING_SYS_REDIRECTION")) # Once app.py has Test 3 (with exec) uncomment this: asyncio.run(run_python_code(interactive_code)) # Test 3: Code with error (uncomment when full exec is working) # print("\n=== Running Test 3: Code with Error ===") # asyncio.run(run_python_code("print(1/0)")) # Test 4: Long-running code (will hit timeout if not finished, uncomment when full exec is working) # print("\n=== Running Test 4: Long Running Code ===") # asyncio.run(run_python_code("import time\nfor i in range(5):\n print(f'Counting: {i}')\n time.sleep(1)"))