o
    ;i#                     @   s  U d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZmZm	Z	 d dl
mZ d dlmZ d dlmZmZmZmZmZmZmZ ddlmZ ddlmZmZ erUd dlZd d	lmZ d d
lmZ d dlm Z m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z'm(Z) ddl*m+Z+ ddl,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5 ddl6m7Z7 ddl8m9Z9m:Z: ddl;m<Z< ddl=m>Z> ddl?m@Z@ ddlAmBZB ddlCmDZDmEZEmFZFmGZG ddlHmIZImJZJmKZK ddlLmMZM ddlNmOZO ddlPmQZQmRZRmSZSmTZT ddlUmVZVmWZW dd lXmYZY dd!lZm[Z[ dd"l\m]Z] dd#l^m_Z_ eO` ZaeOebd$< d%Zcd&Zder&d dleZfd'e	eg d(dfd)d*ZhG d+d, d,egZiei Zjed-d.G d/d0 d0ZkG d1d2 d2e.d3d4Zle5elZmdS )5    N)AsyncGenerator
CollectionSequence)	dataclass)PurePosixPath)TYPE_CHECKINGAnyAsyncIteratorLiteralOptionalUnionoverload   get_pty_info)configlogger)Message)Tunnel)_CloudBucketMountcloud_bucket_mounts_to_proto)_Mount)_Volume)api_pb2task_command_router_pb2)LoadContext)_get_environment_name_Object)Resolver)%convert_fn_config_to_resources_config)TaskContextsynchronize_api)deprecation_warning)validate_network_file_systemsvalidate_volumes)check_object_name)TaskCommandRouterClient)_Client)_ContainerProcess)ExecutionErrorInvalidErrorSandboxTerminatedErrorSandboxTimeoutError)FileWatchEventFileWatchEventType_FileIO)GPU_T)_Image)StreamReaderStreamWriter_StreamReader_StreamWriter)_NetworkFileSystem network_file_system_mount_protos)_Proxy)_Secret)_SandboxSnapshot)
StreamType_default_imagei      argsreturnc                 C   sN   t dd | D stdtdd | D }|tkr%tdt d| dd S )Nc                 s   s    | ]}t |tV  qd S N)
isinstancestr.0arg rF   A/home/ubuntu/.local/lib/python3.10/site-packages/modal/sandbox.py	<genexpr>H   s    z&_validate_exec_args.<locals>.<genexpr>z(All entrypoint arguments must be stringsc                 s   s    | ]}t |V  qd S r@   )lenrC   rF   rF   rG   rH   K   s    z,Total length of CMD arguments cannot exceed z bytes (ARG_MAX). Got z bytes.)allr*   sumARG_MAX_BYTES)r>   total_arg_lenrF   rF   rG   _validate_exec_argsF   s   rN   c                   @   s   e Zd ZdZdefddZdS )DefaultSandboxNameOverridezA singleton class that represents the default sandbox name override.

    It is used to indicate that the sandbox name should not be overridden.
    r?   c                 C   s   dS )N_DEFAULT_SANDBOX_NAME_OVERRIDErF   selfrF   rF   rG   __repr__X   s   z#DefaultSandboxNameOverride.__repr__N)__name__
__module____qualname____doc__rB   rS   rF   rF   rF   rG   rO   R   s    rO   T)frozenc                   @   s"   e Zd ZU dZeed< eed< dS )SandboxConnectCredentialszSSimple data structure storing credentials for making HTTP connections to a sandbox.urltokenN)rT   rU   rV   rW   rB   __annotations__rF   rF   rF   rG   rY   `   s   
 rY   c                @   @   sn  e Zd ZU dZeej ed< ee	 ed< ee	 ed< e
ed< ee	 ed< eeeef  ed< eed< ee ed	< ed
ejfddZeddddddddddi ddi ddg g g dddddfdee	 dedee dee	 dedee dee	 dedee	 deee	ee	 f  dee deeeeeef f  dee deee	ejf ef ded eee	  d!eee	ejf eee f f d"ed#eej d$ee d%ee d&ee d'ee! d(eee	ef  d)ed*ed+ee	 d
d f8d,d-Z"edddddi ddddddddddi dg g g ddddddddd.de	d/ed0 dee	 dee d1eee	ee	 f  deee  deee	ejf ef dedee dee	 dedee	 deee	ee	 f  deeeeeef f  deeeeeef f  ded eee	  d!eee	ejf eee f f d"ed$ee d%ee d&ee d+ee	 d'ee! d*ed(eee	ef  d2ed3ee# d4ee	 d#eej d
d f>d5d6Z$eddddddi ddddddddddi dg g g dddddddd7de	d/ed0 dee	 dee d1eee	ee	 f  deee  dee deee	ejf ef dedee dee	 dedee	 deee	ee	 f  deeeeeef f  deeeeeef f  ded eee	  d!eee	ejf eee f f d"ed$ee d%ee d&ee d'ee! d(eee	ef  d2ed3ee# d*ed#eej d+ee	 f<d8d9Z%d:ee& fd;d<Z'eddd=d>e	de	d4ee	 d3ee# d
d f
d?d@Z(eddAe	d3ee# d
d fdBdCZ)d
ee	e	f fdDdEZ*ddFdGee	e	f d3ee# d
dfdHdIZ+dded
efdKdLZ,dMee-e	f dee fdNdOZ.dMee-e	f d
efdPdQZ/ddSefdTdUZ0dded
eeef fdWdXZ1	ddYeee	ee	e2f f  d
e3fdZd[Z4dd\d]Z5dd^d_Z6d
ee fd`daZ7d
e	fdbdcZ8dde	d
ee fdedfZ9e:e;j<e;j<dddddRdgddddhde	die;dje;dee dee	 d1eee	ee	 f  deee  dke=dR dle=dm d"ed#eej dneej d
e>e	 fdodpZ?e:e;j<e;j<ddddddgddddhde	die;dje;dee dee	 d1eee	ee	 f  deee  dke=d dle=dm d"ed#eej dneej d
e>e@ fdqdpZ?e;j<e;j<dddddRdgddddrde	die;dje;dee dee	 d1eee	ee	 f  deee  dkedle=dm d"edneej d#eej fdsdpZ?de;j<e;j<dddddRdgdt	de	d#eej die;dje;dee dee	 d1eee	ee	 f  deee  dkedle=dm d
ee>e@ e>e	 f fdudvZAde;j<e;j<ddddRdgddw	de	dde	d#eej die;dje;dee dee	 dxeee	  dkedle=dm dyed
ee>e@ e>e	 f fdzd{ZBde;j<e;j<ddddRdgddw	de	dde	d|ed#eej die;dje;dee dee	 dxeee	  dkedle=dm dyed
ee>e@ e>e	 f fd}d~ZCd
eDfddZEe	deFddeDd3ee# dee	 fddZGe:dMe	ddd
eHe	 fddZIe:dMe	ddd
eHe@ fddZI	ddMe	ded fddZIdMe	d
eJjKe	 fddZLddMe	ded
dfddZMddMe	ded
dfddZN			ddMe	deeJjKeO  dee dee d
ePeQ f
ddZReSd
ee	 fddZTeSd
ee	 fddZUeSd
e
fddZVeSd
ee fddZWedddddee	 dGeee	e	f  d3ee# d
eXd fddZKdS )_Sandboxa<  A `Sandbox` object lets you interact with a running sandbox. This API is similar to Python's
    [asyncio.subprocess.Process](https://docs.python.org/3/library/asyncio-subprocess.html#asyncio.subprocess.Process).

    Refer to the [guide](https://modal.com/docs/guide/sandbox) on how to spawn and use sandboxes.
    _result_stdout_stderr_stdin_task_id_tunnels_enable_snapshot_command_router_clientr?   c                   C   s   t dddS )NT)shellno_terminate_on_idle_stdinr   rF   rF   rF   rG   _default_pty_infox   s   z_Sandbox._default_pty_infoNi,  rF   Fr>   imagesecretsnametimeoutidle_timeoutworkdirgpucloudregioncpumemorymountsnetwork_file_systemsblock_networkcidr_allowlistvolumesptypty_infoencrypted_portsh2_portsunencrypted_portsproxyexperimental_optionsenable_snapshotverbosecustom_domainc                    s,  t |t
trtddurdstd t|dd D dd D d|	rIt|	tr;|	gn|	rAt|	nd}tj|d|rOt	
 d	tt ffd
d}dt	dtdtdtt f 	
fdd}t	j|d|t dS )zmdmd:hiddenzhSandboxes do not support configuring a list of GPUs. Specify a single GPU configuration, e.g. gpu='a10g'N/'workdir must be an absolute path, got: c                 S   "   g | ]\}}t |tr||fqS rF   )rA   r   rD   kvrF   rF   rG   
<listcomp>      " z!_Sandbox._new.<locals>.<listcomp>c                 S   r   rF   )rA   r   r   rF   rF   rG   r      r   )regionsr?   c                     sx   gt  t  } D ]	\}}| | qD ]	\}}| | q D ]\}}|jr2| |j q%r:|  | S r@   )listappendsecret)deps_volcloud_bucket_mount)cloud_bucket_mountsri   rt   r~   rj   validated_network_file_systemsvalidated_volumesrF   rG   _deps   s   
z_Sandbox._new.<locals>._depsrR   resolverload_context_existing_object_idc              
      sJ  dd D }dd D }| dd D  | dd D  r7d ur-tdtjtjjjd}nd u rEtjtjjjd}n
tjtjjjd}d }tjd)i d	 d
j	ddd D dd j
D  ddd D ddddt
|ddrnd dtdtddtddtd|dddtddtj|d d!|d"rj	n2d d#d$d%d&	d'}tj|j|d(}	|jj|	I d H }
|
j}| ||jd  d S d#d$d%d&	d'}tj|j|d(}	|jj|	I d H }
|
j}| ||jd  d S )*Nc                 S   s&   g | ]\}}t j||jd |jdqS )T)
mount_path	volume_idallow_background_commits	read_only)r   VolumeMount	object_id
_read_only)rD   pathvolumerF   rF   rG   r      s    z0_Sandbox._new.<locals>._load.<locals>.<listcomp>c                 S      g | ]	}t j|d dqS )Fportunencryptedr   PortSpecrD   r   rF   rF   rG   r          c                 S   r   )Tr   r   r   rF   rF   rG   r      r   c                 S   s   g | ]}t j|d t jdqS )F)r   r   tunnel_type)r   r   TUNNEL_TYPE_H2r   rF   rF   rG   r      s    z?`cidr_allowlist` cannot be used when `block_network` is enabled)network_access_type)r   allowed_cidrsentrypoint_argsimage_id	mount_idsc                 S      g | ]}|j qS rF   r   )rD   mountrF   rF   rG   r          
secret_idsc                 S   r   rF   r   rD   r   rF   rF   rG   r      r   timeout_secsidle_timeout_secsrn   	resources)rr   rs   ro   ephemeral_diskcloud_provider_str
nfs_mountsruntimefunction_runtimeruntime_debugfunction_runtime_debugr   volume_mountsrz   scheduler_placement	worker_id
open_ports)portsnetwork_accessproxy_idr   r   rk   r   r   )app_id
definitionrF   )extendr*   r   NetworkAccessNetworkAccessTypeBLOCKEDOPEN	ALLOWLISTSandboxr   _mount_layersr   r7   r   getr   	PortSpecsSandboxCreateRequestr   clientstubSandboxCreate
sandbox_id_hydrate)rR   r   r   r   r   r   r   r   r   
create_reqcreate_respr   r>   rv   rw   rp   r   rr   r   r   r{   r   ro   r|   rm   ri   rs   rt   rk   r~   rz   r   rj   rl   r}   r   r   r   rn   rF   rG   _load   s   





z_Sandbox._new.<locals>._loadz	Sandbox())r   load_context_overrides)r#   rA   r   r*   
startswithr$   rB   r   SchedulerPlacementr]   rh   r   r   r   r   _from_loaderempty)r>   ri   rj   rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   rF   r   rG   _new|   s6    
 "BMz_Sandbox._new)apprk   ri   envrj   ru   rl   rm   rn   ro   rp   rq   rr   rs   rv   rw   rx   ry   r{   r|   r}   r   r~   r   r   _experimental_enable_snapshotr   environment_namerz   r   zmodal.app._Appr   r   r   r   c                    s   |dur
t dd |durt dd |pg }|r"g |t|}tj|i d| d|d|d	|d
|d|d|d|d|	d|
d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|d |I dH S )!a  
        Create a new Sandbox to run untrusted, arbitrary code.

        The Sandbox's corresponding container will be created asynchronously.

        **Usage**

        ```python
        app = modal.App.lookup('sandbox-hello-world', create_if_missing=True)
        sandbox = modal.Sandbox.create("echo", "hello world", app=app)
        print(sandbox.stdout.read())
        sandbox.wait()
        ```
        N)        zPassing `environment_name` to `Sandbox.create` is deprecated and will be removed in a future release. A sandbox's environment is determined by the app it is associated with.r   	      zzThe `pty_info` parameter is deprecated and will be removed in a future release. Set the `pty` parameter to `True` instead.r   rk   ri   rj   ru   rl   rm   rn   ro   rp   rq   rr   rs   rv   rw   rx   ry   r{   r|   r}   r~   r   r   r   r   rz   r   )r"   r9   	from_dictr]   _create)r   rk   ri   r   rj   ru   rl   rm   rn   ro   rp   rq   rr   rs   rv   rw   rx   ry   r{   r|   r}   r   r~   r   r   r   r   r   rz   r>   rF   rF   rG   create  s   @	

z_Sandbox.create)r   rk   ri   r   rj   rt   ru   rl   rm   rn   ro   rp   rq   rr   rs   rv   rw   rx   ry   r{   r|   r}   r~   r   r   r   r   rz   r   c           &   	      s  ddl m} t| |durt|d |r |s|s|r td|p#g }|r/g |t|}tj|fi d|p8t	d|d|d	|d
|d|	d|
d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|d|}||_
d} d}!| dur| jdu rtd | j} | j}!n|  }"dur|"j} |"j}!ntd!|p|!}t }#t 4 I dH }$t|| |$d"}%|#||%I dH  W d  I dH  |S 1 I dH sw   Y  |S )#a#  Private method used internally.

        This method exposes some internal arguments (currently `mounts`) which are not in the public API.
        `mounts` is currently only used by modal shell (cli) to provide a function's mounts to the
        sandbox that runs the shell session.
        r   )_AppNr   z9Cannot specify open ports when `block_network` is enabledri   rj   rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   a  App has not been initialized yet. To create an App lazily, use `App.lookup`: 
app = modal.App.lookup('my-app', create_if_missing=True)
modal.Sandbox.create('echo', 'hi', app=app)
In order to initialize an existing `App` object, refer to our docs: https://modal.com/docs/guide/appsa  Sandboxes require an App when created outside of a Modal container.

Run an ephemeral App (`with app.run(): ...`), or reference a deployed App using `App.lookup`:

```
app = modal.App.lookup("sandbox-app", create_if_missing=True)
sb = modal.Sandbox.create(..., app=app)
```)r   r   task_context)r   r   rN   r%   r*   r9   r   r]   r   r<   rd   r   
ValueError_client_get_container_appr   r    r   load)&r   rk   ri   r   rj   rt   ru   rl   rm   rn   ro   rp   rq   rr   rs   rv   rw   rx   ry   r{   r|   r}   r~   r   r   r   r   rz   r   r>   r   objr   
app_clientcontainer_appr   tcr   rF   rF   rG   r     s   '
	

	z_Sandbox._createhandle_metadatac                 C   sh   t tj| jd| jdd| _t tj| jd| jdd| _t| jd| j| _	d | _
d | _d | _d| _d | _d S )NsandboxT)by_lineF)r2   r   FILE_DESCRIPTOR_STDOUTr   r   r_   FILE_DESCRIPTOR_STDERRr`   r3   ra   r^   rb   rc   rd   re   )rR   r   rF   rF   rG   _hydrate_metadata  s   
z_Sandbox._hydrate_metadata)r   r   app_namec                   sR   |du rt  I dH }t|}tj|| |d}|j|I dH }t|j	|dS )zGet a running Sandbox by name from a deployed App.

        Raises a modal.exception.NotFoundError if no running sandbox is found with the given name.
        A Sandbox's name is the `name` argument passed to `Sandbox.create`.
        N)sandbox_namer  r   )
r'   from_envr   r   SandboxGetFromNameRequestr   SandboxGetFromNamer]   _new_hydratedr   )r  rk   r   r   env_namereqresprF   rF   rG   	from_name  s   z_Sandbox.from_namer   c                    sZ   |du rt  I dH }tj| dd}|j|I dH }t| |d}|jj	r+|j|_
|S )zConstruct a Sandbox from an id and look up the Sandbox result.

        The ID of a Sandbox object can be accessed using `.object_id`.
        Nr   r   rl   )r'   r  r   SandboxWaitRequestr   SandboxWaitr]   r  resultstatusr^   )r   r   r	  r
  r   rF   rF   rG   from_id  s   z_Sandbox.from_idc                    s4   t j| jd}| jj|I dH }dd |jD S )zVFetches any tags (key-value pairs) currently attached to this Sandbox from the server.r   Nc                 S   s   i | ]}|j |jqS rF   tag_name	tag_value)rD   tagrF   rF   rG   
<dictcomp>4  s    z%_Sandbox.get_tags.<locals>.<dictcomp>)r   SandboxTagsGetRequestr   r   r   SandboxTagsGettagsrR   r	  r
  rF   rF   rG   get_tags/  s   z_Sandbox.get_tagsr   r  c                   sV   t  }|durtdd dd | D }tj|| j|d}| jj|I dH  dS )z`Set tags (key-value pairs) on the Sandbox. Tags can be used to filter results in `Sandbox.list`.N)r   r      zThe `client` parameter is deprecated. Set `client` when creating the Sandbox instead (in e.g. `Sandbox.create()`/`.from_id()`/`.from_name()`).c                 S      g | ]\}}t j||d qS r  r   
SandboxTagrD   rk   valuerF   rF   rG   r   @      z%_Sandbox.set_tags.<locals>.<listcomp>)r   r   r  )	r   r"   itemsr   SandboxTagsSetRequestr   r   r   SandboxTagsSet)rR   r  r   r   	tags_listr	  rF   rF   rG   set_tags6  s   z_Sandbox.set_tags7   c           	   	      s   |   I dH  tj| j|d}| jj|I dH }|jjtj	j
kr(t|jj|j}|j}dtdtdtdtt fdd}d	}tj||d
t d}||| j| |S )zSnapshot the filesystem of the Sandbox.

        Returns an [`Image`](https://modal.com/docs/reference/modal.Image) object which
        can be used to spawn a new Sandbox with the same filesystem.
        Nr  rR   r   r   existing_object_idc                       d S r@   rF   rR   r   r   r,  rF   rF   rG   r   Y  s   z+_Sandbox.snapshot_filesystem.<locals>._loadzImage()Thydrate_lazilyr   )_get_task_idr   SandboxSnapshotFsRequestr   r   r   SandboxSnapshotFsr  r  GenericResultGENERIC_STATUS_SUCCESSr)   	exceptionr   image_metadatar1   r   r   r   rB   r   r   r   )	rR   rl   r	  r
  r   metadatar   repri   rF   rF   rG   snapshot_filesystemI  s   z_Sandbox.snapshot_filesystemr   c           	         s   d}|r|j std|j }nd}|  I dH }| |I dH  }du r)tdt|}| s8td| | d}tj	|||d}|
|I dH  dS )z3Mount an Image at a path in the Sandbox filesystem.NzImage has not been built. zTMounting directories requires direct Sandbox control - please contact Modal support.z"Mount path must be absolute; got: utf8)task_idr   r   )
_object_idr*   r1  _get_command_router_clientr   is_absoluteas_posixencodesr_pb2TaskMountDirectoryRequestmount_image)	rR   r   ri   r   r=  command_router_client
posix_path
path_bytesr	  rF   rF   rG   _experimental_mount_imaged  s    z"_Sandbox._experimental_mount_imagec                    s   |   I dH }| |I dH  }du rtdt|}| s'td| | d}tj||d}|	|I dH }t
|j| jdS )zKSnapshot local changes to a previously mounted Image, creating a new Image.NzXSnapshotting directories requires direct Sandbox control - please contact Modal support.z%Snapshot path must be absolute; got: r<  )r=  r   )r1  r?  r*   r   r@  rA  rB  rC  TaskSnapshotDirectoryRequestsnapshot_directoryr1   r  r   r   )rR   r   r=  rF  rG  rH  r	  resrF   rF   rG    _experimental_snapshot_directory}  s   z)_Sandbox._experimental_snapshot_directoryTraise_on_terminationc                    s   	 t j| jdd}| jj|I dH }|jjrDt	d| j d|jj  |j| _
|jjt jjkr5t |jjt jjkrB|rBt dS q)z'Wait for the Sandbox to finish running.T
   r  NzSandbox z wait completed with status )r   r  r   r   r   r  r  r  r   debugr^   r4  GENERIC_STATUS_TIMEOUTr,   GENERIC_STATUS_TERMINATEDr+   )rR   rN  r	  r
  rF   rF   rG   wait  s   z_Sandbox.wait2   c                    s`   | j r| j S tj| j|d}| jj|I dH }|jjtj	j
kr$t dd |jD | _ | j S )a  Get Tunnel metadata for the sandbox.

        Raises `SandboxTimeoutError` if the tunnels are not available after the timeout.

        Returns a dictionary of `Tunnel` objects which are keyed by the container port.

        NOTE: Previous to client [v0.64.153](https://modal.com/docs/reference/changelog#064153-2024-09-30), this
        returned a list of `TunnelData` objects.
        r  Nc                 S   s&   i | ]}|j t|j|j|j|jqS rF   )container_portr   hostr   unencrypted_hostunencrypted_port)rD   trF   rF   rG   r    s    z$_Sandbox.tunnels.<locals>.<dictcomp>)rc   r   SandboxGetTunnelsRequestr   r   r   SandboxGetTunnelsr  r  r4  rQ  r,   tunnels)rR   rl   r	  r
  rF   rF   rG   r\    s   z_Sandbox.tunnelsuser_metadatac              
      s|   |dur%t |tr%zt|}W n ty$ } ztd| d}~ww tj| j|d}| j	j
|I dH }t|j|jS )a  
        [Alpha] Create a token for making HTTP connections to the Sandbox.

        Also accepts an optional user_metadata string or dict to associate with the token. This metadata
        will be added to the headers by the proxy when forwarding requests to the Sandbox.Nz#Failed to serialize user_metadata: )r   r]  )rA   dictjsondumps	Exceptionr*   r    SandboxCreateConnectTokenRequestr   r   r   SandboxCreateConnectTokenrY   rZ   r[   )rR   r]  er	  r
  rF   rF   rG   create_connect_token  s   z_Sandbox.create_connect_tokenc                    s0   |   I dH }| jjtj|dI dH  dS )zMReload all Volumes mounted in the Sandbox.

        Added in v1.1.0.
        N)r=  )r1  r   r   ContainerReloadVolumesr   ContainerReloadVolumesRequestrR   r=  rF   rF   rG   reload_volumes  s   z_Sandbox.reload_volumesc                    s$   | j jtj| jdI dH  dS )zbTerminate Sandbox execution.

        This is a no-op if the Sandbox has already finished running.r  N)r   r   SandboxTerminater   SandboxTerminateRequestr   rQ   rF   rF   rG   	terminate  s   "z_Sandbox.terminatec                    s<   t j| jdd}| jj|I dH }|jjr|j| _| j	S )zCheck if the Sandbox has finished running.

        Returns `None` if the Sandbox is still running, else returns the exit code.
        r   r  N)
r   r  r   r   r   r  r  r  r^   
returncoder  rF   rF   rG   poll  s   z_Sandbox.pollc                    sP   | j s%| jjtj| jdI d H }|j| _ | j s"t	dI d H  | j r| j S )Nr  g      ?)
rb   r   r   SandboxGetTaskIdr   SandboxGetTaskIdRequestr   r=  asynciosleep)rR   r
  rF   rF   rG   r1    s   z_Sandbox._get_task_idr=  c                    s(   | j d u rt| j|I d H | _ | j S r@   )re   r&   try_initr   rh  rF   rF   rG   r?    s   
z#_Sandbox._get_command_router_client)stdoutstderrrl   rn   r   rj   textbufsizery   rz   	_pty_inforu  rv  rw  rx  )rt  r   ry  c                   r-  r@   rF   rR   ru  rv  rl   rn   r   rj   rw  rx  ry   rz   ry  r>   rF   rF   rG   exec     z_Sandbox.execc                   r-  r@   rF   rz  rF   rF   rG   r{    r|  )ru  rv  rl   rn   r   rj   rw  rx  ry   ry  rz   c                   sV   |dus	|
durt dd |
p|}|	r|  }| j||||||||||d	I dH S )a  Execute a command in the Sandbox and return a ContainerProcess handle.

        See the [`ContainerProcess`](https://modal.com/docs/reference/modal.container_process#modalcontainer_processcontainerprocess)
        docs for more information.

        **Usage**

        ```python fixture:sandbox
        process = sandbox.exec("bash", "-c", "for i in $(seq 1 3); do echo foo $i; sleep 0.1; done")
        for line in process.stdout:
            print(line)
        ```
        Nr   zThe `_pty_info` and `pty_info` parameters are deprecated and will be removed in a future release. Set the `pty` parameter to `True` instead.	rz   ru  rv  rl   rn   r   rj   rw  rx  )r"   rh   _exec)rR   ru  rv  rl   rn   r   rj   rw  rx  ry   ry  rz   r>   rF   rF   rG   r{  !  s*   !r}  c       	            s   |dur| dstd| t|
 |pg }|r$g |t|} fdd|D }tj| I dH    I dH }||||||dd |D ||	t	dd
} 
|I dH  }durl||d	<  j|
i |I dH S  j|
i |I dH S )
zPrivate method used internally.

        This method exposes some internal arguments (currently `pty_info`) which are not in the public API.
        Nr   r   c                    s   g | ]	}|j  jd qS )r  )hydrater   r   rQ   rF   rG   r   s  r   z"_Sandbox._exec.<locals>.<listcomp>c                 S   r   rF   r   r   rF   rF   rG   r   ~  r   r   )
r=  rz   ru  rv  rl   rn   r   rw  rx  r   rF  )r   r*   rN   r9   r   r    gatherr1  r   r   r?  _exec_through_command_router_exec_through_server)rR   rz   ru  rv  rl   rn   r   rj   rw  rx  r>   secret_corosr=  kwargsrF  rF   rQ   rG   r~  Y  s2   z_Sandbox._exec)	rz   ru  rv  rl   rn   r   rw  rx  r   r   r   c       
      
      s   t j||||
|p
d||d}| jj|I dH }|	dk}|r)t t| t nd}t	
d|j d| j  t|j|| j|||||dS )z+Execute a command through the Modal server.r   )r=  commandrz   r   r   rn   r   Nr   z%Created ContainerProcess for exec_id z on Sandbox )ru  rv  rw  exec_deadliner   )r   ContainerExecRequestr   r   ContainerExectime	monotonicintCONTAINER_EXEC_TIMEOUT_BUFFERr   rP  exec_idr   r(   )rR   r=  rz   ru  rv  rl   rn   r   rw  rx  r   r>   r	  r
  r   r  rF   rF   rG   r    s0   	z_Sandbox._exec_through_serverrF  c                   s   t t }|tjkrtjj}n|tjkrtjj	}n|tj
kr%tjj}ntd|tjkr3tjj}n|tjkr=tjj}n|tj
krGtjj}ntdtj||||||||||d
}||I dH }t||| j||||	|
dk|rzt t| d	S dd	S )zLExecute a command through a task command router running on the Modal worker.z!Unsupported StreamType for stdoutz!Unsupported StreamType for stderr)
r=  r  command_argsstdout_configstderr_configr   rn   r   rz   r   Nr   )rF  ru  rv  rw  r   r  )rB   uuiduuid4r;   PIPErC  TaskExecStdoutConfigTASK_EXEC_STDOUT_CONFIG_PIPEDEVNULLTASK_EXEC_STDOUT_CONFIG_DEVNULLSTDOUTr   TaskExecStderrConfigTASK_EXEC_STDERR_CONFIG_PIPETASK_EXEC_STDERR_CONFIG_DEVNULLTaskExecStartRequest
exec_startr(   r   r  r  r  )rR   r=  rF  rz   ru  rv  rl   rn   r   rw  rx  r   r>   
process_idr  r  	start_reqr   rF   rF   rG   r    sT   











	z%_Sandbox._exec_through_command_routerc           	   	      s   |   I d H  tj| jd}| jj|I d H }|j}tj|dd}| jj	|I d H }|j
jtjjkr;t|j
jdtdtdtdtt fdd	}d
}tj||dt d}||| jd  |S )Nr       K@)snapshot_idrl   rR   r   r   r,  c                    r-  r@   rF   r.  rF   rF   rG   r     s   z._Sandbox._experimental_snapshot.<locals>._loadzSandboxSnapshot()Tr/  )r1  r   SandboxSnapshotRequestr   r   r   SandboxSnapshotr  SandboxSnapshotWaitRequestSandboxSnapshotWaitr  r  r4  r5  r)   r6  r:   r   r   r   rB   r   r   r   )	rR   snap_req	snap_respr  wait_req	wait_respr   r9  r   rF   rF   rG   _experimental_snapshot  s,   
z_Sandbox._experimental_snapshot)rk   snapshotc                   s   |p	t  I d H }|d ur|tkrt|d |tu r&tj| jtjjd}n|d u r5tj| jtjjd}ntj| j|tjj	d}|j
|I d H }t|j|I d H }tj|jddd}|j
|I d H }|jjtjjtjjfvrwt|jj|S )Nr   )r  sandbox_name_override_type)r  sandbox_name_overrider  Tr  )r   wait_until_readyrl   )r'   r  rP   r%   r   SandboxRestoreRequestr   &SANDBOX_NAME_OVERRIDE_TYPE_UNSPECIFIEDSANDBOX_NAME_OVERRIDE_TYPE_NONE!SANDBOX_NAME_OVERRIDE_TYPE_STRINGr   SandboxRestorer]   r  r   rp  ro  task_resultr  r4  GENERIC_STATUS_UNSPECIFIEDr5  r)   r6  )r  r   rk   restore_reqrestore_respr   task_id_reqr
  rF   rF   rG   _experimental_from_snapshot  s>   
z$_Sandbox._experimental_from_snapshotmode_typeshed.OpenTextModec                    r-  r@   rF   rR   r   r  rF   rF   rG   open:     z_Sandbox.open_typeshed.OpenBinaryModec                    r-  r@   rF   r  rF   rF   rG   r  A  r  r)r  r  c                    s(   |   I dH }t||| j|I dH S )ay  [Alpha] Open a file in the Sandbox and return a FileIO handle.

        See the [`FileIO`](https://modal.com/docs/reference/modal.file_io#modalfile_iofileio) docs for more information.

        **Usage**

        ```python notest
        sb = modal.Sandbox.create(app=sb_app)
        f = sb.open("/test.txt", "w")
        f.write("hello")
        f.close()
        ```
        N)r1  r/   r   r   )rR   r   r  r=  rF   rF   rG   r  H  s   c                    s&   |   I dH }t|| j|I dH S )z8[Alpha] List the contents of a directory in the Sandbox.N)r1  r/   lsr   )rR   r   r=  rF   rF   rG   r  ]  s   z_Sandbox.lsparentsc                    (   |   I dH }t|| j||I dH S )z.[Alpha] Create a new directory in the Sandbox.N)r1  r/   mkdirr   )rR   r   r  r=  rF   rF   rG   r  b     z_Sandbox.mkdir	recursivec                    r  )z2[Alpha] Remove a file or directory in the Sandbox.N)r1  r/   rmr   )rR   r   r  r=  rF   rF   rG   r  g  r  z_Sandbox.rmfilterc                 C  s@   |   I dH }t|| j||||2 z	3 dH W }|V  q6 dS )z=[Alpha] Watch a file or directory in the Sandbox for changes.N)r1  r/   watchr   )rR   r   r  r  rl   r=  eventrF   rF   rG   r  l  s
   "z_Sandbox.watchc                 C      | j S )z
        [`StreamReader`](https://modal.com/docs/reference/modal.io_streams#modalio_streamsstreamreader) for
        the sandbox's stdout stream.
        )r_   rQ   rF   rF   rG   ru  x     z_Sandbox.stdoutc                 C   r  )z[`StreamReader`](https://modal.com/docs/reference/modal.io_streams#modalio_streamsstreamreader) for
        the Sandbox's stderr stream.
        )r`   rQ   rF   rF   rG   rv    s   z_Sandbox.stderrc                 C   r  )z
        [`StreamWriter`](https://modal.com/docs/reference/modal.io_streams#modalio_streamsstreamwriter) for
        the Sandbox's stdin stream.
        )ra   rQ   rF   rF   rG   stdin  r  z_Sandbox.stdinc                 C   sN   | j du s| j jtjjkrdS | j jtjjkrdS | j jtjjkr#dS | j jS )zKReturn code of the Sandbox process if it has finished running, else `None`.N|      )r^   r  r   r4  r  rQ  rR  exitcoderQ   rF   rF   rG   rm    s   z_Sandbox.returncode)r   r  r   r   )r]   Nc           
      C  s   d}t  }|du rt I dH }|rdd | D ng }	 tj| ||d|d}|j|I dH }|js7dS |jD ]}t	
|j|d}	|jj|	_|	V  q:|jd j}q)zList all Sandboxes for the current Environment or App ID (if specified). If tags are specified, only
        Sandboxes that have at least those tags are returned. Returns an iterator over `Sandbox` objects.Nc                 S   r  r   r!  r#  rF   rF   rG   r     r%  z!_Sandbox.list.<locals>.<listcomp>TF)r   before_timestampr   include_finishedr  rt  )r   r'   r  r&  r   SandboxListRequestr   SandboxList	sandboxesr]   r  id	task_infor  r^   
created_at)
r   r  r   r  r   r)  r	  r
  sandbox_infor   rF   rF   rG   r     s.   	

z_Sandbox.listr@   )r+  )T)rT  )r?   N)r  )F)NNN)YrT   rU   rV   rW   r   r   r4  r\   r4   rB   r5   r^  r  r   boolr&   staticmethodPTYInforh   r   r1   r   r9   r0   r   floattupler   osPathLiker6   r   r   r8   r   r'   r   r   r   r  r  r  r  r*  r:  r   rI  rM  rS  r\  r   rY   re  ri  rl  rn  r1  r?  r   r;   r  r
   r(   r{  bytesr~  r  r  r:   r  rP   r  r/   r  builtinsr   r  r  r  r.   r	   r-   r  propertyru  rv  r  rm  r   rF   rF   rF   rG   r]   h   s  
 	

 
	
!#%')*,-./0p
	

w(



	

	

;
	

6
	

,	


B*	

r]   sb)type_prefix)nrq  r  r_  r  r  r  collections.abcr   r   r   dataclassesr   pathlibr   typingr   r   r	   r
   r   r   r   _output.ptyr   r   r   	_typeshedgoogle.protobuf.messager   modal._tunnelr   modal.cloud_bucket_mountr   r   modal.mountr   modal.volumer   modal_protor   r   rC  _load_contextr   _objectr   r   	_resolverr   
_resourcesr   _utils.async_utilsr    r!   _utils.deprecationr"   _utils.mount_utilsr#   r$   _utils.name_utilsr%   !_utils.task_command_router_clientr&   r   r'   container_processr(   r6  r)   r*   r+   r,   file_ior-   r.   r/   ro   r0   ri   r1   
io_streamsr2   r3   r4   r5   network_file_systemr6   r7   r~   r8   r   r9   r  r:   stream_typer;   debian_slimr<   r\   rL   r  	modal.appmodalrB   rN   rO   rP   rY   r]   r   rF   rF   rF   rG   <module>   sz   
$
        g