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,13 @@ 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 , request .code , request .language , request .timeout ,
195+ args = request .args
193196 )
194197 end_time = datetime .utcnow ()
195198
@@ -435,12 +438,20 @@ async def _execute_code_in_container(
435438 code : str ,
436439 language : str ,
437440 timeout : Optional [int ] = None ,
441+ args : Optional [List [str ]] = None ,
438442 ) -> Tuple [int , str , str ]:
439443 """Execute code in the container.
440444
441445 For REPL-enabled containers (Python with REPL mode), uses the fast
442446 REPL executor which communicates with the pre-warmed Python interpreter.
443447 For other containers, uses the standard execution path.
448+
449+ Args:
450+ container: Docker container to execute in
451+ code: Code to execute
452+ language: Programming language
453+ timeout: Execution timeout in seconds
454+ args: Optional list of command line arguments
444455 """
445456 language = language .lower ()
446457 lang_config = get_language (language )
@@ -454,7 +465,7 @@ async def _execute_code_in_container(
454465 logger .debug (
455466 "Using REPL executor" , container_id = container .id [:12 ], language = language
456467 )
457- return await self ._execute_via_repl (container , code , execution_timeout )
468+ return await self ._execute_via_repl (container , code , execution_timeout , args = args )
458469
459470 # Standard execution path for non-REPL containers
460471 exec_command = lang_config .execution_command
@@ -480,13 +491,20 @@ async def _execute_code_in_container(
480491 # Direct memory-to-container transfer (no tempfiles)
481492 dest_path = f"/mnt/data/{ code_filename } "
482493 if not await self .container_manager .copy_content_to_container (
483- container , code .encode ("utf-8" ), dest_path
494+ container , code .encode ("utf-8" ), dest_path , language = language
484495 ):
485496 return 1 , "" , "Failed to write code file to container"
486497
498+ # Build execution command with args if provided
499+ final_command = exec_command
500+ if args :
501+ # Safely quote each argument to prevent shell injection
502+ quoted_args = " " .join (shlex .quote (arg ) for arg in args )
503+ final_command = f"{ exec_command } { quoted_args } "
504+
487505 return await self .container_manager .execute_command (
488506 container ,
489- exec_command ,
507+ final_command ,
490508 timeout = execution_timeout ,
491509 language = language ,
492510 working_dir = "/mnt/data" ,
@@ -521,21 +539,23 @@ def _is_repl_container(self, container: Container, language: str) -> bool:
521539 return False
522540
523541 async def _execute_via_repl (
524- self , container : Container , code : str , timeout : int
542+ self , container : Container , code : str , timeout : int ,
543+ args : Optional [List [str ]] = None
525544 ) -> Tuple [int , str , str ]:
526545 """Execute code via REPL server in container.
527546
528547 Args:
529548 container: Docker container with REPL server running
530549 code: Python code to execute
531550 timeout: Maximum execution time in seconds
551+ args: Optional list of command line arguments
532552
533553 Returns:
534554 Tuple of (exit_code, stdout, stderr)
535555 """
536556 repl_executor = REPLExecutor (self .container_manager .client )
537557 return await repl_executor .execute (
538- container , code , timeout = timeout , working_dir = "/mnt/data"
558+ container , code , timeout = timeout , working_dir = "/mnt/data" , args = args
539559 )
540560
541561 async def _execute_via_repl_with_state (
@@ -545,6 +565,7 @@ async def _execute_via_repl_with_state(
545565 timeout : int ,
546566 initial_state : Optional [str ] = None ,
547567 capture_state : bool = True ,
568+ args : Optional [List [str ]] = None ,
548569 ) -> Tuple [int , str , str , Optional [str ], List [str ]]:
549570 """Execute code via REPL server with state persistence.
550571
@@ -554,6 +575,7 @@ async def _execute_via_repl_with_state(
554575 timeout: Maximum execution time in seconds
555576 initial_state: Base64-encoded state to restore before execution
556577 capture_state: Whether to capture state after execution
578+ args: Optional list of command line arguments
557579
558580 Returns:
559581 Tuple of (exit_code, stdout, stderr, new_state, state_errors)
@@ -566,10 +588,11 @@ async def _execute_via_repl_with_state(
566588 working_dir = "/mnt/data" ,
567589 initial_state = initial_state ,
568590 capture_state = capture_state ,
591+ args = args ,
569592 )
570593
571594 async def _mount_files_to_container (
572- self , container : Container , files : List [Dict [str , Any ]]
595+ self , container : Container , files : List [Dict [str , Any ]], language : str = "py"
573596 ) -> None :
574597 """Mount files to container workspace."""
575598 try :
@@ -599,7 +622,7 @@ async def _mount_files_to_container(
599622 dest_path = f"/mnt/data/{ normalized_filename } "
600623
601624 if await self .container_manager .copy_content_to_container (
602- container , file_content , dest_path
625+ container , file_content , dest_path , language = language
603626 ):
604627 logger .info (
605628 "Mounted file" ,
0 commit comments