11"""Code execution runner - core execution logic."""
22
33import asyncio
4+ import shlex
45from datetime import datetime , timedelta
56from pathlib import Path
67from typing import Any , Dict , List , Optional , Tuple
@@ -152,7 +153,7 @@ async def execute(
152153
153154 # Mount files if provided
154155 if files :
155- await self ._mount_files_to_container (container , files )
156+ await self ._mount_files_to_container (container , files , request . language )
156157
157158 # Execute the code
158159 start_time = datetime .utcnow ()
@@ -185,11 +186,16 @@ async def execute(
185186 request .timeout or settings .max_execution_time ,
186187 initial_state = initial_state ,
187188 capture_state = capture_state ,
189+ args = request .args ,
188190 )
189191 else :
190192 # Standard execution (no state persistence)
191193 exit_code , stdout , stderr = await self ._execute_code_in_container (
192- container , request .code , request .language , request .timeout
194+ container ,
195+ request .code ,
196+ request .language ,
197+ request .timeout ,
198+ args = request .args ,
193199 )
194200 end_time = datetime .utcnow ()
195201
@@ -435,12 +441,20 @@ async def _execute_code_in_container(
435441 code : str ,
436442 language : str ,
437443 timeout : Optional [int ] = None ,
444+ args : Optional [List [str ]] = None ,
438445 ) -> Tuple [int , str , str ]:
439446 """Execute code in the container.
440447
441448 For REPL-enabled containers (Python with REPL mode), uses the fast
442449 REPL executor which communicates with the pre-warmed Python interpreter.
443450 For other containers, uses the standard execution path.
451+
452+ Args:
453+ container: Docker container to execute in
454+ code: Code to execute
455+ language: Programming language
456+ timeout: Execution timeout in seconds
457+ args: Optional list of command line arguments
444458 """
445459 language = language .lower ()
446460 lang_config = get_language (language )
@@ -454,7 +468,9 @@ async def _execute_code_in_container(
454468 logger .debug (
455469 "Using REPL executor" , container_id = container .id [:12 ], language = language
456470 )
457- return await self ._execute_via_repl (container , code , execution_timeout )
471+ return await self ._execute_via_repl (
472+ container , code , execution_timeout , args = args
473+ )
458474
459475 # Standard execution path for non-REPL containers
460476 exec_command = lang_config .execution_command
@@ -480,13 +496,20 @@ async def _execute_code_in_container(
480496 # Direct memory-to-container transfer (no tempfiles)
481497 dest_path = f"/mnt/data/{ code_filename } "
482498 if not await self .container_manager .copy_content_to_container (
483- container , code .encode ("utf-8" ), dest_path
499+ container , code .encode ("utf-8" ), dest_path , language = language
484500 ):
485501 return 1 , "" , "Failed to write code file to container"
486502
503+ # Build execution command with args if provided
504+ final_command = exec_command
505+ if args :
506+ # Safely quote each argument to prevent shell injection
507+ quoted_args = " " .join (shlex .quote (arg ) for arg in args )
508+ final_command = f"{ exec_command } { quoted_args } "
509+
487510 return await self .container_manager .execute_command (
488511 container ,
489- exec_command ,
512+ final_command ,
490513 timeout = execution_timeout ,
491514 language = language ,
492515 working_dir = "/mnt/data" ,
@@ -521,21 +544,26 @@ def _is_repl_container(self, container: Container, language: str) -> bool:
521544 return False
522545
523546 async def _execute_via_repl (
524- self , container : Container , code : str , timeout : int
547+ self ,
548+ container : Container ,
549+ code : str ,
550+ timeout : int ,
551+ args : Optional [List [str ]] = None ,
525552 ) -> Tuple [int , str , str ]:
526553 """Execute code via REPL server in container.
527554
528555 Args:
529556 container: Docker container with REPL server running
530557 code: Python code to execute
531558 timeout: Maximum execution time in seconds
559+ args: Optional list of command line arguments
532560
533561 Returns:
534562 Tuple of (exit_code, stdout, stderr)
535563 """
536564 repl_executor = REPLExecutor (self .container_manager .client )
537565 return await repl_executor .execute (
538- container , code , timeout = timeout , working_dir = "/mnt/data"
566+ container , code , timeout = timeout , working_dir = "/mnt/data" , args = args
539567 )
540568
541569 async def _execute_via_repl_with_state (
@@ -545,6 +573,7 @@ async def _execute_via_repl_with_state(
545573 timeout : int ,
546574 initial_state : Optional [str ] = None ,
547575 capture_state : bool = True ,
576+ args : Optional [List [str ]] = None ,
548577 ) -> Tuple [int , str , str , Optional [str ], List [str ]]:
549578 """Execute code via REPL server with state persistence.
550579
@@ -554,6 +583,7 @@ async def _execute_via_repl_with_state(
554583 timeout: Maximum execution time in seconds
555584 initial_state: Base64-encoded state to restore before execution
556585 capture_state: Whether to capture state after execution
586+ args: Optional list of command line arguments
557587
558588 Returns:
559589 Tuple of (exit_code, stdout, stderr, new_state, state_errors)
@@ -566,10 +596,11 @@ async def _execute_via_repl_with_state(
566596 working_dir = "/mnt/data" ,
567597 initial_state = initial_state ,
568598 capture_state = capture_state ,
599+ args = args ,
569600 )
570601
571602 async def _mount_files_to_container (
572- self , container : Container , files : List [Dict [str , Any ]]
603+ self , container : Container , files : List [Dict [str , Any ]], language : str = "py"
573604 ) -> None :
574605 """Mount files to container workspace."""
575606 try :
@@ -599,7 +630,7 @@ async def _mount_files_to_container(
599630 dest_path = f"/mnt/data/{ normalized_filename } "
600631
601632 if await self .container_manager .copy_content_to_container (
602- container , file_content , dest_path
633+ container , file_content , dest_path , language = language
603634 ):
604635 logger .info (
605636 "Mounted file" ,
0 commit comments