
    gj0              *          d 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 ddl	m	Z	 ddl
mZmZ ddlmZmZmZ ddlmZ ddlZddlmZmZmZmZ dd	lmZ dd
lmZ ddl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.m/Z/m0Z0m1Z1m2Z2 ddl3m4Z4m5Z5  ej6        e7          Z8de9de9dz  de:e9e9dz  f         fdZ;dZ<ee9 ej=        d          f         Z>ee9dz   ej?        d          f         Z@ee9dz   ej?        d e)e                    f         ZAeeBe9         dz   ej?        ddd          f         ZCee9dz   ej?        d          f         ZDeeE ej?        dd d!          f         ZFee9dz   ej?        d"          f         ZGeeBeH         dz   ej?        d#d$          f         ZIeeE ej?        d%d&          f         ZJeeBe9         dz   ej?        d'd(          f         ZKee9dz   ej?        d)d*d+          f         ZLeeEdz   ej?        d,          f         ZMeeEdz   ej?        d-          f         ZNee9 ej=        d.          f         ZOee9 ej=        d/          f         ZPeeBe9         dz   ej=        d0          f         ZQeeBe9          ej=        d1          f         ZRee9 ej=        d2          f         ZSeeBe9         dz   ej=        d3          f         ZTee9 ej=        d4          f         ZU e2d5          ZVd6ed7eddfd8ZWeVX                    d9d:d;ig d<=          	 	 	 	 	 	 	 	 	 	 	 	 	 dd?e>d@eRdAe&dBe(dCeCdDe-dEe%dFe'dGeAdHeDdIeFdJeIdKeJdeGdLe,ddf dM            ZYeVX                    dNg dOP          	 	 	 	 ddeSdQeeE ej?        dRdSdT          f         dUeeHdz   ej?        dVdWdX          f         deGdLe,ddfdY            ZZdZe[e9e9f         d[eBe:e9e9e9f                  deEfd\Z\d]eHddfd^Z]de9d_ee[e9ef                  d`eBe9         dee:eEe9eBeBe9eHz                    f                  fdaZ^eVX                    dbdcgP          	 	 	 dddeTdeGdLe,ddfde            Z_eVX                    dfg dgP          	 	 	 	 	 	 	 ddieeE ej?        djdkdl          f         dmeeBe9         dz   ej?        dn e)e          dop          f         dCeeBe9         dz   ej?        dddq          f         dreeH ej?        dsdt          f         deGdLe,dueeBe9         dz   ej?        dRdvdw          f         ddfdx            Z`eVX                    dydzgP          dd{            ZaeVX                    d|d}gP          	 	 dddeeBe9          ej=        d~          f         deGdLe,ddfd            ZbeVX                    ddgP          	 	 ddeSdeGdLe,ddfd            ZceVX                    dg dP          	 	 	 dddeeBe9          ej=        d          f         dHee9dz   ej?        d          f         deGdLe,ddf
d            ZdeVX                    dddgP          	 	 	 	 ddeSdCeCdeeE ej?        dd          f         deGdLe,ddfd            ZeeVX                    dKg dP          	 	 	 	 ddeSde+de*deGdLe,ddfd            Zf e2d          ZgeVh                    egd           egX                    d9d:d;ig d=          	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddePdeQd?e@dGeAdAe&dBe(dCeCdDe-dEe%dFe'dHeDdIeFdJeIdKeJdeGdLe,deKdeLddf&d            Zi e2d          ZjeVh                    ejd           ejX                    d9d:d;idg=          	 	 	 	 	 	 	 	 	 	 	 	 	 ddeOd?e>d@eRdeMdeNdAe&dBe(dCeCdDe-dEe%dFe'dGeAdHeDdJeIdeGdLe,ddf"d            ZkejX                    dfdgP          	 	 	 	 ddieeE ej?        djdkd          f         deGdLe,dueeBe9         dz   ej?        dRdvd          f         ddf
d            ZlejX                    d|dgP          	 	 ddeeBe9          ej=        d          f         deGdLe,ddfd            ZmejX                    ddgP          	 	 ddeUdeGdLe,ddfd            ZnejX                    ddgP          	 	 ddeUdeGdLe,ddfd            ZoejX                    ddgP          	 	 ddeUdeGdLe,ddfd            ZpejX                    dddgP          	 	 	 	 ddeUdCeCdeeE ej?        dd          f         deGdLe,ddfd            Zq e2d          Zrejh                    erd           erX                    d9d:d;iddg=          	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddeOdePdeQdeMdeNd?e@dGeAdAe&dBe(dCeCdDe-dEe%dFe'dHeDdJeIdeGdLe,deKdeLddf(d            ZsdeBe9         dz  de[e9e9f         dz  fdZtdeBeBe9eHz                    deBe9         de9fdZu ed          Zvdeev         dedeev         f         de[ddfdńZwdejx        jy        dedeev         f         deBe[         deev         fdȄZzdS )a  Contains commands to interact with jobs on the Hugging Face Hub.

Usage:
    # run a job
    hf jobs run <image> <command>

    # List running or completed jobs
    hf jobs ls [-a] [-f key=value]

    # Print logs from a job (non-blocking)
    hf jobs logs <job-id>

    # Stream logs from a job (blocking, like `docker logs -f`)
    hf jobs logs -f <job-id>

    # Stream resources usage stats and metrics from a job
    hf jobs stats <job-id>

    # Inspect detailed information about a job
    hf jobs inspect <job-id>

    # Cancel a running job
    hf jobs cancel <job-id>

    # Wait until one or more jobs finish
    hf jobs wait <job-id> [<job-id>...]

    # List available hardware options
    hf jobs hardware

    # Run a UV script
    hf jobs uv run <script>

    # Schedule a job
    hf jobs scheduled run <schedule> <image> <command>

    # List scheduled jobs
    hf jobs scheduled ls [-a] [-f key=value]

    # Inspect a scheduled job
    hf jobs scheduled inspect <scheduled_job_id>

    # Suspend a scheduled job
    hf jobs scheduled suspend <scheduled_job_id>

    # Resume a scheduled job
    hf jobs scheduled resume <scheduled_job_id>

    # Delete a scheduled job
    hf jobs scheduled delete <scheduled_job_id>

    N)CallableIterable)fnmatch)EmptyQueue)	AnnotatedAnyTypeVar)urlsplit)HfApiJobHardwareJobInfoJobStage)TERMINAL_JOB_STAGES)CLIError)logging)_format_size)format_durationparse_duration   )
EnvFileOptEnvOptSecretsFileOpt
SecretsOpt
SoftChoiceSshDryRunOptSshIdentityFileOptTokenOpt
VolumesOptexec_ssh
get_hf_apiparse_env_mapparse_volumestyper_factory)_dataclass_to_dictoutjob_id	namespacereturnc                 0   | st          d          |                     d          dk    rt          d|  d          d| vr| |fS |                     dd          \  }}|r|st          d|  d          |||k    rt          d| d| d	          ||fS )
a&  Extract namespace from job_id if provided in 'namespace/job_id' format.

    Allows users to pass job IDs copied from the Hub UI (e.g. 'username/job_id')
    instead of only bare job IDs. If the namespace is also provided explicitly via
    --namespace and conflicts, a CLIError is raised.
    zJob ID cannot be empty./r   z<Job ID must be in the form 'job_id' or 'namespace/job_id': 'z'.Nz(Conflicting namespace: got --namespace='z ' but job ID implies namespace='')r   countsplit)r'   r(   extracted_namespaceparsed_job_ids       \/var/www/app.qaans.com/backend/venv/lib/python3.11/site-packages/huggingface_hub/cli/jobs.py_parse_namespace_from_job_idr2   m   s      20111||C1`V\```aaa
&y  )/c1)=)=& bm b`V\```aaa.A!A!Axyxxbuxxx
 
 	
 ---    g?zThe Docker image to use.)helpz.Use a custom Docker image with `uv` installed.zcFlavor for the hardware. Run 'hf jobs hardware' to list available flavors. Defaults to `cpu-basic`.)r4   
click_typez-lz--labelz3Set labels. E.g. --label KEY=VALUE or --label LABELzVMax duration: int/float with s (seconds, default), m (minutes), h (hours) or d (days).z-dz--detachz3Run the Job in the background and print the Job ID.zVThe namespace where the job will be running. Defaults to the current user's namespace.z--exposezExpose a container port through the jobs proxy. Repeat the flag for multiple ports (e.g. `--expose 8000 --expose 8001`). Each exposed port is reachable on the public jobs domain; access requires an HF token with read access to the job's namespace.z--sshzMake the job's container reachable over SSH. Connect with `hf jobs ssh <job_id>`. Requires an SSH public key registered on https://huggingface.co/settings/keys.z--withz%Run with the given packages installedz-pz--pythonz5The Python interpreter to use for the run environmentz!Suspend (pause) the scheduled Jobz8Allow multiple instances of this Job to run concurrentlyzWOne of annually, yearly, monthly, weekly, daily, hourly, or a CRON schedule expression.z$UV script to run (local file or URL)zArguments for the scriptzThe command to run.zJob ID (or 'namespace/job_id')zJob IDs (or 'namespace/job_id')z2Scheduled Job ID (or 'namespace/scheduled_job_id')zRun and manage Jobs on the Hub.apijobc                    |                      |j        |j        j        d          D ]}t	          j        |           |                     |j        |j        j                  }|j        j        t          j
        k    rD|j        j        rd|j        j         nd}t          d|j         d|j        j         d|           t	          j        d|j         d	           d
S )zcStream Job logs until the Job ends, then fail the command if the Job did not complete successfully.T)r'   r(   followr'   r(   z:  zJob z finished with stage 'r,   z
 completedN)fetch_job_logsidownernamer&   textwait_for_jobstatusstager   	COMPLETEDmessager   )r6   r7   logfinalrE   s        r1   _stream_logs_and_check_statusrH   '  s    !!39>RV!WW  CFcinEEE|X///161EM-u|+---2\eh\\el>P\\SZ\\]]]H(EH((()))))r3   runignore_unknown_optionsT)z3hf jobs run python:3.12 python -c 'print("Hello!")'z1hf jobs run --detach python:3.12 python script.pyz3hf jobs run -e FOO=foo python:3.12 python script.pyz;hf jobs run --secrets HF_TOKEN python:3.12 python script.pyz^hf jobs run -v hf://org/my-model:/data -v hf://buckets/org/b:/mnt python:3.12 python script.py)context_settingsexamplesFimagecommandenvsecretslabelvolumeenv_filesecrets_fileflavortimeoutdetachexposesshtokenc                    t          ||          }t          ||          }t          |          }|                    | |||t          |          t	          |          ||	|||          }t          j        d|j        |j                   t          |j
        j        t                    r@d                    d |j
        j        D                       }t          j        d|            t          |j
        j        t                     r*t          j        d|j        j         d	|j         d
           |
r3|j        j         d	|j         }t          j        d| d| d           dS t'          ||           dS )z
Run a Job.rZ   )rM   rN   rO   rP   labelsvolumesrU   rV   rX   rY   r(   Job startedr=   url
c              3       K   | ]	}d | V  
dS z  N .0ra   s     r1   	<genexpr>zjobs_run.<locals>.<genexpr>c  (      FFcFFFFFFr3   SExposed ports are reachable at (requires an HF token with read access to the job):
Use `hf jobs ssh r+   &` to open an SSH session into the job.Use `hf jobs logs -f &` to stream logs, or `hf jobs inspect ` to check status.N)r"   r!   run_job_parse_labels_mapr#   r&   resultr=   ra   
isinstancerB   expose_urlslistjoinhintssh_urlstrr>   r?   rH   )rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r(   rZ   env_mapsecrets_mapr6   r7   urlsjob_refs                        r1   jobs_runr~   3  s   : C**G66K
5
!
!
!C
++ ''f%%   C J}SW5555#*($// pyyFFsz/EFFFFFnhlnnooo#*$c** fdSY^ddcfdddeee Y^..cf..sssX_sssttt!#s+++++r3   logs)zhf jobs logs <job_id>zhf jobs logs -f <job_id>zhf jobs logs --tail 20 <job_id>z#hf jobs logs -f --tail 100 <job_id>)rL   r9   z-fz--followzqFollow log output (stream until the job completes). Without this flag, only currently available logs are printed.tailz-nz--tailzvNumber of lines to show from the end of the logs. When combined with --follow, starts streaming from the last N lines.c                     t          | |          \  } }t          |          }|                    | |||          }|D ]}t          j        |           |r%|r| d|  n| }t          j        d| d           dS dS )a  Fetch the logs of a Job.

    By default, prints currently available logs and exits (non-blocking).
    Use --follow/-f to stream logs in real-time until the job completes.
    Use --tail/-n to limit the number of lines returned (server-side when supported).

    Note: following exits when the log stream ends, regardless of whether the Job
    succeeded or failed. Run `hf jobs inspect <job_id>` to check the final status.
    r\   )r'   r(   r9   r   r+   z#Stream ended. Run `hf jobs inspect z6` to check the final status (e.g. COMPLETED or ERROR).N)r2   r!   r<   r&   r@   rw   )	r'   r9   r   r(   rZ   r6   r   rF   r}   s	            r1   	jobs_logsr   n  s    N 5VYGGFI
5
!
!
!CVyVZ[[D   x-6BY)))))Fvwvvvwwwwwx xr3   job_propertiesfiltersc                     |D ]n\  }}}|                      |          }|
|dk    r$ dS t          |                                |                                          }|dk    r|r|dk    r|r dS odS )z5Check if scheduled job matches all specified filters.N!=F=T)getr   lower)r   r   keyop_strpatternvaluematchs          r1   _matches_filtersr     s     '  VW""3''=~~55w}}77cMM%MVt^^^554r3   nc                 T    d}d}t          |           D ]}t          ||           d S )Nz[1Az[2K)end)rangeprint)r   LINE_UP
LINE_CLEARis       r1   _clear_liner     sA    GJ1XX ' 'g:&&&&&' 'r3   metrics_streamtable_headersc              #     K   |D ]}| |d          dt          |d         dz  d          t          d|d         z  |d         z  d	           dt          |d                    d
t          |d                    dt          |d                    dt          |d                    dg}|d         rt          |d         t                    r|gdgt	          |          z  gt	          |d                   dz
  z  z   }t          |t          |d                             D ]s\  }}|d         |         }||d          dt          d|d         z  |d         z  d	           dt          |d                    d
t          |d                    dgz  }tn)|dgt	          |          t	          |          z
  z  z  }|g}d| |fV  d| g fV  d S )Ncpu_usage_pct%cpu_millicoresg     @@r   d   memory_used_bytesmemory_total_bytes   zB / Brx_bpszbps / tx_bpsbpsgpusr;   utilizationN/AFT)roundr   rs   dictlenzipsorted)r'   r   r   metricsrowrowsgpu_idgpus           r1   _get_jobs_stats_rowsr     sA      " " "'***'*+f4a88S7#677'BV:WWYZ[[^^^G$7899mm|GThLi?j?jmmmGH-..ZZl78CT6U6UZZZ
 6? 	z'&/4@@ 	5RD3s88O,GFO0D0Dq0HIID"4)@)@AA  Vfof-=),,,S3':#;;cBV>WWYZ[[^^^#C(;$<==mm<PSThPiCjCjmmm  E7c-003s88;<<C5DVT!!!!!

r3   statszhf jobs stats <job_id>job_idsc                 6   | 1g }| D ]*}t          |          \  }|                    |           +|} t          |                                          d         |  d                               D             } t          |           dk    rt          j        d           dS g dt          j	        
                    t          |                     5 }i | D ]"}|g}|d	 d
d         D             z  }|g|<   #t          j                    }fdD             }t          t          |                     fd| D             }	t          |t          |	          D ]\  }
}}|
r                    |d           n||<   t          j                    }||z
  t"          k    rMt%          dt          |          z              fdD             }t          t          |                     |}	 ddd           dS # 1 swxY w Y   dS )z7Fetch the resource usage statistics and metrics of JobsNr\   r?   c                 J    g | ] }|j         r|j         j        nd dv |j        !S )UNKNOWN)RUNNINGUPDATING)rB   rC   r=   rg   r7   s     r1   
<listcomp>zjobs_stats.<locals>.<listcomp>  sA     
 
 
$'J=
  IBYYY FYYYr3   r(   r   zNo running jobs found)	zJOB IDzCPU %zNUM CPUzMEM %z	MEM USAGEzNET I/Oz
GPU UTIL %z	GPU MEM %zGPU MEM USAGEc                 &    g | ]}d |v sd|v rdndS )r+   USAGEz-- / --z--re   )rg   headers     r1   r   zjobs_stats.<locals>.<listcomp>  s/    pppTZ#--7f3D3DII4pppr3   r   c                 *    g | ]}|         D ]}|S re   re   rg   r'   r   rows_per_job_ids      r1   r   zjobs_stats.<locals>.<listcomp>  s,    [[[f?SYCZ[[Cc[[[[r3   )headersc                 F    g | ]}|                     |           dS )r:   )r'   r   r   )fetch_job_metrics)rg   r'   r6   r(   r   s     r1   r   zjobs_stats.<locals>.<listcomp>  sO     
 
 
 	 !"%"7"7vQZ"7"["[!. 
 
 
r3   )kwargs_listr   c                 *    g | ]}|         D ]}|S re   re   r   s      r1   r   zjobs_stats.<locals>.<listcomp>  s,    cccf?[aKbccCcccccr3   )r2   appendr!   whoami	list_jobsr   r&   r@   multiprocessingpool
ThreadPooltimer   	_tabulateiflatmap_unorderedr   popSTATS_UPDATE_MIN_INTERVALr   )r   r(   rZ   
parsed_idsr'   r   r   last_update_time
total_rowsr   doner   nowr6   r   r   s    `           @@@r1   
jobs_statsr     s    
 	& 	&F <VY O OFIf%%%%
5
!
!
!CJJLL(	
 
}}y}99
 
 

 7||q()))
 
 
M 
		(	(W	6	6 '$<> 	, 	,F$*8Cpp^klmlnln^oppppC'*eOF##9;;[[[[[[[
 	i
M:::;;;
 
 
 
 
 
 "
 
 
 #5T;O]h"i"i"i 
	' 
	'D&$ /##FD1111*.')++C%%)BBBAJ/000ccccccc
i
MBBBCCC#& 
	')' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' 's   D!HHHzlist | ls | ps)z
hf jobs lszhf jobs ls -az&hf jobs ls --status running,schedulingz+hf jobs ls --label env=prod --label team=mlz%hf jobs ls --all --label hf-sandbox=1r   allz-az--allzWShow all Jobs (default shows running and scheduling). Cannot be combined with --status.rB   z--statuszfOnly show Jobs with the given status. Comma-separated or repeated, e.g. `--status running,scheduling`.)r5   r4   z{Only show Jobs with the given `key=value` label. Repeat to require several labels, e.g. `--label env=prod --label team=ml`.limitz--limitzCMaximum number of Jobs to display. Set to 0 to show all (no limit).filterz--filterz2(Deprecated) Use `--status` and `--label` instead.c                    t          |          }|rt          j        d| d           | r|rt          d          g }|pg D ]4}	|                    d |	                    d          D                        5|r|}
n'| rd}
n"t          j        j        t          j	        j        g}
i }|pg D ]6}d|vrt          d	| d
          |                    d          \  }}	|	||<   7|
                    ||
|pd          }d}|dk    rEt          t          j        ||dz                       }t          |          |k    rd}|d|         }nt          |          }g }|D ]5}t          |          }|                    d          pi }|                    d          pg }|                    dd          |d<   |                    d          pd|d<   |rd                    |          nd|d<   |                    d          r$|d         dd                             dd          nd|d<   |                    d          pi                     dd          |d<   t'          |                    d                     |d!<   |                    |           7t          j        |g d"d#           |rt          j        d$| d%           |st|s|rXd&                    g d' |D             d( |                                D                       }t          j        d)|            dS | st          j        d*           dS dS dS )+zList Jobs.

    Use `--status` to filter by status (see [`JobStage`] for possible values) and `--label` to filter by `key=value`
    labels. A Job must match every filter to be listed.
    r\   zIgnoring filter 'zc'. `-f`/`--filter` is deprecated and will be removed in a future release. Use `--status`/`--label`.z0`-a`/`--all` cannot be combined with `--status`.c              3   f   K   | ],}|                                 |                                 V  -d S N)strip)rg   parts     r1   rh   zjobs_ps.<locals>.<genexpr>^  s7      VVTVDJJLLVVVVVVr3   ,Nr   zInvalid label filter 'z"': must be in the form 'key=value')r(   rB   r]   Fr   r   T	durationsrN   r=   r;   r'   docker_imager   image/space 
created_at   TcreatedrB   rC   r   running_secsruntime)r'   r   rN   r   rB   r   r   id_keyzOutput truncated to z4 Jobs. Use `--limit 0` to show all (or `--limit N`)., c              3       K   | ]	}d | V  
dS )zstatus=Nre   )rg   ss     r1   rh   zjobs_ps.<locals>.<genexpr>  s(      77Q=Q==777777r3   c              3   ,   K   | ]\  }}d | d| V  dS )zlabel=r   Nre   )rg   kvs      r1   rh   zjobs_ps.<locals>.<genexpr>  s:      :g:gPTPQST;KA;K;K;K;K:g:g:g:g:g:gr3   zNo jobs matched filters: zHNo running jobs. Use `-a`/`--all` to include finished (and failed) jobs.)r!   r&   warningr   extendr.   r   r   r   
SCHEDULINGr   ru   	itertoolsislicer   r%   r   rv   replacer   r   tablerw   itemsr@   )r   rB   rQ   r   r(   rZ   r   r6   raw_statusesr   server_statusesr]   itemr   	jobs_iter	truncatedjobs	job_itemsr7   job_itemr   cmdfilters_msgs                          r1   jobs_psr    s   t 5
!
!
!C 
p p p p	
 	
 	

  Kv KIJJJ !L2 W WVVU[[5E5EVVVVVVV  N&	 N#+183F3LM  F  d??\D\\\]]]ZZ__
Us	/RXR`\`aaI IqyyI$Y	::;;t99uI<DI ')I 
# 
#%c**LL--3	ll9%%+%\\$33"*,,~">">"G%/2=chhsmmmOW||\hOiOith|4SbS9AA#sKKKot&ll844:??SS-immN.K.KLL""""ITTT   
  eccccddd a 	a6 	a))h77,777h:g:gX^XdXdXfXf:g:g:gh K H>>>????? 	aH_`````a a	a 	ar3   hardwarezhf jobs hardwarec                     t                      } |                                 }g }|D ]}d}|j        r)|j        j         d|j        j         d|j        j         d}|j        rd|j        dnd}|j        rd|j        dz  d	nd}|                    |j        |j	        |j
        |j        |j        |||d
           t          j        |           t          j        d           dS )z(List available hardware options for Jobsr;   zx  ()$z.4ffree<   z.2f)r?   zpretty namecpuramstorageacceleratorzcost/minz	cost/hourzLUse `hf jobs run --flavor <name> ...` to request a specific hardware flavor.N)r!   list_jobs_hardwarer  quantitymodelvramunit_cost_usdr   r?   pretty_namer  r  ephemeral_storager&   r   rw   )r6   hardware_listr   hwaccelerator_infocost_min	cost_hours          r1   jobs_hardwarer     s+    ,,C**,,ME 
 
> 	l"$."9kkR^=QkkUWUcUhkkk131AM-r'----v797GS3(2-3333V	!~vv//$&	 		
 	
 	
 	
 IeH[\\\\\r3   inspectzhf jobs inspect <job_id>z*Job IDs to inspect (or 'namespace/job_id')c                     g }| D ]*}t          |          \  }|                    |           +|} t          |          fd| D             }t          j        d |D                        dS )z0Display detailed information on one or more Jobsr\   c                 >    g | ]}                     |           S )r:   )inspect_job)rg   r'   r6   r(   s     r1   r   z jobs_inspect.<locals>.<listcomp>  s)    VVVFCOO6YO??VVVr3   c                 ,    g | ]}t          |          S re   r%   r   s     r1   r   z jobs_inspect.<locals>.<listcomp>  s!    7773!#&&777r3   Nr2   r   r!   r&   r   )r   r(   rZ   r   r'   r  r6   s    `    @r1   jobs_inspectr(    s     J " "8KK	&!!!!G
5
!
!
!CVVVVVgVVVDI77$77788888r3   cancelzhf jobs cancel <job_id>c                     t          | |          \  } }t          |          }|                    | |           t          j        d|            dS )zCancel a Jobr\   r:   zJob cancelledr=   N)r2   r!   
cancel_jobr&   rr   )r'   r(   rZ   r6   s       r1   jobs_cancelr-    sY     5VYGGFI
5
!
!
!CNN&IN666J6******r3   wait)zhf jobs wait <job_id>z"hf jobs wait <job_id_1> <job_id_2>z"hf jobs ls -q | xargs hf jobs waitz,Job IDs to wait for (or 'namespace/job_id').zZMax time to wait: int/float with s (seconds, default), m (minutes), h (hours) or d (days).c           
         g }t                      }| D ]?}t          ||          \  }}|                    |           |                    |           @t	          |          dk    rCt          dd                    d t          |t                    D                       z             |	                                }|t          |          nd}	t          |          }
t          j        dt	          |           d	          }	 |
                    ||	|
          }n7# t          $ r* |                    d           t          d| d          dw xY w|                    t	          |           d           t          j        d |D                        d |D             }|rOt          t	          |           dt	          |           dd                    d |D                       z             dS )a  Wait for one or more Jobs to reach a terminal state.

    Blocks until every Job has finished, then exits with code 0 if all Jobs completed
    successfully, or a non-zero exit code if any Job was canceled, errored or deleted.

    All Jobs must belong to the same namespace.
    r   z0All Job IDs must be in the same namespace, got: r   c              3   4   K   | ]}t          |          V  d S r   )ry   )rg   nss     r1   rh   zjobs_wait.<locals>.<genexpr>  s(      FFBBFFFFFFr3   )r   Nr\   zWaiting for z Job(s) to finish...)rV   r(   z
Timed out.zTimed out after z waiting for Job(s) to finish.z Job(s) finished.c                 f    g | ].}|j         t          |j        j                  |j        j        d /S ))r=   rC   rE   )r=   ry   rB   rC   rE   r   s     r1   r   zjobs_wait.<locals>.<listcomp>  s7    mmmadcfs3:+;'<'<I[\\mmmr3   c                 F    g | ]}|j         j        t          j        k    |S re   )rB   rC   r   rD   r   s     r1   r   zjobs_wait.<locals>.<listcomp>  s*    LLLcSZ%59K%K%Kc%K%K%Kr3   z of z' Job(s) did not complete successfully: c              3   D   K   | ]}|j          d |j        j         dV  dS )r  r  N)r=   rB   rC   r   s     r1   rh   zjobs_wait.<locals>.<genexpr>  s:      KKS3688SZ%5888KKKKKKr3   )setr2   r   addr   r   rv   r   ry   r   r   r!   r&   rB   rA   TimeoutErrorr   r   )r   rV   r(   rZ   r   
namespacesr'   	parsed_idparsed_namespacetimeout_secsr6   rB   r  faileds                 r1   	jobs_waitr=    s>   > JJ ) )&B69&U&U#	#)$$$'((((
:>iiFF&*E*E*EFFFFFG
 
 	
   I.5.A>'***tL
5
!
!
!CZLs:LLLMMF]
LIVV ] ] ]L!!!Q'QQQRRX\\] KK3t99///000ImmhlmmmnnnLLTLLLF 
6{{RRD		RRRiiKKFKKKKKL
 
 	

 
s   D 4Er]   z8hf jobs labels <job_id> --label env=prod --label team=mlzhf jobs labels <job_id> --clearclearz--clearzRemove all labels from the job.c                     |s|st          d          |r|rt          d          t          | |          \  } }t          |          pi }t          |          }|                    | ||          }t          j        d|j                   dS )z5Update labels on a Job. Replaces all existing labels.OPlease set at least one label with --label. To remove all labels, pass --clear.bCannot set labels and clear them at the same time. Please use either --label or --clear, not both.r\   )r'   r]   r(   Labels updatedr+  N)r   r2   rq   r!   update_job_labelsr&   rr   r=   )r'   rQ   r>  r(   rZ   r]   r6   r7   s           r1   jobs_labelsrD    s      j jhiii 
 
p
 
 	
 5VYGGFIu%%+F
5
!
!
!C


vf	

R
RCJCF++++++r3   )zhf jobs ssh <job_id>zhf jobs ssh <job_id> --dry-runz)hf jobs ssh <job_id> -i ~/.ssh/id_ed25519identity_filedry_runc                 J   t          | |          \  } }t          |          }|                    | |          }|j        j        t          d          |j        j        t          v r%t          d|j         d|j        j         d          |j        j        t          j
        k    rt          j        d|j         d	|j        j         d
          }|                    |j        |t          j
        g          }|j        j        t          j
        k    r:|                    d           t          d|j         d|j        j         d          |                    d           t          |j        j                  }t          |j         d|j         |j        ||           dS )a   SSH into a running Job.

    If the Job is not yet running, waits until it reaches the RUNNING state before
    connecting. Requires the Job to be started with SSH enabled (`hf jobs run --ssh ...`)
    and your SSH public key to be registered at https://huggingface.co/settings/keys.
    r\   r:   Nz[SSH is not enabled on this job. Start a job with SSH support using `hf jobs run --ssh ...`.zCannot SSH into job 'z%': job has already finished (stage: 'z').zWaiting for job 'z' to be running (stage: 'z')...)r'   r(   stageszJob finished.z1': job finished before reaching RUNNING (stage: 'zJob is running.@)portrE  rF  )r2   r!   r$  rB   rx   r   rC   r   r=   r   r   r&   rA   r   r   r    usernamehostnamerJ  )	r'   rE  rF  r(   rZ   r6   r7   rB   rx   s	            r1   jobs_sshrM  5  s   * 5VYGGFI
5
!
!
!C
//9/
=
=C
z!tuuu
z...qsvqq\_\f\lqqqrrr
z8+++hhhQTQ[Qahhhiicf	8K[J\]]:x///KK(((vvvadakaqvvv   	%&&&sz)**G00g.00\#	     r3   zFRun UV scripts (Python with inline dependencies) on HF infrastructure.uv)r?   )zhf jobs uv run my_script.pyz$hf jobs uv run --detach my_script.pyz1hf jobs uv run ml_training.py --flavor a10g-smallz+hf jobs uv run --with transformers train.pyzNhf jobs uv run -v hf://org/my-model:/data -v hf://buckets/org/b:/mnt script.pyscriptscript_argswith_pythonc                     t          ||          }t          ||	          }t          |          }|                    | |pg |||||t          |          t	          |          ||
|||          }t          j        d|j        |j                   t          |j
        j        t                    r@d                    d |j
        j        D                       }t          j        d|            t          |j
        j        t                     r*t          j        d|j        j         d	|j         d
           |r3|j        j         d	|j         }t          j        d| d| d           dS t'          ||           dS )8Run a UV script (local file or URL) on HF infrastructurer\   )rO  rP  dependenciesrR  rM   rO   rP   r]   r^   rU   rV   rX   rY   r(   r_   r`   rb   c              3       K   | ]	}d | V  
dS rd   re   rf   s     r1   rh   zjobs_uv_run.<locals>.<genexpr>  ri   r3   rj   rk   r+   rl   rm   rn   ro   N)r"   r!   
run_uv_jobrq   r#   r&   rr   r=   ra   rs   rB   rt   ru   rv   rw   rx   ry   r>   r?   rH   )rO  rP  rM   rU   rO   rP   rQ   rR   rS   rT   rV   rW   rX   rY   r(   rZ   rQ  rR  rz   r{   r6   r7   r|   r}   s                           r1   jobs_uv_runrX  g  s   @ C**G66K
5
!
!
!C
..%2 ''f%%   C  J}SW5555#*($// pyyFFsz/EFFFFFnhlnnooo#*$c** fdSY^ddcfdddeee Y^..cf..sssX_sssttt!#s+++++r3   z,Create and manage scheduled Jobs on the Hub.	scheduledz>hf jobs scheduled run "0 0 * * *" python:3.12 python script.pyschedulesuspendconcurrencyc                 N   t          ||	          }t          ||
          }t          |          }|                    ||| ||||t          |          t	          |          ||||          }t          j        d|j                   t          j        d|j         d           dS )zSchedule a Job.r\   )rM   rN   rZ  r[  r\  rO   rP   r]   r^   rU   rV   rX   r(   Scheduled Job createdr+  Use `hf jobs scheduled inspect ` to view its details.N)	r"   r!   create_scheduled_jobrq   r#   r&   rr   r=   rw   )rZ  rM   rN   r[  r\  rO   rP   rQ   rR   rS   rT   rU   rV   rX   r(   rZ   rz   r{   r6   scheduled_jobs                       r1   scheduled_runrc    s    0 C**G66K
5
!
!
!C,, ''f%% -  M J&=+;<<<<HW}/?WWWXXXXXr3   zhf jobs scheduled lsz1Show all scheduled Jobs (default hides suspended)z>Filter output based on conditions provided (format: key=value)c                    t          |          }|                    |          }g }|pg D ]}d|v rz|                    dd          \  }}	|                    d          rd}
|dd         }nd}
|                    |                                |
|	                                f           t          j        d	| d
           g }|D ]}|j        pd}| s|r|j	        j
        pd}|j	        j        pg }|rd                    |          nd}|j        |t          |          |d}t          ||          so|                    |           g }|D ]O}t!          |          }|                    d          pi }|                    d          pi }|                    d          }|                    d          pg }|                    d          pd|d<   |rd                    |          nd|d<   |r9|                    d          r$|d         dd                             dd          nd|d<   |                    d          r$|d         dd                             dd          nd|d<   |                    d          pd|d<   |                    |           Qt          j        |g dd           |s:|r:d                    d  |D                       }t          j        d!|            dS dS dS )"zList scheduled Jobsr\   r   r   r   !r   Nz Ignoring invalid filter format 'z'. Use key=value format.Fr   r   )r=   rM   r[  rN   job_specrB   last_jobrN   r   r   atr   r   last_runnext_job_run_atnext_runr[  )r=   rZ  r   rN   rj  rl  r[  r=   r   r   c              3   .   K   | ]\  }}}| | | V  d S r   re   )rg   r   or   s       r1   rh   zscheduled_ps.<locals>.<genexpr>&  s4      DDAq1aDDDDDDr3   z#No scheduled jobs matched filters: )r!   list_scheduled_jobsr.   endswithr   r   r&   r   r[  rg  r   rN   rv   r=   ry   r   r%   r   r   r   r@   )r   r(   rZ   r   r6   scheduled_jobsr   fr   r   opfiltered_jobsrb  r[  image_or_spacer  command_strpropsr   sjr   rg  status_dictrh  r  s                            r1   scheduled_psrz    s   , 5
!
!
!C,,y,AAN*,G\r X X!88aJC||C   #2#hNNCIIKKU[[]];<<<<KV1VVVWWWW M' 
, 
,'05 	w 	&/<E$,2'*5chhsmmm$'.SQX\\fqrrw// 	]++++ #%E  !"%%88J''-2hhx((.B??:..ll9%%+&ll>::Ce]+.9#((3---EYDLnQYQ]Q]^bQcQcn8D>#2#.66sC@@@inZEP__UfEgEgrK)*3B3/77SAAAmr 	Z ((9--6YTI___   
  FW FiiDDGDDDDDD{DDEEEEEF F F Fr3   zhf jobs scheduled inspect <id>scheduled_job_idsz>Scheduled Job IDs to inspect (or 'namespace/scheduled_job_id')c                     g }| D ]*}t          |          \  }|                    |           +|} t          |          fd| D             }t          j        d |D                        dS )z:Display detailed information on one or more scheduled Jobsr\   c                 >    g | ]}                     |           S )scheduled_job_idr(   )inspect_scheduled_job)rg   r  r6   r(   s     r1   r   z%scheduled_inspect.<locals>.<listcomp><  s=        	!!3Cy!YY  r3   c                 ,    g | ]}t          |          S re   r&  )rg   rb  s     r1   r   z%scheduled_inspect.<locals>.<listcomp>@  s!    UUU]!-00UUUr3   Nr'  )r{  r(   rZ   r   r'   rq  r6   s    `    @r1   scheduled_inspectr  *  s     J# " "8KK	&!!!!"
5
!
!
!C     1  N IUUnUUUVVVVVr3   deletezhf jobs scheduled delete <id>r  c                     t          | |          \  } }t          |          }|                    | |           t          j        d|            dS )zDelete a scheduled Job.r\   r~  zScheduled Job deletedr+  N)r2   r!   delete_scheduled_jobr&   rr   r  r(   rZ   r6   s       r1   scheduled_deleter  C  b     #??OQZ"["[i
5
!
!
!C.>)TTTJ&+;<<<<<<r3   zhf jobs scheduled suspend <id>c                     t          | |          \  } }t          |          }|                    | |           t          j        d|            t          j        d|  d           dS )z Suspend (pause) a scheduled Job.r\   r~  zScheduled Job suspendedr+  zUse `hf jobs scheduled resume z` to resume it.N)r2   r!   suspend_scheduled_jobr&   rr   rw   r  s       r1   scheduled_suspendr  P  s     #??OQZ"["[i
5
!
!
!C/?9UUUJ(-=>>>>HO.>OOOPPPPPr3   resumezhf jobs scheduled resume <id>c                     t          | |          \  } }t          |          }|                    | |           t          j        d|            dS )z!Resume (unpause) a scheduled Job.r\   r~  zScheduled Job resumedr+  N)r2   r!   resume_scheduled_jobr&   rr   r  s       r1   scheduled_resumer  ^  r  r3   z>hf jobs scheduled labels <id> --label env=prod --label team=mlz%hf jobs scheduled labels <id> --clearz)Remove all labels from the scheduled job.c                     |s|st          d          |r|rt          d          t          | |          \  } }t          |          pi }t          |          }|                    | ||          }t          j        d|j                   dS )z?Update labels on a scheduled Job. Replaces all existing labels.r@  rA  r\   )r  r]   r(   rB  r+  N)r   r2   rq   r!   update_scheduled_job_labelsr&   rr   r=   )r  rQ   r>  r(   rZ   r]   r6   rb  s           r1   scheduled_labelsr  k  s      j jhiii 
 
p
 
 	
 #??OQZ"["[iu%%+F
5
!
!
!C33)&I 4  M JM$4555555r3   z)Schedule UV scripts on HF infrastructure.z.hf jobs scheduled uv run "0 0 * * *" script.pyz<hf jobs scheduled uv run "0 0 * * *" script.py --with pandasc                 X   t          ||          }t          ||          }t          |          }|                    ||pg | |||||||t          |	          t	          |
          ||||          }t          j        d|j                   t          j        d|j         d           dS )rT  r\   )rO  rP  rZ  r[  r\  rU  rR  rM   rO   rP   r]   r^   rU   rV   rX   r(   r^  r+  r_  r`  N)	r"   r!   create_scheduled_uv_jobrq   r#   r&   rr   r=   rw   )rZ  rO  rP  r[  r\  rM   rU   rO   rP   rQ   rR   rS   rT   rV   rX   r(   rZ   rQ  rR  rz   r{   r6   r7   s                          r1   scheduled_uv_runr    s    < C**G66K
5
!
!
!C

%
%%2 ''f%%! &  C$ J&362222HMsvMMMNNNNNr3   c                 h    | sdS i }| D ](}d|v r|                     dd          n|df\  }}|||<   )|S )a  Parse label key-value pairs from CLI arguments.

    Args:
        labels: List of label strings in KEY=VALUE format. If KEY only, then VALUE is set to empty string.

    Returns:
        Dictionary mapping label keys to values, or None if no labels provided.
    Nr   r   r;   )r.   )r]   
labels_map	label_varr   r   s        r1   rq   rq     sa      t!#J    	03y0@0@Y__S!,,,yRTo
U
3r3   r   r   c                    d t          g | |R  D             }t          t          j                    j        t          |          dz            }t          |          t          |          z   |k    r|                    t          |                    }||xx         dz  cc<   t          |          t          |          z   |k    r.|t          |          z
  t          |          z
  ||         z   ||<   t          |          t          |          z   |k     dt          |          z  j        | }g }|	                     |j        |            |	                     |j        d |D                         | D ]9}d t          ||          D             }|	                     |j        |            :d
                    |          S )z
    Inspired by:

    - stackoverflow.com/a/8356620/593036
    - stackoverflow.com/questions/9535954/printing-lists-as-tabular-data
    c                 @    g | ]}t          d  |D                       S )c              3   N   K   | ] }t          t          |                    V  !d S r   r   ry   )rg   xs     r1   rh   z'_tabulate.<locals>.<listcomp>.<genexpr>  s.      //ac#a&&kk//////r3   )max)rg   cols     r1   r   z_tabulate.<locals>.<listcomp>  s/    OOOC#//3/////OOOr3      r   z{{:{}}} c                     g | ]}d |z  S )-re   )rg   ws     r1   r   z_tabulate.<locals>.<listcomp>  s    $A$A$AS1W$A$A$Ar3   c                     g | ]Q\  }}t          t          |                    |k    rt          |          d |dz
           dz   nt          |          RS )N   z...r  )rg   r  	col_widths      r1   r   z_tabulate.<locals>.<listcomp>  sf     
 
 
9 033q66{{Y/F/FCFF?Y]?#e++CPQFF
 
 
r3   rb   )r   r  shutilget_terminal_sizecolumnsr   sumindexformatr   rv   )	r   r   
col_widthsterminal_widthcol_to_minimize
row_formatlinesr   row_format_argss	            r1   r   r     s    PO3;N;Ng;N;N;NOOOJ133;S\\B=NOON
g,,Z
(>
9
9$**3z??;;?###)###w<<#j//)^;;*83z??*JSQX\\*Y\fgv\w*wJ'	 g,,Z
(>
9
9
 4*s7||+3Z@JE	LL""G,---	LL""$A$Aj$A$A$ABCCC : :
 
 #C 4 4
 
 
 	&Z&8999999Ur3   r   queuefunc.kwargsc                 F     |di |D ]}|                      |           d S )Nre   )put)r  r  r  rr   s       r1   _write_generator_to_queuer    s<    $....  		& r3   r   r   c             #      K   t                       fd|D             }	 	 	                     d          V  n?# t          $ r2 t          d |D                       r                                rY nY nw xY wZn# t
          $ r Y nw xY w	 d |D              dS # t          j        $ r Y dS w xY w# 	 d |D              w # t          j        $ r Y w w xY wxY w)a;  
    Takes a function that returns an iterable of items, and run it in parallel using threads to return the flattened iterable of items as they arrive.

    This is inspired by those three `map()` variants, and is the mix of all three:

    * `imap()`: like `map()` but returns an iterable instead of a list of results
    * `imap_unordered()`: like `imap()` but the output is sorted by time of arrival
    * `flatmap()`: like `map()` but given a function which returns a list, `flatmap()` returns the flattened list that is the concatenation of all the output lists
    c                 L    g | ] }                     t          |f          !S re   )apply_asyncr  )rg   r  r  r   r  s     r1   r   z&iflatmap_unordered.<locals>.<listcomp>  s2    rrr\bT%%&?%vAVWWrrrr3   T皙?rV   c              3   >   K   | ]}|                                 V  d S r   )readyrg   async_results     r1   rh   z%iflatmap_unordered.<locals>.<genexpr>  s.      NN|))++NNNNNNr3   c                 :    g | ]}|                     d           S )r  r  )r   r  s     r1   r   z&iflatmap_unordered.<locals>.<listcomp>  s)    NNN\d++NNNr3   N)r   r   r   r   emptyKeyboardInterruptr   r7  )r   r  r   async_resultsr  s   ``  @r1   r   r     sf      ggErrrrrrfqrrrM	iii------   NNNNNNN SXS^S^S`S` E	
    	NNNNNNNN+ 	 	 	DD		NNNNNNN+ 	 	 	D	s   B A  B  7A<7B ;A<<B  B6 
BB6 BB6 B   B32B36C8CCCCCC)NNNNNNNNFNFNN)FNNN)NNN)FNNr   NNN)r)   N)NN)NFNN)NNNNNNNNNNFNFNNNN)NNNNNNNNNNNNN)NNNNNNNNNNNNNNNNN){__doc__r   r   multiprocessing.poolr  r   collections.abcr   r   r   r  r   r   typingr   r	   r
   urllib.parser   typerhuggingface_hubr   r   r   r   huggingface_hub._jobs_apir   huggingface_hub.errorsr   huggingface_hub.utilsr   $huggingface_hub.utils._cache_managerr   huggingface_hub.utils._parsingr   r   
_cli_utilsr   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   _outputr%   r&   
get_logger__name__loggerry   tupler2   r   ArgumentImageArgOptionImageOpt	FlavorOptru   	LabelsOpt
TimeoutOptbool	DetachOptNamespaceOptint	ExposeOptSshEnabledOptWithOpt	PythonOpt
SuspendOptConcurrencyOptScheduleArg	ScriptArgScriptArgsArg
CommandArgJobIdArg	JobIdsArgScheduledJobIdArgjobs_clirH   rN   r~   r   r   r   r   r   r   r  r   r(  r-  r=  rD  rM  uv_app	add_typerrX  scheduled_apprc  rz  r  r  r  r  r  scheduled_uv_appr  rq   r   r   r  r   r   r   re   r3   r1   <module>r     sL  3 3j               . . . . . . . .               * * * * * * * * * * ! ! ! ! ! !  A A A A A A A A A A A A 9 9 9 9 9 9 + + + + + + ) ) ) ) ) ) = = = = = = J J J J J J J J                                 - , , , , , , , 
	H	%	%. .t .cSVY]S]oH^ . . . .8    EN'   $JEL=   $JELr:k**  	 IELB  	 $JELe  
 ELB  	 $JELe   IEL G  	 EL p   IEL4   $JELD  	 4KEL0  
 4KELG   ENf   EN3  	 IEN'   IEN"  
 EN-   IEN.  	 ENA    =?@@@	*u 	*7 	*t 	* 	* 	* 	* 
	.5    
 
 #'"-, -,-,-, 
-, 	-,
 -, -, -, !-, -, -, -, -, 
-, -, -,  
!-, -, -,
 
-,` 

     $ 	 	"'&x &x&x E	
 	
 	
	&x d
 J	
 	
 	
	&x$ %&x& '&x( 
)&x &x &x &xRT#s(^ d5cSVCW>X ]a    '3 '4 ' ' ' '!)$sCx.!9JNs)eD#tDsO4456   8 
'%=$>??"A' A'A'A' A' 
	A' A' A' @?A'H 
    	 	$ 	 	 	 	" 	Sxa xa	j	
 	
 	
	
xa S	D!z(++y	
 	
 	
	xa" S	D O	
 	
 	
	#xa2 V	
 	
 	
	3xa@ AxaB CxaD S	DE	
 	
 	
	ExaT 
Uxa xa xa	 	xav 
*(:';<<] ] ] =<]6 
)'A&BCC #9 9S	=	
 	
 	
	9 9 9 
9 9 9 DC9* 
(&?%@AA #	+ 	+	+	+ 	+ 
		+ 	+ 	+ BA	+ 

     ( 	"4
 4
S	?	
 	
 	
	4
 d
m	
 	
 	
	4
 4
 4
 
4
 4
 4
 4
n 
B)    ^c", ,,, T<5<	8YZZZZ[, 	,
 , 
, , , ,* 
	      )-!"# ##%# # 	#
 # 
# # # #L 
d	e	e	e   6  % % % 	.5    
 
 "&#'"%3, 3,3,3, 3, 	3,
 
3, 3, 3, 3, 3, !3, 3, 3, 3, 
3, 3,  !3," #3,$ %3,& 
'3, 3, 3,
 
3,l #QRRR   ={  3 3 3 	.5NO    "&#'"!'Y 'Y'Y'Y 'Y 	'Y
  'Y 
'Y 'Y 'Y 'Y 'Y !'Y 'Y 'Y 'Y 'Y  !'Y" 
#'Y 'Y 'Y 
'YT '3I2JKK 	" 	%KF KF	D	
 	
 	
	
KF KF KF S	DQ	
 	
 	
	KF& 
'KF KF KF LKKF\ y,L+MNN #W W S	Q	
 	
 	
	W W W 
W W W ONW0 x+J*KLL #	= 	='	=	= 	= 
		= 	= 	= ML	= y,L+MNN #
Q 
Q'
Q
Q 
Q 
	
Q 
Q 
Q ON
Q x+J*KLL #	= 	='	=	= 	= 
		= 	= 	= ML	= H/    hm"6 6'66 T<5<	8cdddde6 	6
 6 
6 6 6 6. !=&QRRR    (t  4 4 4 	.58F    "&"&#'"'-O -O-O-O -O 	-O
  -O -O -O 
-O -O -O -O -O !-O -O -O  !-O" #-O$ %-O& '-O( 
)-O -O -O -Ofd3i$. 4S>D3H    $DcCi) DI #    6 GCLLU1X Xc8A;>N5O Y] bf    



)
3#
$ d	
 a[     r3   