
    \jG                        d Z ddlZddlZddlmZ ddlmZmZmZ ddl	Z	ddl
mZmZmZmZmZ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 dd	lmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& dd
l'm(Z(m)Z) ddl*m+Z+ ddl,m-Z-m.Z.  e&d      Z/ e&d      Z0e/jc                  e0d        e&d      Z2e/jc                  e2d       ee3 e(d      f   Z4ede3de3dz  de3dz  dee   fd       Z5e/jm                  dg d      	 	 	 	 	 	 	 	 	 	 	 	 drdee3dz   e(d      f   dee3dz   e)dd       f   d!e-d"ee3dz   e)d#      f   d$ed%e d&ed'ed(e"de.d)ee7 e)d*d+      f   de!ddfd,       Z8e/jm                  d-d.d/id0d1g2      	 	 	 	 	 	 dsde4d3ee9e3    e(d4      f   d5ee3dz   e)d6d7d8      f   d$ed&ed9ee:dz   e)d:d;      f   de.de!ddfd<       Z;e/jm                  d=d.d/id>d?g2      	 	 	 	 	 dtde4d3ee9e3    e(d@      f   d5ee3dz   e)d6d7d8      f   d$ed&ede.de!ddfdA       Z<e/jm                  dBdCdDg      	 	 dudEee3 e(dF      f   dGee3 e(dH      f   de.de!ddf
dI       Z=e/jm                  dJg dK      	 	 	 	 	 dvdee3dz   e(dL      f   dMee7 e)dNdO      f   dPee7 e)dQdRdS      f   de.de!ddfdT       Z>e0jm                  dg dU      ddeddddfdee3dz   e(dV      f   d!e-dWee? e)dXddYe dZ[      f   d\ee?dz   e)d]dd^[      f   d"ee3dz   e)d_      f   de.de!ddfd`       Z@e0jm                  dadbg      	 	 dude.de!ddfdc       ZAe0jm                  dddeg      	 	 	 dwdfee3 e(dg      f   dPee7 e)dQdRdS      f   de.de!ddf
dh       ZBdie3e9e3   z  de3fdjZCdede3fdkZDe2jm                  dadlg      	 	 dude4de.de!ddfdm       ZEe2jm                  dJdng      	 	 dude4doee? e(dp      f   de.de!ddf
dq       ZFy)xzCContains commands to run and manage sandboxes on Hugging Face Jobs.    N)contextmanager)	AnnotatedAnyIterator)DEFAULT_IDLE_TIMEOUTDEFAULT_IMAGEDEFAULT_SANDBOXES_PER_HOST
MODE_LABEL	MODE_POOL
POOL_LABELSANDBOX_LABELSHARED_ID_SEPSandboxSandboxPoolSandboxProcess_split_sandbox_id)delete_pool_cache)CLIErrorSandboxError   )

EnvFileOptEnvOptSecretsFileOpt
SecretsOptTokenOpt
VolumesOpt
get_hf_apiparse_env_mapparse_volumestyper_factory)ArgumentOption)out)	FlavorOptNamespaceOptz.Run and manage sandboxes on Hugging Face Jobs.)helpzBWarm pools of host VMs and spawn cheap shared sandboxes from them.pool)namez8List and stop background processes running in a sandbox.processz1The sandbox id as printed by `hf sandbox create`.
sandbox_id	namespacetokenreturnc             #      K   t        j                  | ||      }	 | |j                          y# |j                          w xY ww)zIReattach to a sandbox and close the HTTP client when the command is done.r+   r,   N)r   connectclose)r*   r+   r,   sandboxs       N/root/.hermes/venv/lib/python3.12/site-packages/huggingface_hub/cli/sandbox.py_connectr4   B   s6      oojIUKGs   A1 AAAcreate)zhf sandbox createzhf sandbox create ubuntu:24.04z%hf sandbox create --flavor a10g-smallz@hf sandbox create --pool pool-ab12cd34ef56 --env LOG_LEVEL=debug)examplesimagezDocker image (needs /bin/sh).z--poolzJSpawn a cheap shared sandbox in this pool (from `hf sandbox pool create`).flavoridle_timeoutzTAuto-terminate the sandbox after this much inactivity (e.g. '10m'). Defaults to 10m.envsecretsenv_filesecrets_filevolumeforward_hf_tokenz--forward-hf-tokenz0Inject your HF token as HF_TOKEN in the sandbox.c                    t        j                          }||nt        }|| ||rt        d      |s|rt        d      t        j                  ||	|      j                  t        ||      ||
      }t        j                  d|j                  |j                  |t        j                          |z
  dd	       t        j                  d
|j                   d       t        j                  d|j                   d       yt        j
                  | xs t        |xs d|t        ||      t        ||      t        |      |	|
|	      }|j                          t        j                  d|j                  |j                   t        j                          |z
  dd       t        j                  d
|j                   d       t        j                  d|j                   d       y)a  Create a sandbox: a dedicated VM by default, or a cheap shared one with `--pool`.

    Env and idle-timeout apply to the sandbox in both modes. With `--pool`, the image and
    flavor come from the pool, so passing them here is an error; `--secrets` is also
    rejected since pooled sandboxes have no encrypted-secrets channel (use `--env`). Define
    a pool first with `hf sandbox pool create`.
    NzQ--pool fixes the image/flavor (and volumes aren't supported); drop those options.zF--pool can't encrypt secrets; pass them with --env/--env-file instead.r/   )r:   r9   r?   zSandbox ready.1fs)idhostr'   elapsedz$Run a command with `hf sandbox exec z -- echo hello`.z#Terminate it with `hf sandbox kill `.	cpu-basic)	r7   r8   r9   r:   r;   volumesr+   r?   r,   )rC   r7   rE   )timer   r   r   r0   r5   r   r#   resultrC   host_idhintr   r   r   r1   r7   )r7   r'   r8   r9   r:   r;   r<   r=   r>   r+   r?   r,   startidlesbxr2   s                   r3   sandbox_createrP   L   s   L IIKE'3<9MD 2fnoolcdd!!$)5IPPc8,- Q 

 	

?svvCKKdW[W`W`WbejWjknVoopTqr7x?OPQ6svvhbABnn$}$#x(g|4f%)
G MMOJJ7::W]]tyy{]bObcfNgghLijHH3GJJ<?OPQHH27::,bAB    execignore_unknown_optionsTz5hf sandbox exec <sandbox_id> -- python -c "print(42)"z1hf sandbox exec -w /app <sandbox_id> -- pytest -x)context_settingsr6   commandzThe command to run.workdirz-wz	--workdirzWorking directory.exec_timeoutz	--timeoutz)Kill the command after this many seconds.c           
         dt         ddfd}dt         ddfd}	t        | ||      5 }
|
j                  t        |      t	        ||      ||||	d      }ddd       j
                  rGt        j                  d	| d
       t        j                  j                  |j                  xs d      |j                  dk7  r=t        j                  j                  |j                  |j                        d      y# 1 sw Y   xY w)zRun a command in a sandbox, streaming output. Exits with the command's exit code.

    To start a long-running command in the background instead of waiting for it, use
    `hf sandbox spawn`.
    datar-   Nc                 ~    t         j                  j                  |        t         j                  j                          y N)sysstdoutwriteflushrY   s    r3   write_stdoutz"sandbox_exec.<locals>.write_stdout   $    



rQ   c                 ~    t         j                  j                  |        t         j                  j                          y r[   )r\   stderrr^   r_   r`   s    r3   write_stderrz"sandbox_exec.<locals>.write_stderr   rb   rQ   r/   F)r:   cwdtimeout	on_stdout	on_stderrcheckzCommand timed out after zs.|   )coder   r   )strr4   runlistr   	timed_outr#   errorclick
exceptionsExit	exit_code)r*   rU   rV   r:   r<   rW   r+   r,   ra   re   r2   rJ   s               r3   sandbox_execrv      s   43 4 3 4  
*		? 	
7Mc8, ""  
	
 		,\N"=>##)9)9)@S#AA1##V=M=M=Y)9)9#aa_`#aa 	
 	
s   ,C;;Dspawnz;hf sandbox spawn <sandbox_id> -- python -m http.server 8000z8hf sandbox spawn -w /app <sandbox_id> -- uvicorn app:appz%The command to run in the background.c                 \   t        | ||      5 }|j                  t        |      t        ||      |d      }ddd       t	        j
                  d| j                         t	        j                  d|  d       t	        j                  d	|  d
|j                   d       y# 1 sw Y   kxY w)zStart a long-running command in the background and return its pid (don't wait).

    List a sandbox's processes with `hf sandbox process ls` and stop one with
    `hf sandbox process kill`.
    r/   T)r:   rf   
backgroundNzProcess startedr2   pidz+List processes with `hf sandbox process ls rF   z&Stop it with `hf sandbox process kill  )r4   rn   ro   r   r#   rJ   r{   rL   )	r*   rU   rV   r:   r<   r+   r,   r2   r)   s	            r3   sandbox_spawnr}      s    , 
*		? m7++d7msH1MSZgk+lmJJ *'++FHH::,bIJHH5j\7;;-rRS	m ms   )B""B+cpz2hf sandbox cp data.csv <sandbox_id>:/data/data.csvz7hf sandbox cp <sandbox_id>:/app/result.json result.jsonsrcz,Source: a local path or <sandbox_id>:<path>.dstz1Destination: a local path or <sandbox_id>:<path>.c                    dt         dt        t         dz  t         f   fd} ||       \  }} ||      \  }}|du |du k(  rt        d      |4t        |||      5 }	|	j                  j                  ||       ddd       n7|J t        |||      5 }	|	j                  j                  ||       ddd       t        j                  d| |       y# 1 sw Y   "xY w# 1 sw Y   .xY w)	zCCopy a file between the local machine and a sandbox (docker-style).refr-   Nc                     d| v r8| j                  d      s'| j                  dd      \  }}t        |      dkD  r||fS d | fS )N:)./~r   )
startswithsplitlen)r   r*   paths      r3   parsezsandbox_cp.<locals>.parse   sL     #:cnn_="yya0J:"!4''SyrQ   zHExactly one of SRC and DST must be a sandbox path (<sandbox_id>:<path>).r/   Copied)r   r   )	rm   tupler   r4   filesdownloaduploadr#   rJ   )
r   r   r+   r,   r   src_sandboxsrc_pathdst_sandboxdst_pathr2   s
             r3   
sandbox_cpr      s    3 5tS1  "#JK!#JKt!45abbkYeD 	7MM""8X6	7 	7 &&&kYeD 	5MM  84	5JJxSc*	7 	7	5 	5s   CCCC&kill)zhf sandbox kill <sandbox_id>zKhf sandbox kill <host_id>   # kills a whole shared host (all its sandboxes)zhf sandbox kill --allz$The sandbox or host id to terminate.all_z--allz2Terminate every sandbox and host in the namespace.yesz-yz--yesz$Answer Yes to prompts automatically.c                    t        |      }|rt        |j                  ddgt        di|            }|st	        j
                  d       yt	        j                  dt        |       d	|
       |D ]3  }|j                  |j                  |j                  j                         5 t	        j                  dt        |             y| t        d      t        | |      \  }}	t        |v r@	 t!        | ||      5 }
|
j#                          ddd       t	        j                  d|        y|j)                  ||	      }|j*                  xs i j-                  t.              t0        k(  rdt	        j                  d| d|
       |j                  |j                  |j                  j                         t	        j                  d|       y	 t!        | ||      5 }
|
j#                          ddd       t	        j                  d|        y# 1 sw Y   xY w# t$        $ r}t        t'        |            |d}~ww xY w# 1 sw Y   TxY w# t$        $ r}t        t'        |            |d}~ww xY w)z@Terminate a sandbox, a whole shared host, or everything (--all).r,   RUNNING
SCHEDULING1statuslabelsr+   zNo running sandboxes.N
Terminate zA sandbox job(s) (including shared hosts and all their sandboxes)?r   job_idr+   
Terminated)jobsz*Provide a sandbox id, a host id, or --all.r/   zSandbox terminated)rC   zTerminate shared host z and all of its sandboxes?zHost terminated)r   ro   	list_jobsr   r#   textconfirmr   
cancel_jobrC   ownerr(   rJ   r   r   r   r4   r   r   rm   inspect_jobr   getr
   r   )r*   r   r   r+   r,   apir   jobsidnsr2   es               r3   sandbox_killr     s     5
!CCMM)\)BM[^K_ktMuvHH,-jT+lmsvw 	DCNN#&&CIINNNC	D

<c$i0CDD
I6GC	**	G 7 	

'J7 ///
3C

bj)Y6,SE1KLRUVcff		?

$-&jIUC 	wLLN	 JJ#
3'  	*3q6")	*	 	 &s1vA%&s`   .H <HH I I.I HH 	H>$H99H>I
I 	I0I++I0)zhf sandbox pool createz5hf sandbox pool create python:3.12 --flavor cpu-basicz7hf sandbox pool create --per-host 50 --idle-timeout 30mz+Docker image for the hosts (needs /bin/sh).per_hostz
--per-hostz&Sandboxes packed per host VM (default z).)minr&   	max_hostsz--max-hostsz'Optional cap on the number of host VMs.zZShut a host down once it has had no sandboxes for this long (e.g. '10m'). Defaults to 10m.c           	         t        j                          }| xs t        } t        | |xs d||||nt        ||      }|j                  }	|j
                  }
t        j                  d|	| |xs d|
d   t        j                          |z
  dd       t        j                  d	|	 d
       t        j                  d|	 d
       y)zRWarm a pool: boot one host VM now, tagged so it can be found later by its pool id.rG   N)r7   r8   sandboxes_per_hostr   r9   r+   r,   zPool createdr   rA   rB   )rC   r7   r8   rD   rE   z/Spawn a sandbox with `hf sandbox create --pool rF   z=Delete the pool (and its hosts) with `hf sandbox pool delete )	rI   r   r   r   r(   host_idsr#   rJ   rL   )r7   r8   r   r   r9   r+   r,   rM   r'   pool_idr   s              r3   pool_creater   G  s    4 IIKE"]E$#%1%=\CWD iiG}}HJJ$a[99;&s+1- HH>wirJKHHLWIUWXYrQ   z	ls | listzhf sandbox pool lsc                 j   t        |      }i }|j                  dt        t        i|       D ]  }|j                  xs i j                  t              }|s)t        |j                  t              r|j                  ni }|j                  |||j                  xs |j                  |j                  |j                  dd      dd      }|dxx   d	z  cc<    t        |j                               }t!        j"                  |d
       |st!        j$                  d       yt!        j$                  d       y)z9List running sandbox pools (grouped from their host VMs).r   r   r   SBX_CAPACITY r   )rC   r7   r8   r   hostsr   r   rC   id_keyz)Create one with `hf sandbox pool create`.z5Spawn a sandbox with `hf sandbox create --pool <id>`.N)r   r   r
   r   r   r   r   
isinstanceenvironmentdict
setdefaultdocker_imagespace_idr8   ro   valuesr#   tablerL   )	r+   r,   r   poolsr   r{   r:   inforowss	            r3   pool_lsr   z  s     5
!C')E}}Iz96MYb}c zzR$$Z0!+COOT!Bcoo))9S\\**GGNB7	
 	W  DIId4 <=HIrQ   zdelete | rmz hf sandbox pool delete <pool_id>r   zPool id to delete.c           	         t        |      }t        |j                  ddgt        t        t
        | i|            }|s%t        |        t        j                  d|  d       yt        j                  dt        |       d	|  d
|       |D ]3  }|j                  |j                  |j                  j                         5 t        |        t        j                  d| t        |             y)zDTerminate every host VM of a pool (and therefore all its sandboxes).r   r   r   r   zNo running hosts for pool 'z'.Nr   z host(s) of pool 'z' (and all their sandboxes)?r   r   zPool deleted)rC   hosts_terminated)r   ro   r   r
   r   r   r   r#   r   r   r   r   rC   r   r(   rJ   )r   r   r+   r,   r   r   r   s          r3   pool_deleter     s     5
!C|,	:w? 	 	
E '".wir:;KK*SZL(:7)C_`fij @cff		?@gJJ~'CJGrQ   cmdc                 H    t        | t              r| S dj                  |       S )Nr|   )r   rm   join)r   s    r3   _fmt_cmdr     s    S#&39CHHSM9rQ   c                 X    | j                   ry| j                  dS d| j                   dS )Nrunningexitedzexited ())r   ru   )r)   s    r3   _fmt_statusr     s3    ((08UARAR@SST6UUrQ   z"hf sandbox process ls <sandbox_id>c                 ~   t        | ||      5 }|j                         }ddd       D cg c].  }|j                  t        |      t	        |j
                        d0 }}t        j                  |d       |st        j                  d|  d       yt        j                  d|  d	       y# 1 sw Y   xY wc c}w )
zUList the background processes running in a sandbox (started with `hf sandbox spawn`).r/   N)r{   r   r   r{   r   z!Start one with `hf sandbox spawn z -- <cmd>`.z'Stop one with `hf sandbox process kill z <pid>`.)	r4   	processesr{   r   r   r   r#   r   rL   )r*   r+   r,   r2   r   pr   s          r3   
process_lsr     s     
*		? (7%%'	(V_`QRAEE[^HQUUOL`D`IId5!4ZLLM::,hOP( (`s   B.3B:.B7z*hf sandbox process kill <sandbox_id> <pid>r{   z.The pid as printed by `hf sandbox process ls`.c                 
   t        | ||      5 }t        fd|j                         D        d      }|t        d d|  d      |j	                          ddd       t        j                  d|        y# 1 sw Y   "xY w)	z/Stop a background process running in a sandbox.r/   c              3   B   K   | ]  }|j                   k(  s|  y wr[   )r{   ).0r   r{   s     r3   	<genexpr>zprocess_kill.<locals>.<genexpr>  s     Ga!%%3,Gs   NzNo process with pid z in sandbox r   zProcess stoppedrz   )r4   nextr   r   r   r#   rJ   )r*   r{   r+   r,   r2   r)   s    `    r3   process_killr     s     
*		? 7G7#4#4#6GN?1#l:,aPQQ	
 JJ *#> s   AA99B)NNNNNNNNNNFN)NNNNNN)NNNNN)NN)NFFNN)FNN)G__doc__r\   rI   
contextlibr   typingr   r   r   rr   huggingface_hub._sandboxr   r   r	   r
   r   r   r   r   r   r   r   r   huggingface_hub._sandbox_cacher   huggingface_hub.errorsr   r   
_cli_utilsr   r   r   r   r   r   r   r   r   r    
_frameworkr!   r"   _outputr#   r   r$   r%   sandbox_clipool_cli	add_groupprocess_clirm   SandboxIdArgr4   rU   boolrP   ro   floatrv   r}   r   r   intr   r   r   r   r   r   r    rQ   r3   <module>r      s+   J 
  % + +     = 9   )  ) !QRbc   hV  ,![\   k	  2h,_``a  C$J sTz hW^N_      TX 	 	#'" 	)>CS4Z/N!OOP>C
d
xjk	m>C >C d
jk	m>C 
>C >C >C !>C >C  !>C"  f)0bcc#>C( )>C* 
+>C>CB 
.5?;   \` 	"(b(btCy(0E"FFG(b sTz6$BV#WWX(b 
	(b
 (b f[/Z[[(b (b (b 
(b(bV .5EB   \`"TTtCy(0W"XXYT sTz6$BV#WWXT 
	T
 T T T 
TT* <A   #	+	3&TUU	V+	3&YZZ	[+ + 	+
 
++@ 
   `dhm_d"/4#*h4Z&[[\/4
D&/cdd
e/4 
4g4Z[[	\/4 	/4
 /4 
/4/4d 
   bf 	# 	 	"(ZS4Z/\!]]^(Z(Z |+QRlQmmo)pq	s(Z d
F=a6_``(Z d
pq	s(Z (Z (Z  
!(Z(ZV 
+)=(>?"JJJ 
J @J> 
01   `e"	HsH*>??@H	4g4Z[[	\H H 	H
 
H	H4:#S	/ :c :V VC V [,P+QR #QQQ Q 
	Q SQ  V'S&TU #	??	3&VWW	X? ? 	?
 
? V?rQ   