o
    A@i                 !   @   s9  d dl mZmZ 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mZ d dlmZmZmZmZ d dlZd dlZd dlZd dlmZ d dlZd dlZd dlZd dlmZ d dlm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 d dl#Z#d dl$Z$d dl%Z%d dl&m'Z' d dl(Z(d dl)Z*dZ+dZ,da-dZ.zd dl/Z/dZ.W n   Y zd dl0Z0W n	 e1y   Y nw zd dl2m3Z3 W n e1y   d dl4m3Z3 Y nw zej5Z5W n e6y   e7Z5Y nw ze8Z9W n	 e:y   Y nw e;dpdZ<e$j=e;dpe$j>dd de?de@eAdf fddZBdd ZCdd ZDdd ZEd e?de?fd!d"ZFd#d$ ZGd%e?deHe?eHe?e?f f fd&d'ZId(eHe?eHe?e?f f de?fd)d*ZJd+d, ZKd-ZLeG ZMzd dlNZNeNO eNP d.ZQW n   ejRSe;d/d0ejRSe;d/d1d.ZQY eQT D ]ZUejRSeQeU eL eQeU< ZRejRVeRseWeR qejRSeQd2 d3ZXed4d5ZYejRSeQd6 d7ZZejR[d8Z\ejRVeZsejRVe\re#]e\eZ e^ Z_i Z`G d9d: d:e^Zad;d< Zbd=d> Zcd?d@ ZddAe
e?e
f dBee? fdCdDZeG dEdF dFe^ZfG dGdH dHe^ZgddIeHe?e?f dB fdJdKZhddLdMZidi fdNdOZjdi fdPdQZkdi fdRdSZldTdU ZmddVdWZnddXdYZoddZd[ZpG d\d] d]e^ZqG d^d_ d_ejrZseqd`esdaZtdbe
de
fdcddZuddeejvdfe?dge
de?fdhdiZwdeejvde
fdjdkZxdle?de?fdmdnZydodpdqdrdsdtdudvdwdxdydz dfd{d|d}d~dddddddxddz dfdddxddz dfdddddfZzdodpdqdrdsdtdudvdwdxddz dfd{dd}d~ddddddxddz dfdddxddz dfdddddfZ{h dZ|dodpdtdd{ddddddddxddz dfdddxddz dfddddfZ}dod{ddddddxddz dfdddxddz dfdddddddfZ~doddddrddudvdwdxddz dfdddd|ddddddxddz dfddddddz dfdfZdZdZdZdZdoddd{ddddddddxddz dfdddddz dfdddddfZdoddddddddz dfddddddddddddddz dfdddddz dfdfZddddddz dfdddddz dfddfZdZdZddddddddz dfdddddz dfddddf	ZdZdZdZdeAfddZh dZddddddZdddddZdi i i fde?de
de
fddZddedededdfddZG dd  d eZdd Zdd ZetjefddeAdefdd	e?dd
deydddd Zetjefdde?dddeydddeejvfddZetjefdde?dddeydddeejvfddZdd Zdd Zd d! Zd"d# Zd$d% Zetjefd&d'eAdefd(d)edefd*g d+d,d-efd.e?e d/d0efd1e?e d2d0efd3ed4d d5efd6ed7d d5d8d9eyd:d
deejvfd;d<Zetjefd=d>eAdefd?d@eAdefdAdBdCedefdDdEdFdGdHdIdJeydKddeejvfdLdMZetjefdNdOe?defddPe?defdQdRdSe?ddTdUeydVddeejvfdWdXZ	 etjefdYdZe?defd[d\e?d]d^efd_d`e?defdadbe?defdcdde?ded^efdfdgdFdhefdidjdFdhefdkdldFdhefdmdndFdhefdodpdFdhefd*g d+d,d-efd.e?e d/d0efd1e?dqdrefd3ed4d d5efd6ed7d d5dsdteyduddeejvfdvdwZetjefddxe?defdydze?d{d^efd|d}e?defd~de?defdde?defdde?dd^ddeydd	deejvfddZdd Zdd Zdd Zetjefdde?defdde?defdde?dddeydddd Zetjefdde?defddeAdddeydddeejvfddZetjefdde?defdde?dddddd Zetjefdde?ddefddddFdhddeydddd ZdddZetjefdde?defddeAdefdddFddHefdde?defdÐde?defdŐdeAdefdǐdeAdɐd^efdʐdedefd̐de?defdΐdedefdАdedefdҐdedefdԐdeAdefd֐de?dؐd^dِdeydۃddܐd݄ Zetjefdΐdedߐd^efdАdedd^efdҐdedd^efdԐdeAdd^efddeAdd^efdÐde?defd֐de?dؐd^ddeydd
dd Zdd Zdd Zdd Zetjefd&deAdefdde?defdde?defddedd^efdde?defdde?defd de?defdde?defdde?defdde?defdd	dFdhefd
ddFdhefdddFdhefdde?defdddFdhefdddFdhefdddFdhefdejdefdde?defdejddefdddFdhefdd dFdhefd!d"edefd#d$d%eAd&efd'd(d)eAd&efd*d+eAdefd,d-e?defd.d/e?dfd0d1eyd2ddeejvfd3d4Zetjefd5d6e?defd7d8e?defd9d:e?defd;d<e?dd=d>eyd?dd@dA ZetjefdBdCe?ddDdEeydFddGdH ZetjefddIe?defdJdKe?ddLdMeydNddOdP ZdQdR Zetje dSdTeydUddVdW Zetjefd&dXeAdefdAdBdYdZed[efddd\e?dd]d^eyd_ddeejvfd`daZetjefd&dbeAdefdAdBdcdZed[efdddde?ddedfeydgddeejvfdhdiZetjefdjdkeAdefddlddmdneydoddeejvfdpdqZetjefd&dreAddsdtddudv Zetjefd&dweAddxdyddzd{ Zetjefd&d|eAdd}d~ddd ZetjefdjdeAdddeydddeejvfddZetjefd&deAdddeydddd Zetjefd&deAdddeydddd Zetjefdde?dddddd ZetjefddddddddeejvfddZetjefddeAdefdde?dddeydddd Zetjefd&deAdddeydddeejvfddZɐdd Zetjefd&deAdddeydddd ZetjefddeAddddddd Zetjddddd Zetjefdd`eAdefdde?ddÐdeydŃddƐdǄ Zetjefd&deAdefdɐde?defd*g d+d,d-efd.e?e d/d0efd1e?e d2d0efd3ed4d d5efd6ed7d d5dːdeyd̓d
dΐdτ Zetjefd&deAdefdѐdeAdӐd^efdԐdeAdd^d֐deyd؃ddِdڄ Zetjefd&deAdefdѐdeAdӐd^efdԐdeAdd^dېdeyd؃ddݐdބ Zetjefd5de?defdde?dddddd ZetjefdjdeAdefddeAddddeydddeejvfddZetjefdde?defddeAdddeydddeejvfddZetjefd&deAdefdde?dddddd ZՐdd Zdee? fddZאd ddddddZؐdd Zِd	d
 Zetjefdde?de׃ ddefdde?dg dddefdde?ddrefdQddddefdDdeddd0efddeAdՐdefdde?ddd5efdde?defd de?defdde?defdde?defdde?defdd	dFdhefd
ddFdhefdddFdhefdde?defdddFdhefdddFdhefdddFdhefdejdefdde?defdejddefdddFdhefdd dFdhefdde?dfd d!eyd"dd#d$ Zetjefd%d&eAdefdԐd'e?defd(d)e?defd*d+dFdhd,d-dd.d/ Zetjefd&d0eAdefd1d2edd3d4dd5d6 Z	 etjefd&d7eAdefd*g d+d,d-efd.e?e d/d0efd1e?e d2d0efd3ed4d d5efd6ed7d d5d8d9eyd:d	d;d< Zetjefd&d=eAdd>d?eyd@ddAdB Zetjefd&dCeAddDdEddFdG ZetjefdHdIe?ddIdJddKdL Zetjefd&dMeAddNdOddPdQ ZetjdRdSddTdU ZddWdXZdYdZ Zd[d\ Zd]d^ Zetjefd&d_eAdd`daeydbddcdd ZetjefddeeAdddfdgddhdi Zdjdk Zetjefd&dleAddmdneydoddpdq ZetjefddreAdddsdteyduddvdw Zdxdy Zh dzZetjefdAd{d|dd}d~deydegdgddd Zh dZetjefdAd{d|dd}ddeydegdgddd Zetjefdd;dddefdQddddddefdddddddefdddddddefdDddddddefdddFddHefddFddHefdeAdՐdrefddFddHefdeddd0efdde?ddd5efdAdd|dd}ddeydegdgddd Zh dZetjefdAd{d|dd}ddeydegdgddd ZetjefdddFddHefdeAdՐdrefdeddd0efdde?ddd5efdAdd|dd}ddeydddeejvfddZetjefdddFddHefdeAdՐdrefdeddd0efdde?ddd5efdAdd|dd}ddeydddeejvfddZetjefdddddÐddĐdń ZetjefdƐde?ddȐdeydʃddːd̄ Zetjefd&d&eAdd͐dΐddϐdЄ Zetjefd&d&eAddѐdҐddӐdԄ ZdՐdք Zetjefd&deAddؐdِddڐdۄ Zetjdܐdݐddސd߄ Zetjddddd Zdd Zdd Z etjddddd Zetjddddd Zetjddeydddd Zetjddeydddd Zetjddddd Zetjefd&deAddd ddd ZetjefdddFddHefdAd.de?defdd1de?defd	d
deAdddddd Zdd Zdd Z	etjefdAddFddHddddd Z
etjefdddFddHefdAd.de?defdd1de?defdddFddHefdd dFd!dHefd"d#dd$d%dd&d' Zetjefd&d(eAdd)d*dd+d, ZetjefdddFddHd-d*di i fd.d/Zetjd0d1dd2d3 Zetjd4d5eyd6ddeejvfd7d8Zetjd9d:eyd;ddeejvfd<d=ZetjefdddFd>dHd?d@ddAdB ZetjdCdDddEdF ZetjefdHdIe?ddGdHddIdJ ZetjdKdLddMdN ZetjefdddFdOdHdPdQeydRddSdT Zetjefdd;dUe?dVd^dWdXeydYddeejvfdZd[Zetjefdjd\eAdefd]d^eAdefd_d`eAdddadbeydcddeejvfdddeZetjefdfdge?defd1dhedefdidjdFddkdldmeydnddeejvfdodpZetjefd&dqeAdefdΐdedefdАdedefdҐdedefdԐdeAdefdǐdeAdefdʐdedefddre?defddseAdefd̐de?defdddFddHefddte?defdÐde?defdŐdeAddudveydwddxdy Zetjefd&dzeAdefdΐdedefdАdedefdҐdedefdԐdeAdefddeAdefdÐde?dd{d|eyd}d
d~d Zetjefdde?defdde?dddddd Zetjefd&deAdefddeAdefdde?defdde?defdde?defddejdefdde?dddeydd
dd Zetjefd&deAdefdde?defdJdKe?dddddd Zetjefdde?dge R ddeydddd Zetjefd&deAdefdde?dddddd Z dd Z!deejvdede
fddZ"etjefd&deAdddeydddd Z#dd Z$etjefd&deAdddeydddd Z%etjefd&deAdddddd Z&dd Z'etjefd&deAdefdddedefdAddedefdĐdŐdedefdDdǐdedefddɐdedefddːdedefd	d͐deAdefdd1de?defdАdѐdҐdefdӐdԐdeAdefd֐dאdeddِdeydۃddܐd݄ Z(etjefddeAddefdddedefdAddedefdĐdŐdedefdDdǐdedefddɐdedefddːdedefd	d͐deAdefdd1de?defdАdѐdҐdefdӐdԐdeAdefd֐dאdedddeydddd Z)etjefddeAddefdde?defdDddeAddddeydddd Z*etjddeydddeejvfddZ+etjefddeAdefdddded[efdd1de?dd^efdAdBddZeAd[ddddd Z,etjefd&deAdd dddd Z-etjefd&deAdefdddded[efdd1de?defdAdBddZdddeyd	dd
d Z.etjefddeAddefdddded[efdd1de?defdAdBddZdddeydddd Z/etjefd&deAdddddd Z0etjefd&deAdddddd Z1dd Z2etjefd&deAdefddedefdŐdedefdǐdedefdde?defdejd dd!d"eyd#d	d$d% Z3d&d' Z4d(d) Z5d*d+ Z6etjefd&d,eAdefd(d-edd.d/eyd0dd1d2 Z7etjefd&d3eAdefd4d5edefdѐd6edefd7d8e?d9d^d:d;eyd<dd=d> Z8etjefd?d@eAdefdddFddHdAdBddCdD Z9etjefdddFddHdEdBddFdG Z:etjefdHdIe?defdddFdJdHdKdLddMdN Z;etjefd&dOeAddPdQddRdS Z<dTdU Z=dVdW Z>dXdY Z?dZd[ Z@d\d] ZAdd^d_ZBd`da ZCdbdc ZDddedfZEetjefd]dge?defdhdFdidHefdjdFdkdHefdldFdmdHefdndoddefdpdqeAdɐd^efdrdFdsdHdtdueydvd
dwdx ZFdyZG	 zG dzd{ d{e/jHZIW n   Y d|d} ZJeKd~krzeJ  W dS  eLeMfy   Y dS w dS (      )unicode_literalsprint_functionN)DictListTupleOptional)datedatetime	timedeltatimezone)ThreadPoolExecutor)sleep)PIPE)redirect_stdoutredirect_stderr)StringIO)r   )Pathzhttps://pypi.orgFT)
quote_plusVAST_URLhttps://console.vast.aiLOGLEVELz%(levelname)s - %(message)s)levelformatversionreturn.c                 C   s<   |  d}t|dk rtd|  tjd tdd |D S )N.   zInvalid version format: filec                 s       | ]}t |V  qd S Nint).0part r%   B/home/ubuntu/transcripts/venv/lib/python3.10/site-packages/vast.py	<genexpr>W       z parse_version.<locals>.<genexpr>)splitlenprintsysstderrtuple)r   partsr%   r%   r&   parse_versionQ   s   
r0   c                  C   sT   zt jg ddddd} | j }|dr|dd  W S |W S  ty)   Y dS w )N)gitdescribez--tagsz
--abbrev=0T)capture_outputtextcheckv   0.0.0)
subprocessrunstdoutstrip
startswith	Exception)resulttagr%   r%   r&   get_git_versionZ   s   
rA   c                   C   s$   zt jdW S  ty   Y dS w )Nvastair8   )	importlibmetadatar   r>   r%   r%   r%   r&   get_pip_versioni   s
   rE   c                   C   s(   z	t jdd uW S  ty   Y dS w )NrB   F)rC   rD   r>   r%   r%   r%   r&   is_pip_packagep   s
   rF   stable_versionc                 C   s>   t  rdtv rtj dt d|  S tj d|  S d|  S )Nztest.pypi.orgz4 -m pip install --force-reinstall --no-cache-dir -i z	 vastai==z9 -m pip install --force-reinstall --no-cache-dir vastai==z5git fetch --all --tags --prune && git checkout tags/v)rF   PYPI_BASE_PATHr,   
executable)rG   r%   r%   r&   get_update_commandv   s
   
rJ   c                   C   s   t  rt S t S r    )rF   rE   rA   r%   r%   r%   r&   get_local_version   s   rK   project_namec                 C   sV   t d|  d }tj|ddid}|  |jdkr%td|  d|j | }|S )	Nz/pypi/z/jsonAcceptapplication/jsonheaders   zCould not get PyPi Project: z. Response: )rH   requestsgetraise_for_statusstatus_coder>   json)rL   urlresponseresponse_datar%   r%   r&   get_project_data   s   
rZ   project_datac                 C   s,   |  d}|stdt| d}t|S )NinfozCould not get PyPi Projectr   )rS   r>   str)r[   	info_dataversion_datar%   r%   r&   get_pypi_version   s
   
r`   c                  C   s   t d} t| }t }t|}t|}||krd S td| d| d }|dvr0td d S t|}td tj	|dddtj
tj
d	}td
 td d S )NrB   zUpdate available from  to z". Would you like to update [Y/n]: )y zlYou selected no. If you don't want to check for updates each time, update should_check_for_update in vast.pyzUpdating...T)shellr5   r4   r;   r-   zAUpdate completed successfully!
Attempt to run your command again!r   )rZ   r`   rK   r0   inputlowerr+   rJ   r9   r:   r   r,   exit)	pypi_datapypi_versionlocal_versionlocal_tuple
pypi_tupleuser_wants_updateupdate_command_r%   r%   r&   check_for_update   s6   	rp   rB   )configtempHOMEz.configz.cacherr   zgpu_names_cache.json   )hoursrq   vast_api_key~/.vast_api_keyc                   @      e Zd ZdS )ObjectN__name__
__module____qualname__r%   r%   r%   r&   ry          ry   c                 C   s   z8t | }t tdd }t | }tdddddd}t | }||  kr-|ks6n t|  d|W S  tyG   t|  dw )z^Validate that the input value is a valid number for seconds between yesterday and Jan 1, 2100.r7   daysi4  r   z! is not a valid second timestamp.z is not a valid integer.)r"   r	   nowr
   	timestampargparseArgumentTypeError
ValueError)valueval	yesterdaymin_secondsmax_datemax_secondsr%   r%   r&   validate_seconds   s   r   c                 C   sJ   t | tr	|  S t | trdd |  D S t | tr#dd | D S | S )Nc                 S      i | ]	\}}|t |qS r%   strip_stringsr#   kr6   r%   r%   r&   
<dictcomp>      z!strip_strings.<locals>.<dictcomp>c                 S      g | ]}t |qS r%   r   )r#   itemr%   r%   r&   
<listcomp>      z!strip_strings.<locals>.<listcomp>)
isinstancer]   r<   dictitemslistr   r%   r%   r&   r     s   


r   c                 C   sD   | d u rd S zt | W S  ty!   t| d}t|  Y S w )Nz%m/%d/%Y)floatr   r	   strptimetimemktime	timetuple)date_stringdate_objectr%   r%   r&   string_to_unix_epoch  s   
r   querydate_fieldsc                 C   sF   i }|   D ]\}}||v rdd |  D }|||< q|||< q|S )zZTakes in a query and date fields to correct and returns query with appropriate epoch datesc                 S   r   r%   )r   r   r%   r%   r&   r   !  r   z#fix_date_fields.<locals>.<dictcomp>r   )r   r   	new_queryfield	sub_querynew_sub_queryr%   r%   r&   fix_date_fields  s   

r   c                   @   s   e Zd Zdd ZdS )argumentc                 O   s   || _ || _d S r    )argskwargsselfr   r   r%   r%   r&   __init__*  s   
zargument.__init__N)r{   r|   r}   r   r%   r%   r%   r&   r   )  s    r   c                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )hidden_aliasesc                 C   s
   || _ d S r    )l)r   r   r%   r%   r&   r   1     
zhidden_aliases.__init__c                 C   s
   t | jS r    )iterr   r   r%   r%   r&   __iter__4  r   zhidden_aliases.__iter__c                 C      dS NFr%   r   r%   r%   r&   __bool__7     zhidden_aliases.__bool__c                 C   r   r   r%   r   r%   r%   r&   __nonzero__:  r   zhidden_aliases.__nonzero__c                 C   s   | j | d S r    )r   append)r   xr%   r%   r&   r   =     zhidden_aliases.appendN)r{   r|   r}   r   r   r   r   r   r%   r%   r%   r&   r   /  s    r   rP   c                 C   s  d}t d|jD ]v}tj| |||d}t }||}	tjrht	|	}
t
dd|
}t
d|}|d d}|d	  d
7  < g |d d dd d|dD }tdd|  d  td n||	}|jdkr|t| |d9 }q |S |S )N333333?r   )methodrW   rP   rV   z -H '[^']*'rc   z(?=\s+-\S+)'z
 c                 S   s   g | ]}|  qS r%   )rstripr#   r   r%   r%   r&   r   L  r   z http_request.<locals>.<listcomp>
z \
  i  g      ?)rangeretryrR   RequestSessionprepare_requestARGScurlcurlifyto_curlresubr)   joinr+   r<   r,   rg   sendrU   r   r   )verbr   req_urlrP   rV   tireqsessionprepas_curlsimpler/   pprr%   r%   r&   http_request@  s(   

*



r   c                 C      t d| |||S )NGETr   r   r   rP   rV   r%   r%   r&   http_getY  r   r   c                 C   r   )NPUTr   r   r%   r%   r&   http_put\  r   r   c                 C   r   )NPOSTr   r   r%   r%   r&   	http_post_  r   r   c                 C   r   )NDELETEr   r   r%   r%   r&   http_delb  r   r   c                 C   s8   t | d}t|W  d    S 1 sw   Y  d S )Nr   )openrV   load)	file_pathr   r%   r%   r&   load_permissions_from_filef  s   $r   c                 C      t tdddS )NT
machine_idinternalr   show__instancesr   prefixactionparserparsed_argsr%   r%   r&   complete_instance_machinej  r   r   c                 C   r   )NTidr   r   r   r%   r%   r&   complete_instancem  r   r   c                 C   s   dd t  ddD S )Nc                 S   r   r%   r]   )r#   mr%   r%   r&   r   q  r   z$complete_sshkeys.<locals>.<listcomp>.sshz*.pub)r   homejoinpathglobr   r%   r%   r&   complete_sshkeysp  s   r  c                   @   sN   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdddddZdddZ	dS )apwrapc                 O   s^   d|vrt |d< tj|i || _| jj| jd d | _g | _d| _g | _	t
 | _t
 | _d S )Nformatter_classfuncF)MyWideHelpFormatterr   ArgumentParserr   set_defaultsfail_with_helpsubparsers_subparser_objsadded_help_cmd
post_setupsetverbsobjsr   r%   r%   r&   r   t  s   zapwrap.__init__c                 O   s   | j tj tr    )r   
print_helpr,   r-   
SystemExitr   akwr%   r%   r&   r    s   zapwrap.fail_with_helpc              	   O   sP   | ds| jD ]}z
|j|i | W q tjy   Y qw | jj|i |S )Nparent_only)rS   r  add_argumentr   ArgumentErrorr   )r   r  r  r   r%   r%   r&   r    s   

zapwrap.add_argumentc                 O   s4   | j d u rd|d< d|d< | jj|i || _ | j S )Ncommandmetavarzcommand to run. one of:help)r  r   add_subparsersr  r%   r%   r&   
subparsers  s
   
zapwrap.subparsersc                 C   s@   |r| j | | j| |d | }|S | j| |}|S )N )r  addr  )r   r   objnamer%   r%   r&   get_name  s   zapwrap.get_namer%   Naliasesr  c                   s|   |j sd_ jtdd ddddfdd} fd	d
}tdkr<td tkr<d }g ||S |S )NT
subcommand?)defaultnargszprint this help messager  c                     s       d S r    )r  )r  r  r   r%   r&   r    s   zapwrap.command.<locals>.helpc                    s>  | j dd}|d\}}}||} rg ntg } D ]}|d\}}}||| qdvr;td<  j|f|d}t	| d| t	| d j
| D ]9}	|j|	ji |	j}
d }|	jd	  }|d
rzt}n|ds|drt}n|drt}|rt	|
d| q]|j| d | S )Nro   -z--r"  r  r'  mysignaturemysignature_helpr   machiner   ssh	completerr  )r{   replace	partitionr&  r   r   r
  r!  
add_parsersetattrr  r  r   r   rf   r=   r   endswithr   r  r  )r	  dashed_namer   ro   r$  r%  aliases_transformedr   spargtspmyCompleter
comparatorr(  	argumentshelp_r   r   r%   r&   inner  s8   

zapwrap.command.<locals>.innerr7   r   )r  r  r   r*   type)r   r(  r  rA  r   rC  r	  r%   r@  r&   r    s   &zapwrap.commandc                 O   s   |d u rt jdd  }g }|D ]}|r%|d | jv r%|d  d| 7  < q|| q| jj|g|R i |}| jD ]}|| q;|S )Nr7   r   r"  )r,   argvr  r   r   
parse_argsr  )r   rE  r  r  argv_r   r   r	  r%   r%   r&   rF    s   

zapwrap.parse_argsr    )
r{   r|   r}   r   r  r  r!  r&  r  rF  r%   r%   r%   r&   r  s  s    

5r  c                       s   e Zd Z fddZ  ZS )r
  c                    s   t  j|dddd d S )N   2   r7   )widthmax_help_positionindent_increment)superr   )r   prog	__class__r%   r&   r     s   zMyWideHelpFormatter.__init__)r{   r|   r}   r   __classcell__r%   r%   rO  r&   r
    s    r
  z7Use 'vast COMMAND --help' for more info about a command)epilogr  dc                    s"   dd   fdd|   D }|S )a	  Map over a dict and translate any null string values into ' '.
    Leave everything else as is. This is needed because you cannot add TableCell
    objects with only a null string or the client crashes.

    :param Dict d: dict of item values.
    :rtype Dict:
    c                 S   s   | dkrdS | S )Nrc   r"  r%   )sr%   r%   r&   translate_nulls  s   z9translate_null_strings_to_blanks.<locals>.translate_nullsc                    s   i | ]	\}}| |qS r%   r%   r   rU  r%   r&   r     r   z4translate_null_strings_to_blanks.<locals>.<dictcomp>r   )rS  new_dr%   rV  r&    translate_null_strings_to_blanks  s   
rX  r   subpath
query_argsc                 C   s   d}|du ri }| j dur| j |d< d}|r/	 ddd | D }| jd | d | }n| jd | }| jr\td t| td	 td
| jd | d  d t| td	 |S )aa  Creates the endpoint URL for a given combination of parameters.

    :param argparse.Namespace args: Namespace with many fields relevant to the endpoint.
    :param str subpath: added to end of URL to further specify endpoint.
    :param typing.Dict query_args: specifics such as API key and search parameters that complete the URL.
    :rtype str:
    Napi_key&c                 s   s:    | ]\}}d j |tt|tr|nt|dV  qdS )z{x}={y})r   rb   N)r   r   r   r]   rV   dumps)r#   r   rb   r%   r%   r&   r'     s    *
zapiurl.<locals>.<genexpr>z/api/v0r*  zquery args:rc   zbase: z
 + query: )r[  r   r   rW   explainr+   )r   rY  rZ  r?   
query_jsonr%   r%   r&   apiurl  s*   


r`  c                 C   s    i }| j durd| j  |d< |S )zCreates the headers for a given combination of parameters.

    :param argparse.Namespace args: Namespace with many fields relevant to the endpoint.
    :rtype Dict:
    NBearer Authorizationr[  )r   r?   r%   r%   r&   
apiheaders-  s   
rd  messagec                 C   s^   t jdd| t jd} dd t d| t jD }t|}t jdt| d d| t jd} |  S )	z
    Deindent a quoted string. Scans message and finds the smallest number of whitespace characters in any line and
    removes that many from the start of every line.

    :param str message: Message to deindent.
    :rtype str:
    z *$rc   )flagsc                 S   s   g | ]
}t |rt |qS r%   r*   r   r%   r%   r&   r   B      zdeindent.<locals>.<listcomp>z^ *(?=[^ ])z^ {,})r   r   	MULTILINEfindallminr]   r<   )re  indentsr  r%   r%   r&   deindent9  s
    rn  r   ID{}NT)cuda_max_goodCUDA{:0.1f}NT)num_gpusN{}xNF)gpu_nameModelrq  NT)pcie_bwPCIErt  NT)cpu_ghzr|  rt  NT)cpu_cores_effectivevCPUsrt  NTcpu_ramRAMrt  c                 C      | d S N  r%   r   r%   r%   r&   <lambda>R      r  )
disk_spaceDisk{:.0f}NT)	dph_total$/hr{:0.4f}NT)dlperfDLPrt  NT)dlperf_per_dphtotalzDLP/${:0.2f}NT)scorer  rt  NT)driver_versionz	NV Driverrq  NT)inet_upNet_uprt  NT)	inet_downNet_downrt  NTreliabilityRc                 C      | d S Nd   r%   r  r%   r%   r&   r  [  r  durationMax_Daysc                 C   r  N     @r%   r  r%   r%   r&   r  \  r  )r   mach_idrq  NT)verificationstatusrq  NT)host_idr  rq  NT)direct_port_countportsrq  NT)geolocationcountryrq  NTc                 C   r  r  r%   r  r%   r%   r&   r  n  r  )discounted_dph_totalr  r  NTc                 C   r  r  r%   r  r%   r%   r&   r  v  r  c                 C   r  r  r%   r  r%   r%   r&   r  w  r  >   r   disk_bwhas_avxr  r  pci_genrz  cpu_archr  gpu_archverified	cuda_versr  	static_ip
cluster_id
datacenterr  r   r  r  total_flopsstorage_costr  nw_disk_avg_bwnw_disk_max_bwnw_disk_min_bwubuntu_version)r  zDisk B/Wrt  NT)	disk_namez	Disk Namerq  NT)r  z
$/Gb/Monthz{:.2f}NTc                 C   r  r  r%   r  r%   r%   r&   r    r  c                 C   r  r  r%   r  r%   r%   r&   r    r  c                 C   r  r  r%   r  r%   r%   r&   r    r  c                 C   r  r  r%   r  r%   r%   r&   r    r  )r  r  rq  NT)r  zMin BW MiB/srq  NT)r  zMax BW MiB/srq  NT)r  zAvg BW MiB/srq  NT)r   Machinerq  NT)actual_statusStatusrq  NT)ru  Numrw  NF)gpu_utilzUtil. %rt  NTc                 C   r  r  r%   r  r%   r%   r&   r    r  )r  Storager  NT)ssh_hostzSSH Addrrq  NT)ssh_portzSSH Portrq  NT)
image_uuidImagerq  NT)r  zNet uprt  NT)r  zNet downrt  NTreliability2c                 C   r  r  r%   r  r%   r%   r&   r    r  )labelLabelrq  NTz
age(hours)r  c                 C   r  Ng      @r%   r  r%   r%   r&   r    r  )uptime_minszuptime(mins)r  NT)ro  subnetSubnetrq  NT)
node_countNodesrq  NT)
manager_idz
Manager IDrq  NT)
manager_ipz
Manager IPrq  NT)machine_idszMachine ID'srq  NT))network_disk_idzNetwork Disk IDrq  NT)
free_spacezFree Space (GB)rq  NT)total_spacezTotal Space (GB)rq  NT)r   
Machine IDrq  NT)mount_pointzMount Pointrq  NT))
overlay_idz
Overlay IDrq  NT)r%  Namerq  NTr  r  z
Cluster IDrq  NT)instance_count	Instancesrq  NT)	instanceszInstance IDsrq  NTr  )r  r  rq  NT)r  r  rq  NTc                 C   r  r  r%   r  r%   r%   r&   r    r  c                 C   r  r  r%   r  r%   r%   r&   r    r  )r  Verificationrq  NT)r  r  rq  NT)ru  z#gpusrq  NT)rx  rx  rq  NT)r  diskrq  NThostnamerq  c                 C   s   | d d S )N   r%   r  r%   r%   r&   r        )r  driverrq  NT)r  reliabr  NT)r  verirq  NT)public_ipaddriprq  NT)r  geolocrq  NT)num_reportsreportsrq  NT)listed_gpu_costzgpuD_$/hr  NT)min_bid_pricezgpuI$/hr  NT)credit_discount_maxrdiscr  NTlisted_inet_up_costz	netu_$/TBc                 C   r  Ni   r%   r  r%   r%   r&   r    r  listed_inet_down_costz	netd_$/TBc                 C   r  r  r%   r  r%   r%   r&   r     r  )gpu_occupancyoccuprq  NTr  
start_timezStart (Date/Time)c                 C      t | dS Nz%Y-%m-%d/%H:%Mr	   fromtimestampstrftimer  r%   r%   r&   r  '      end_timezEnd (Date/Time)c                 C   r  r  r  r  r%   r%   r&   r  (  r  )duration_hourszDuration (Hrs)rq  NT)maintenance_categoryCategoryrq  NT))r  r  rq  NT)
first_seenr  rq  NT)first_locationr  rq  NT))
ip_addressr   rq  NT)
api_key_idr  rq  NT)
created_atr  rq  NT)	api_router  rq  NT)r   r   rq  NT)r   zScheduled Job IDrq  NT)instance_idzInstance IDrq  NT)api_endpointzAPI Endpointrq  NTzStart (Date/Time in UTC)c                 C   r  r  r  r  r%   r%   r&   r  A  r  zEnd (Date/Time in UTC)c                 C   r  r  r  r  r%   r%   r&   r  B  r  )day_of_the_weekzDay of the Weekrq  NT)hour_of_the_dayzHour of the Day in UTCrq  NT)min_of_the_hourzMinute of the Hourrq  NT)	frequency	Frequencyrq  NT))descriptionDescriptionrq  NT)quantityQuantityrq  NT)rateRaterq  NT)amountAmountrq  NT)r   	Timestamprt  NT)rD  Typerq  NT))balanceBalancerq  NT)balance_thresholdz	Bal. Thldrq  NT)balance_threshold_enabledzBal. Thld Enabledrq  NT)billaddress_cityCityrq  NT)billaddress_countryCountryrq  NT)billaddress_line1zAddr Line 1rq  NT)billaddress_line2zAddr line 2rq  NT)billaddress_zipZiprq  NT)billed_expectedzBilled Expectedrq  NT)billed_verifiedz
Billed Vfyrq  NT)billing_creditonlyzBilling Creditonlyrq  NT)can_payzCan Payrq  NT)creditCreditr  NT)emailEmailrq  NT)email_verifiedz	Email Vfyrq  NT)fullnamez	Full Namerq  NT)got_signup_creditzGot Signup Creditrq  NT)has_billingzHas Billingrq  NT)
has_payoutz
Has Payoutrq  NT)r   Idrq  NT)last4Last4rq  NT)paid_expectedzPaid Expectedrq  NT)paid_verifiedzPaid Vfyrq  NT)password_resettablezPwd Resettablerq  NT)paypal_emailzPaypal Emailrq  NT)ssh_keyzSsh Keyrq  NT)userUserrq  NT)usernameUsernamerq  NT)ro  )r%  NAMErq  NT)
cloud_typez
Cloud Typerq  NTc                 C   s   |  d}| d}dS )a#  
    Accepts two version strings and decides whether a > b, a == b, or a < b.
    This is meant as a sort function to be used for the driver versions in which only
    the == operator currently works correctly. Not quite finished...

    :param str a:
    :param str b:
    :return int:
    r   r   )r)   )r  ba_partsb_partsr%   r%   r&   version_string_sortx  s   


r?  >5   r   r  rentedr|  r  r  gpu_ramr  r  r  min_bidr  rz  r  r  externalr  gpu_fracrx  ru  rentabler  	bw_nvlink	cpu_coresr  r  	mobo_namer  r  r  r  
gpu_mem_bwr   compute_capr  r  r  vms_enabledgpu_max_tempinet_up_costr  r  rr  gpu_max_powergpu_total_ramr  inet_down_costr  r  flops_per_dphtotalgpu_display_activer}  r  rr  rR  r  r  rQ  )r  display_active
dlperf_usddph	flops_usdr  r  )r  rA  rO  r  	query_strresc                 C   s  | du r|S |du ri }t | tkrd| } |  } d}t|| }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dddddddddd}ddd |D }|| krytdt| d t|  |D ]\}	}
}}}|d}||	i }|
 }
|	|
}|	|v r|
|	 ||	 }	|	dkrd|v rt|}|	|vrtd|	tjd  |std!t|
d" |d#v rd$d% |d&D }|std't|	|
|f |	std(t|	|
|f |d)v r|dkrtd*|	|v r	||	= |	|v r||	= q{t|tr$|d+d}|d,}nt|tr8d-d% |D }d.d% |D }|	|v rJt|||	  }|||< n1|d/ksT|d0krYd1||< n"|d2ksc|d3krhd4||< n|d5ksr|d6krwd||< n|||< |	|vr|||	< q{||	 | q{|S )7a  
    Basically takes a query string (like the ones in the examples of commands for the search__offers function) and
    processes it into a dict of URL parameters to be sent to the server.

    :param str query_str:
    :param Dict res:
    :return Dict:
    Nr"  zn([a-zA-Z0-9_]+)( *[=><!]+| +(?:[lg]te?|nin|neq|eq|not ?eq|not ?in|in) )?( *)(\[[^\]]+\]|\"[^\"]+\"|[^ ]+)?( *)z>=gte>gtz<=lte<ltz!=neqz==eq=noteqznot eqnotinznot inin)ninrd  rc   c                 s   s    | ]}d  |V  qdS )rc   N)r   r   r%   r%   r&   r'     s    zparse_query.<locals>.<genexpr>z5Unconsumed text. Did you forget to quote your query? z != z,[]r  r   z?Warning: Unrecognized field: {}, see list of recognized fields.r   z6Unknown operator. Did you forget to quote your query? u)rd  rc  c                 S   s   g | ]
}|  r|  qS r%   r<   r   r%   r%   r&   r     rh  zparse_query.<locals>.<listcomp>,z;Value cannot be blank. Did you forget to quote your query? z;Field cannot be blank. Did you forget to quote your query? )r*  *anyz&Wildcard only makes sense with equals.ro   "c                 S   s   g | ]}| d dqS )ro   r"  r4  r   r%   r%   r&   r   1      c                 S   s   g | ]}| d qS )rk  rg  r   r%   r%   r&   r   2      trueTrueTfalseFalseFNonenull)rD  r   r   r<   r   rk  r   repr
setdefaultrS   popnumeric_versionr+   r   r,   r-   r)   r   r]   r4  r   update)rW  rX  fieldsfield_aliasfield_multiplierpatternoptsop_namesjoinedr   opro   r   r6   op_namer%   r%   r&   parse_query  s   	
	














r  rowsrz  replace_spacesc                 C   s(  dd |D }|g}dd |D }| D ]K}g }| | |D ]?\}}	}
}}|p*dd }||d}|du r8d}n	||}|
|}|rI|dd	}t|}tt||| ||< | | qq|D ]0}g }t|||D ]\}}}|\}}}}}|r||}n||}| | qkt	d

| qadS )a  Basically takes a set of field names and rows containing the corresponding data and prints a nice tidy table
    of it.

    :param list rows: Each row is a dict with keys corresponding to the field names (first element) in the fields tuple.

    :param Tuple fields: 5-tuple describing a field. First element is field name, second is human readable version, third is format string, fourth is a lambda function run on the data in that field, fifth is a bool determining text justification. True = left justify, False = right justify. Here is an example showing the tuples in action.

    :rtype None:

    Example of 5-tuple: ("cpu_ram", "RAM", "{:0.1f}", lambda x: x / 1000, False)
    c                 S   s   g | ]	\}}}}}|qS r%   r%   )r#   ro   r%  r%   r%   r&   r   V  r   z!display_table.<locals>.<listcomp>c                 S   r   r%   rg  r   r%   r%   r&   r   X  r   c                 S   s   | S r    r%   r  r%   r%   r&   r  ]  s    zdisplay_table.<locals>.<lambda>Nr.  r"  ro   z  )r   rS   r   r4  r*   maxzipljustrjustr+   r   )r  rz  r  headerout_rowslengthsinstancerowkeyr%  fmtconvro   r   rT  idxoutr   fr  r%   r%   r&   display_tableJ  s:   


r  c                   @   rx   )VRLExceptionNrz   r%   r%   r%   r&   r  u  r~   r  c                 C   s   d}| }d| v r|  dd}t|dkr|\}}ntdzt|}d}W n   Y td}|dkrB||du rBtd| d||fS )	z
    Breaks up a vast-style url in the form instance_id:path and does
    some basic sanity type-checking.

    :param url_str:
    :return:
    N:   z$Invalid VRL (Vast resource locator)./z^(/)?([^/ ]+(/)?)+$zPath component: z' of VRL is not a valid Unix style path.)r)   r*   r  r"   r   compilematch)url_strr  path	url_partsvalid_unix_path_regexr%   r%   r&   parse_vast_urlx  s    	

r  c                 C   sx   | }t j| r t| }| }W d    n1 sw   Y  d|v r*ttd| ds:ttd	||S )NzPRIVATE KEYu{  
        🐴 Woah, hold on there, partner!

        That's a *private* SSH key.  You need to give the *public* 
        one. It usually starts with 'ssh-rsa', is on a single line, 
        has around 200 or so "base64" characters and ends with 
        some-user@some-where. "Generate public ssh key" would be 
        a good search term if you don't know how to do this.
      r2  a  
        Are you sure that's an SSH public key?

        Usually it starts with the stanza 'ssh-(keytype)' 
        where the keytype can be things such as rsa, ed25519-sk, 
        or dsa. What you passed me was:

        {}

        And welp, that just don't look right.
      )
osr  existsr   readr   rn  rf   r=   r   )argstrr5  r  r%   r%   r&   get_ssh_key  s   



r  r  zid of instance to attach tor  rD  r5  zssh key to attach to instancez!vastai attach instance_id ssh_keyzaAttach an ssh key to an instance. This will allow you to connect to the instance with the ssh keya6  
        Attach an ssh key to an instance. This will allow you to connect to the instance with the ssh key.

        Examples:
         vast attach 12371 ssh-rsa AAAAB3NzaC1yc2EAAA...
         vast attach 12371 ssh-rsa $(cat ~/.ssh/id_rsa)

        The first example attaches the ssh key to instance 12371
    )usager  rR  c                 C   sN   t | j}t| dj| jd}d|i}t| |t|d}|  t|	  d S )Nz/instances/{id}/ssh/r   r5  rP   rV   )
r  r5  r`  r   r  r   rP   rT   r+   rV   )r   r5  rW   req_jsonr   r%   r%   r&   attach__ssh  s   
r  dstz-instance_id:/path to target of copy operationzvastai cancel copy DSTz5Cancel a remote copy in progress, specified by DST ida  
        Use this command to cancel any/all current remote copy operations copying to a specific named instance, given by DST.

        Examples:
         vast cancel copy 12371

        The first example cancels all copy operations currently copying data into instance 12371

    c                 C      t | d}| j}|du rtd dS td| d d|d}t| |t|d}|  |jd	krF| }|d
 r>td dS t|d  dS t|j tdj	di t
  dS )zw
    Cancel a remote copy in progress, specified by DST id"

    @param dst: ID of copy instance Target to cancel.
    /commands/copy_direct/Ninvalid argumentscanceling remote copies to r"  me	client_iddst_idr  rQ   success\Remote copy canceled - check instance status bar for progress updates (~30 seconds delayed).msg!failed with error {r.status_code}r%   r`  r  r+   r   rP   rT   rU   rV   r4   r   localsr   rW   r  r  r   rjr%   r%   r&   cancel__copy      



r  z-instance_id:/path to target of sync operationzvastai cancel sync DSTa  
        Use this command to cancel any/all current remote cloud sync operations copying to a specific named instance, given by DST.

        Examples:
         vast cancel sync 12371

        The first example cancels all copy operations currently copying data into instance 12371

    c                 C   r  )z
    Cancel a remote cloud sync in progress, specified by DST id"

    @param dst: ID of cloud sync instance Target to cancel.
    /commands/rclone/Nr  r  r"  r  r  r  rQ   r  r  r  r  r%   r  r  r%   r%   r&   cancel__sync  r  r  c                   C   s   t tjdS )N%Y-%m-%d)r	   r   r   utcr  r%   r%   r%   r&   default_start_date(  s   r  c                   C   s   t tjtdd dS )N   r   r  )r	   r   r   r  r
   r  r%   r%   r%   r&   default_end_date+  s   r  c                 C   s   t j| tjd}|dS )N)tzr  )r	   r  r   r  r  )unix_timestamputc_datetimer%   r%   r&   convert_timestamp_to_date.  s   
r  c                 C   \   t |  }|dkrdS zt|}d|  krdkr|W S  W n	 ty(   Y nw td)zo
    Accepts an integer string 0-6 or '*' to indicate 'Every day'.
    Returns 0-6 as int, or None if '*'.
    ri  Nr      z0Day must be 0-6 (0=Sunday) or '*' for every day.r]   r<   r"   r   r   r   )r   r   dayr%   r%   r&   parse_day_cron_style2     
r  c                 C   r  )zr
    Accepts an integer string 0-23 or '*' to indicate 'Every hour'.
    Returns 0-23 as int, or None if '*'.
    ri  Nr      z(Hour must be 0-23 or '*' for every hour.r  )r   r   hourr%   r%   r&   parse_hour_cron_styleB  r  r  r   z!id of instance type to change bidz--pricezper machine bid price in $/hourz
--schedule)HOURLYDAILYWEEKLYz|try to schedule a command to run hourly, daily, or monthly. Valid values are HOURLY, DAILY, WEEKLY  For ex. --schedule DAILY)choicesr  z--start_datezTStart date/time in format 'YYYY-MM-DD HH:MM:SS PM' (UTC). Default is now. (optional))rD  r+  r  z
--end_datez^End date/time in format 'YYYY-MM-DD HH:MM:SS PM' (UTC). Default is 7 days from now. (optional)z--dayzmDay of week you want scheduled job to run on (0-6, where 0=Sunday) or "*". Default will be 0. For ex. --day 0)rD  r  r+  z--hourzfHour of day you want scheduled job to run on (0-23) or "*" (UTC). Default will be 0. For ex. --hour 16z$vastai change bid id [--price PRICE]z6Change the bid price for a spot/interruptible instancez
        Change the current bid price of instance id to PRICE.
        If PRICE is not specified, then a winning bid price is used as the default.
    c                 C   s   t | dj| jd}d| jd}| jrtd t| | jrBt| j| j	| j d}dj| jd}| j|d< t
| |||d	| jd
 dS t| |t|d}|  td|  dS )zAlter the bid with id contained in args.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype int:
    z/instances/bid_price/{id}/r  r  r  pricerequest json: z
change bidz!/api/v0/instances/bid_price/{id}/r  r   r  Nr  zPer gpu bid price changed)r`  r   r   r  r^  r+   schedulevalidate_frequency_valuesr  r  add_scheduled_jobr   rP   rT   rV   )r   rW   	json_blobcli_commandr  r   r%   r%   r&   change__bidR  s   
r  sourcez"id of volume contract being cloneddestz,id of volume offer volume is being copied toz-sz--sizezSize of new volume contract, in GB. Must be greater than or equal to the source volume, and less than or equal to the destination offer.z-dz--disable_compression
store_truez+Do not compress volume data before copying.r   r  z2vastai copy volume <source_id> <dest_id> [options]zClone an existing volumez
        Create a new volume with the given offer, by copying the existing volume. 
        Size defaults to the size of the existing volume, but can be increased if there is available space.
    c                 C   s   | j | jd}| jr| j|d< | jrd|d< t| d}| jr&td t| t| |t|d}|	  | j
r7|S td|  d S )	N)r  r  sizeTdisable_compressionz/volumes/copy/r  r  Created. {})r  r  r  r  r`  r^  r+   r   rP   rT   rawr   rV   r   r  rW   r   r%   r%   r&   clone__volume|  s    

r  srcz>Source location for copy operation (supports multiple formats)z>Target location for copy operation (supports multiple formats)z-iz
--identityzLocation of ssh private keyzvastai copy SRC DSTz/Copy directories between instances and/or locala  
        Copies a directory from a source location to a target location. Each of source and destination
        directories can be either local or remote, subject to appropriate read and write
        permissions required to carry out the action.

        Supported location formats:
        - [instance_id:]path               (legacy format, still supported)
        - C.instance_id:path              (container copy format)
        - cloud_service:path              (cloud service format)
        - cloud_service.cloud_service_id:path  (cloud service with ID)
        - local:path                      (explicit local path)

        You should not copy to /root or / as a destination directory, as this can mess up the permissions on your instance ssh folder, breaking future copy operations (as they use ssh authentication)
        You can see more information about constraints here: https://vast.ai/docs/gpu-instances/data-movement#constraints

        Examples:
         vast copy 6003036:/workspace/ 6003038:/workspace/
         vast copy C.11824:/data/test local:data/test
         vast copy local:data/test C.11824:/data/test
         vast copy drive:/folder/file.txt C.6003036:/workspace/
         vast copy s3.101:/data/ C.6003036:/workspace/

        The first example copy syncs all files from the absolute directory '/workspace' on instance 6003036 to the directory '/workspace' on instance 6003038.
        The second example copy syncs files from container 11824 to the local machine using structured syntax.
        The third example copy syncs files from local to container 11824 using structured syntax.
        The fourth example copy syncs files from Google Drive to an instance.
        The fifth example copy syncs files from S3 bucket with id 101 to an instance.
    c                 C   s  t | j\}}t | j\}}|du r|du r	 td|r!t|d nd | d|r.t|d nd |  d||||d}| jrHtd t| |du sP|du rVt| d	}nt| d
}t| |t|d}|	  |j
dkr7| }|d r
|du s|dks|du s|dkr
td}	d}
| jdur| jn|	 d}|du s|dkr|d }
|d }d| d|
 d| d| d| d| }t| tj|dd}dS |du s|dkrtjd| dd}|d }
|d }d| d|
 d| d| d| d| }t| tj|dd}dS dS |d rtd dS |d  d!kr"td" dS |d  d#kr/td" dS t|d   dS t|j td$jd%i t  dS )&
    Transfer data from one instance to another.

    @param src: Location of data object to be copied.
    @param dst: Target to copy object to.
    Ncopying r  rc   r"  r  )r  src_idr  src_pathdst_pathr  z/commands/rsync/r  r  rQ   r  localz
echo $HOMEz/.ssh/id_rsadst_portdst_addrz8sudo rsync -arz -v --progress --rsh=ssh -e 'sudo ssh -i z -p z -o StrictHostKeyChecking=no' z vastai_kaalia@z::r  T)rd   z	mkdir -p src_portsrc_addrz, -o StrictHostKeyChecking=no' vastai_kaalia@zgRemote to Remote copy initiated - check instance status bar for progress updates (~30 seconds delayed).r  zsrc_path not supported VMs.zScopy between VM instances does not currently support subpaths (only full disk copy)zdst_path not supported for VMs.r  r%   )r  r  r  r+   r]   r^  r`  r   rP   rT   rU   rV   r9   	getoutputidentityr:   r4   r   r  )r   r  r  r  r  r  rW   r   r  homedirremote_portr  remote_addrcmdr?   r%   r%   r&   copy  s`   +<
,
((
	
r  z--srcz path to source of object to copyz--dstz path to target of copy operationz
/workspace)r  rD  r+  z
--instancezid of the instancez--connectionzSid of cloud connection on your account (get from calling 'vastai show connections')z
--transferzRtype of transfer, possible options include Instance To Cloud and Cloud To InstancezInstance to Cloud	--dry-runz%show what would have been transferredr  r   --size-onlyz1skip based on size only, not mod-time or checksum--ignore-existingz(skip all files that exist on destination--updatez,skip files that are newer on the destination--delete-excludedz+delete files on dest excluded from transferz]End date/time in format 'YYYY-MM-DD HH:MM:SS PM' (UTC). Default is contract's end. (optional))rD  r  zovastai cloud copy --src SRC --dst DST --instance INSTANCE_ID -connection CONNECTION_ID --transfer TRANSFER_TYPEz.Copy files/folders to and from cloud providersaZ  
        Copies a directory from a source location to a target location. Each of source and destination
        directories can be either local or remote, subject to appropriate read and write
        permissions required to carry out the action. The format for both src and dst is [instance_id:]path.
        You can find more information about the cloud copy operation here: https://vast.ai/docs/gpu-instances/cloud-sync
                    
        Examples:
         vastai show connections
         ID    NAME      Cloud Type
         1001  test_dir  drive 
         1003  data_dir  drive 
         
         vastai cloud copy --src /folder --dst /workspace --instance 6003036 --connection 1001 --transfer "Instance To Cloud"

        The example copies all contents of /folder into /workspace on instance 6003036 from gdrive connection 'test_dir'.
    c                 C   s"  t | d}| jdu r| jdu rtd dS g }| jr|d | jr'|d | jr/|d | jr7|d | j	r?|d td	| j d
| j d
| j
 d
| j d
| j 
 | j| j| j
| j| j|d}| jrptd t| | jrt| j| j| j t | dj| j
dddi}t| |}|  | d }| j dkr|r|dd}|durtd| d  }|dkrtd dS ntd d}	d}
|dd}t| ||	|
d| j
|d dS td dS t| |t|d}|  |jd krtd! td" dS t|j td#jd$i t  dS )%r  r  Nr  r  r  r   r  r  r  r"  )r  r  r  selectedtransferrf  r  /instances/{id}/r  ownerr  r  zinstance to cloudinternet_up_cost_per_tbzInternet upload cost is $zB per TB. Are you sure you want to schedule a cloud backup? (y/n): rb   z Cloud backup scheduling aborted.zWarning: Could not retrieve internet upload cost. Proceeding without confirmation. You can use show scheduled-jobs and delete scheduled-job commands to delete scheduled cloud backup job.z
cloud copyz/api/v0/commands/rclone/end_dater   )r  contract_end_datez1Instance not found. Please check the instance ID.r  rQ   zZCloud Copy Started - check instance status bar for progress updates (~30 seconds delayed).ziWhen the operation is finished you should see 'Cloud Copy Operation Finished' in the instance status bar.r  r%   ) r`  r  r  r+   dry_runr   	size_onlyignore_existingry  delete_excludedr  
connectionr  r^  r  r  r  r  r   r   rT   rV   rf   rS   re   r<   r  r   rP   rU   r4   r  )r   rW   rf  r  r   r   r  up_costconfirmr  r  r	  r%   r%   r&   cloud__copyA  sx   
+




0	



r  z1instance_id of the container instance to snapshotz--container_registryzEContainer registry to push the snapshot to. Default will be docker.ioz	docker.io--repozrepo to push the snapshot toz--docker_login_userz)Username for container registry with repoz--docker_login_passz2Password or token for container registry with repoz--pauseziPause container's processes being executed by the CPU to take snapshot (true/false). Default will be truero  zvastai take snapshot INSTANCE_ID --repo REPO --docker_login_user USER --docker_login_pass PASS[--container_registry REGISTRY] [--pause true|false]z[Schedule a snapshot of a running container and push it to your repo in a container registryaC  
        Takes a snapshot of a running container instance and pushes snapshot to the specified repository in container registry.
        
        Use pause=true to pause the container during commit (safer but slower),
        or pause=false to leave it running (faster but may produce a filesystem-
// safer snapshot).
    c                 C   s  | j }| j}| j}| j}| j}| j}td| d| d|  ||||||d}t| d| d}| jrAtd tt	j
|dd	 t| |t|d
}	|	  |	jdkrr|		 }
|
drhtd| d| d dS t|
dd dS t|	j tdjdi t  dS )a  
    Take a container snapshot and push.

    @param instance_id: instance identifier.
    @param repo: Docker repository for the snapshot.
    @param container_registry: Container registry
    @param docker_login_user: Docker registry username.
    @param docker_login_pass: Docker registry password/token.
    @param pause: "true" or "false" to pause the container during commit.
    zTaking snapshot for instance z and pushing to repo z in container registry )r   container_registrypersonal_repodocker_login_userdocker_login_passpausez/instances/take_snapshot/r  zRequest JSON:r  indentr  rQ   r  z;Snapshot request sent successfully. Please check your repo z~ in 5-10 mins. It can take longer than 5-10 mins to push your snapshot image to your repo depending on the size of your image.r  z#Unknown error with snapshot requestr  Nr%   )r  repor  r  r  r  r+   r`  r^  rV   r]  r   rP   rT   rU   rS   r4   r   r  )r   r  r  r  r6  password
pause_flagr  rW   r   datar%   r%   r&   take__snapshot  s6   	


r  c                    sr    fdd} dkr| d u r|d u s|   dkr$| d u r!|d us$|   dkr5| d ur0|d us7|  d S d S d S )Nc                     sF   d}  dkr| d7 } n dkr| d7 } n dkr| d7 } t |  d S )Nrc   r  z/For HOURLY jobs, day and hour must both be "*".r  zHFor DAILY jobs, day must be "*" and hour must have a value between 0-23.r  z[For WEEKLY jobs, day must have a value between 0-6 and hour must have a value between 0-23.)r,   rg   )r  r	  r%   r&   raise_frequency_error  s   

z8validate_frequency_values.<locals>.raise_frequency_errorr  r  r  r%   )r  r  r	  r   r%   r  r&   r    s   

r  c              
   C   sh  t | \}}| jd u r|}t|| _||krtd| j| j| j}	}
}t| d}||||||	|
||d	}tj	|t
|d}| jrItd t| |jdkrctd| d| d	| j d
| j d	 d S |jdkrstd|j d d S |jdkrtd}|  dkr| d }t| d| d}t|||| j| j|}d S td d S td|j d|j  d S )Nz*--start_date must be less than --end_date./commands/schedule_job/)	r  r  r  request_methodrequest_bodyr  r  r	  r  r  r  rQ   z/add_scheduled_job insert: success - Scheduling  job to  from  UTC to  UTC  z.add_scheduled_job insert: failed status_code: 7. It could be because you aren't using a valid api_key.i  z>Existing scheduled job found. Do you want to update it (y|n)? rb   scheduled_job_idr  zJob update aborted by the user.z(add_scheduled_job insert: failed error: z. Response body: )convert_dates_to_timestampsr  r  r   r  r  r  r`  rR   postrP   r^  r+   rU   
start_datere   r<   rf   rV   update_scheduled_jobr4   )r   r  r  r  r"  r  r	  start_timestampend_timestampr  r  r	  schedule_job_urlr#  rX   
user_inputr*  r%   r%   r&   r    sD   



*

r  c              
   C   s   t j|t|d}|  |jdkr*td| d|  d| d| d	 t|  |S |jdkr:td	|j d
 |S td	|j d t|  |S )Nr  rQ   z/add_scheduled_job update: success - Scheduling r$  r%  r&  r'  r(  z.add_scheduled_job update: failed status_code: r)  r   )rR   putrP   rT   rU   r+   rV   )r  r1  r	  r-  r  r#  rX   r%   r%   r&   r.  D  s   
"
r.  --namezname of the api-keyz--permission_filezofile path for json encoded permissions, see https://vast.ai/docs/cli/roles-and-permissions for more informationz--key_paramsz.optional wildcard key params for advanced keysz?vastai create api-key --name NAME --permission_file PERMISSIONSzZCreate a new api-key with restricted permissions. Can be sent to other users and teammatesz
        In order to create api keys you must understand how permissions must be sent via json format. 
        You can find more information about permissions here: https://vast.ai/docs/cli/roles-and-permissions
    c              
   C   s   z(t | d}t| j}t| |t| j|| jdd}|  td	|
  W d S  ty:   td	| j Y d S  tjjyU } ztd	| W Y d }~d S d }~w tyl } ztd| W Y d }~d S d }~ww )N/auth/apikeys/)r%  permissions
key_paramsr  zapi-key created {}z&Error: Permission file '{}' not found.z+Error: Failed to create api-key. Reason: {}zAn unexpected error occurred:)r`  r   permission_filer   rP   r%  r7  rT   r+   r   rV   FileNotFoundErrorrR   
exceptionsRequestExceptionr>   )r   rW   r6  r   er%   r%   r&   create__api_keyV  s   

r=  r  z*local subnet for cluster, ex: '0.0.0.0/24'r  z:Machine ID of manager node in cluster. Must exist already.z'vastai create cluster SUBNET MANAGER_IDzCreate Vast clusterzG
        Create Vast Cluster by defining a local subnet and manager id.c                 C   sb   | j | jd}| jrtd t| t| d}t| ||d}|  | jr'|S t| d  d S )N)r  r  r  	/cluster/rV   r  )	r  r  r^  r+   r`  r   rT   r  rV   r   r  r   r   r%   r%   r&   create__clusterp  s   
rA  r%  zEnvironment variable namer   zEnvironment variable valuez$vastai create env-var <name> <value>z&Create a new user environment variable)r  r  c                 C   p   t | d}| j| jd}t| |t|d}|  | }|dr+t|dd d	S td|dd  d	S )
z7Create a new environment variable for the current user.	/secrets/r  r   r  r  r  z*Environment variable created successfully.z'Failed to create environment variable: Unknown errorN)	r`  r%  r   r   rP   rT   rV   rS   r+   r   rW   r  r   r?   r%   r%   r&   create__env_var     

rG  zadd your existing ssh public key to your account (from the .pub file). If no public key is provided, a new key pair will be generated.r*  )r  rD  r,  z-yz--yesz#automatically answer yes to promptsz+vastai create ssh-key [ssh_public_key] [-y]zCreate a new ssh-keya  
        You may use this command to add an existing public key, or create a new ssh key pair and add that public key, to your Vast account. 
        
        If you provide an ssh_public_key.pub argument, that public key will be added to your Vast account. All ssh public keys should be in OpenSSH format.
        
                Example: $vastai create ssh-key 'ssh_public_key.pub'
        
        If you don't provide an ssh_public_key.pub argument, a new Ed25519 key pair will be generated.
            
                Example: $vastai create ssh-key
                    
        The generated keys are saved as ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public). Any existing id_ed25519 keys are backed up as .backup_<timestamp>.
        The public key will be added to your Vast account.
        
        All ssh public keys are stored in your Vast account and can be used to connect to instances they've been added to.
    c                 C   sZ   | j }|st| j}ntd t| d}t| |td|id}|  td|	  d S )Nz,Adding provided SSH public key to account.../ssh/r5  r  z]ssh-key created {}
Note: You may need to add the new public key to any pre-existing instances)
r5  generate_ssh_keyyesr+   r`  r   rP   rT   r   rV   )r   ssh_key_contentrW   r   r%   r%   r&   create__ssh_key  s   
rM  c                 C   s  t d t d }|d }|d }z	|jddd W n! ty< } zt d| tjd	 td
 W Y d}~nd}~ww | sE| rt d|  | rUt d d}nt	d
 }|dvrht d td tt }|d|  }|d|  }z"| r|| t d|  | r|| t d|  W n! ty } zt d| tjd	 td
 W Y d}~nd}~ww t d ztjddgddd W n ty   t dtjd	 td
 Y nw z%dddd t|d!d"d#td$ptd%d& d'g	}	tj|	ddd(dd)}
W nS tjy= } z$t d*| tjd	 |jr.t d+|j tjd	 td
 W Y d}~n&d}~w ty^ } zt d,| tjd	 td
 W Y d}~nd}~ww z|d- W n ty } zt d.| tjd	 W Y d}~nd}~ww z!t|d/}|  }W d   |W S 1 sw   Y  |W S  ty } zt d0| tjd	 td
 W Y d}~dS d}~ww )1aU  
    Generate a new SSH key pair using ssh-keygen and return the public key content.
    
    Args:
        auto_yes (bool): If True, automatically answer yes to prompts
    
    Returns:
        str: The content of the generated public key
        
    Raises:
        SystemExit: If ssh-keygen is not available or key generation fails
    zVNo SSH key provided. Generating a new SSH key pair and adding public key to account...r  
id_ed25519zid_ed25519.pubi  T)modeexist_okzError creating .ssh directory: r   r7   Nz/An SSH key pair 'id_ed25519' already exists in z/Auto-answering yes to backup existing key pair.rb   z_Would you like to generate a new key pair and backup your existing id_ed25519 key pair. [y/N]: )rb   rK  zAborted. No new key generated.r   zid_ed25519.backup_zid_ed25519.pub.backup_z#Backed up existing private key to: z"Backed up existing public key to: z$Error backing up existing SSH keys: z?Generating new SSH key pair and adding public key to account...z
ssh-keygenz--helpF)r3   r5   zAError: ssh-keygen not found. Please install OpenSSH client tools.-ted25519z-fz-Nrc   z-CUSERUSERNAMEr6  z-vast.aizy
)r3   r4   re   r5   zError generating SSH key: zssh-keygen error: z(Unexpected error during key generation: i  z4Warning: Could not set permissions for private key: r   z$Error reading generated public key: )r+   r   r  mkdirOSErrorr,   r-   rg   r  re   rf   r"   r   renamer9   r:   r9  r]   r  getenvCalledProcessErrorr>   chmodr   r  r<   IOError)auto_yesssh_dirprivate_key_pathpublic_key_pathr<  rX   r   backup_private_pathbackup_public_pathr  r?   r  public_key_contentr%   r%   r&   rJ    s   



 
rJ  z--template_hashztemplate hash (required, but **Note**: if you use this field, you can skip search_params, as they are automatically inferred from the template)z--template_idztemplate id (optional)-n--no-default'Disable default search param query argsz--launch_argszlaunch args  string for create instance  ex: "--onstart onstart_wget.sh  --env '-e ONSTART_PATH=https://s3.amazonaws.com/vast.ai/onstart_OOBA.sh' --image atinoda/text-generation-webui:default-nightly --disk 64"z--endpoint_namezYdeployment endpoint name (allows multiple workergroups to share same deployment endpoint)z--endpoint_idzWdeployment endpoint id (allows multiple workergroups to share same deployment endpoint)z--test_workerszinumber of workers to create to get an performance estimate for while initializing workergroup (default 3)r   z	--gpu_ramz5estimated GPU RAM req  (independent of search string)--search_paramszsearch param string for search offers    ex: "gpu_ram>=23 num_gpus=2 gpu_name=RTX_4090 inet_down>200 direct_port_count>2 disk_space>=64"z
--min_loadzw[NOTE: this field isn't currently used at the workergroup level] minimum floor load in perf units/s  (token/s for LLms)z--target_utilz}[NOTE: this field isn't currently used at the workergroup level] target capacity utilization (fraction, max 1.0, default 0.9)z--cold_multz[NOTE: this field isn't currently used at the workergroup level]cold/stopped instance capacity target as multiple of hot capacity target (default 2.0)z--cold_workersz9min number of workers to keep 'cold' for this workergroupz--auto_instanceunusedprodz#vastai workergroup create [OPTIONS]zCreate a new autoscale groupz
        Create a new autoscaling group to manage a pool of worker instances.
                    
        Example: vastai create workergroup --template_hash HASH  --endpoint_name "LLama" --test_workers 5
        c                 C   s  t | d}| jrd}nd}| jd ur| jnd|  }d| j| j| j| j| j| j	| j
|| j| j| j| j| jd}| jrCtd t| t| |t|d}|  d|jd	dv r~ztd
|  W d S  tjjy}   td t| t|j Y d S w td|jd	 t|j d S )N
/autojobs/rc   ) verified=True rentable=True rented=Falser  )r  min_loadtarget_util	cold_multcold_workerstest_workerstemplate_hashtemplate_idsearch_paramslaunch_argsrA  endpoint_nameendpoint_idautoscaler_instancer  r  rN   Content-Typezworkergroup create {}The response is not valid JSON.'The response is not JSON. Content-Type:)r`  
no_defaultrr  r<   rk  rl  rm  rn  ro  rp  rq  rs  rA  rt  ru  auto_instancer^  r+   r   rP   rT   rS   r   rV   rR   r:  JSONDecodeErrorr4   )r   rW   r   rr  r  r   r%   r%   r&   create__workergroup:  s*   
:r}  z6minimum floor load in perf units/s  (token/s for LLms)        z<target capacity utilization (fraction, max 1.0, default 0.9)?zVcold/stopped instance capacity target as multiple of hot capacity target (default 2.5)g      @zFmin number of workers to keep 'cold' when you have no load (default 5)   z--max_workersz?max number of workers your endpoint group can have (default 20)   z]deployment endpoint name (allows multiple autoscale groups to share same deployment endpoint)z vastai create endpoint [OPTIONS]zCreate a new endpoint groupz
        Create a new endpoint group to manage many autoscaling groups
                    
        Example: vastai create endpoint --target_util 0.9 --cold_mult 2.0 --endpoint_name "LLama"
    c              	   C   s   t | d}d| j| j| j| j| j| j| jd}| jr"t	d t	| t
j|t|d}|  d|jddv r]zt	d	|  W d S  t
jjy\   t	d
 t	| t	|j Y d S w t	d|jd t	|j d S )N/endptjobs/r  )r  rk  rl  rm  rn  max_workersrt  rv  r  r  rN   rw  rc   zcreate endpoint {}rx  ry  )r`  rk  rl  rm  rn  r  rt  r{  r^  r+   rR   r,  rP   rT   rS   r   rV   r:  r|  r4   r   rW   r  r   r%   r%   r&   create__endpointq  s"   
$r  c                 C   s   d}| j rd}| j dks| j dgks| j g krd}d | _ | js(| js%| jr(d| _| jr8|dkr8tdtjd dS | jrF| jrBd}|S d	}|S | jrP| jrNd
nd}|S )Nr2  r   rc   TzaError: Can't use --jupyter and --args together. Try --onstart or --onstart-cmd instead of --args.r   r7   z!jupyter_direc ssh_direc ssh_proxyzjupyter_proxy ssh_proxyzssh_direc ssh_proxy	ssh_proxy)	r   jupyterjupyter_dirjupyter_labr+   r,   r-   directr2  )r   runtyper%   r%   r&   get_runtype  s&    
r  c                 C   s   | j r| jstd| js| jr| jstdtd}|| js.td| j d| j| jr5dnd| jr<| jn| jd}| j	rI| j	|d	< | j rS| j |d
< |S | jrZd|d
< |S )NzError: --volume-size can only be used with --create-volume. Please specify a volume ask ID to create a new volume of that size.zBError: --mount-path is required when creating or linking a volume.z^(/)?([^/\0]+(/)?)+$zError: --mount-path 'z!' is not a valid Linux file path.TF)
mount_path
create_new	volume_idr%  r     )
volume_sizecreate_volumer   r   link_volumer  r   r  r  volume_label)r   valid_linux_path_regexvolume_infor%   r%   r&   validate_volume_params  s&   




r  c                 C   sR   d| d v rd S | d d  d}dd |D }|stdd|| d d< d S )	Nr  r  envPORTAL_CONFIG|c                 S   s   g | ]
}d |  vr|qS )r  )rf   )r#   
config_strr%   r%   r&   r     rh  z*validate_portal_config.<locals>.<listcomp>zwError: env variable PORTAL_CONFIG must contain at least one non-jupyter related config string if runtype is not jupyter)r)   r   r   )r  portal_configfiltered_configr%   r%   r&   validate_portal_config  s   r  z;id of instance type to launch (returned from search offers)z"Create instance from template infoz--userziUser to use with docker create. This breaks some images, so only use this if you are certain you need it.z--diskz"size of local disk partition in GB
   --image docker container image to launch--loginzIdocker login arguments for private repo authentication, surround with '' z--labelzlabel to set on the instancez	--onstartz!filename to use as onstart script--onstart-cmd-contents of onstart script as single argumentz--entrypointz,override entrypoint for args launch instance--sshLaunch as an ssh instance type	--jupyter7Launch as a jupyter instance instead of an ssh instance--direct1Use (faster) direct connections for jupyter & ssh--jupyter-dirlFor runtype 'jupyter', directory in instance to use to launch jupyter. Defaults to image's working directory--jupyter-lab7For runtype 'jupyter', Launch instance with jupyter labz--lang-utf8zzWorkaround for images with locale problems: install and generate locales before instance launch, and set locale to C.UTF-8z--python-utf8zJWorkaround for images with locale problems: set python's locale to C.UTF-8z--extrar-  --envz9env variables and port mapping options, surround with '' z--argszrlist of arguments passed to container ENTRYPOINT. Onstart is recommended for this purpose. (must be last argument))r,  r  z--forcez:Skip sanity checks when creating from an existing instancez--cancel-unavailzJReturn error if scheduling fails (rather than creating a stopped instance)z--bid_pricezP(OPTIONAL) create an INTERRUPTIBLE instance with per machine bid price in $/hourz--create-volumeVOLUME_ASK_IDzpCreate a new local volume using an ID returned from the "search volumes" command and link it to the new instance)r  r  rD  z--link-volumeEXISTING_VOLUME_IDzkID of an existing rented volume to link to the instance during creation. (returned from "show volumes" cmd)z--volume-sizezSSize of the volume to create in GB. Only usable with --create-volume (default 15GB)z--mount-pathzPThe path to the volume from within the new instance container. e.g. /root/volumez--volume-labelzJ(optional) A name to give the new volume. Only usable with --create-volumez0vastai create instance ID [OPTIONS] [--args ...]zCreate a new instancea	  
        Performs the same action as pressing the "RENT" button on the website at https://console.vast.ai/create/ 
        Creates an instance from an offer ID (which is returned from "search offers"). Each offer ID can only be used to create one instance.
        Besides the offer ID, you must pass in an '--image' argument as a minimum.

        If you use args/entrypoint launch mode, we create a container from your image as is, without attempting to inject ssh and or jupyter.
        If you use the args launch mode, you can override the entrypoint with --entrypoint, and pass arguments to the entrypoint with --args.
        If you use --args, that must be the last argument, as any following tokens are consumed into the args string.
        For ssh/jupyter launch types, use --onstart-cmd to pass in startup script, instead of --entrypoint and --args.
        
        Examples:

        # create an on-demand instance with the PyTorch (cuDNN Devel) template and 64GB of disk
        vastai create instance 384826 --template_hash 661d064bbda1f2a133816b6d55da07c3 --disk 64

        # create an on-demand instance with the pytorch/pytorch image, 40GB of disk, open 8081 udp, direct ssh, set hostname to billybob, and a small onstart script
        vastai create instance 6995713 --image pytorch/pytorch --disk 40 --env '-p 8081:8081/udp -h billybob' --ssh --direct --onstart-cmd "env | grep _ >> /etc/environment; echo 'starting up'";                

        # create an on-demand instance with the bobsrepo/pytorch:latest image, 20GB of disk, open 22, 8080, jupyter ssh, and set some env variables
        vastai create instance 384827  --image bobsrepo/pytorch:latest --login '-u bob -p 9d8df!fd89ufZ docker.io' --jupyter --direct --env '-e TZ=PDT -e XNAME=XX4 -p 22:22 -p 8080:8080' --disk 20

        # create an on-demand instance with the pytorch/pytorch image, 40GB of disk, override the entrypoint to bash and pass bash a simple command to keep the instance running. (args launch without ssh/jupyter)
        vastai create instance 5801802 --image pytorch/pytorch --disk 40 --onstart-cmd 'bash' --args -c 'echo hello; sleep infinity;'

        # create an interruptible (spot) instance with the PyTorch (cuDNN Devel) template, 64GB of disk, and a bid price of $0.10/hr
        vastai create instance 384826 --template_hash 661d064bbda1f2a133816b6d55da07c3 --disk 64 --bid_price 0.1

        Return value:
        Returns a json reporting the instance ID of the newly created instance:
        {'success': True, 'new_contract': 7835610} 
    c                 C   s  | j rt| j d}| | _W d   n1 sw   Y  | jdu r'| j| _d}i ddd| jdt| jd| jd| j	d	| j
d
| jd| jd| jd| jd| jd| jd| jd| jd| jd| jd| j}| jsv| jr~t| }||d< | jdu rt| }|dkrdS ||d< | jdkr| j|d< d|d v rt| t| dj| jd}| jrtd t| t | |t!|d}|"  | j#r|S td|$  dS )zPerforms the same action as pressing the "RENT" button on the website at https://console.vast.ai/create/.

    :param argparse.Namespace args: Namespace with many fields relevant to the endpoint.
    r   Nr  r  imager  r  r  r  extraonstartimage_loginpython_utf8	lang_utf8use_jupyter_labr  forcecancel_unavailtemplate_hash_idr6  r  r7   r  r   r  z/asks/{id}/r  r  r  Started. {})%r  r   r  onstart_cmd
entrypointr  	parse_envr  	bid_pricer  r  r  loginr  r  r  r  r  r  rp  r6  r  r  r  r  r   r  r`  r   r   r^  r+   r   rP   rT   r  rV   )r   readerr  r  r  rW   r   r%   r%   r&   create__instance  s~   G

	



r  z--emailzemail address to use for loginz
--usernamezusername to use for loginz
--passwordzpassword to use for loginz--typezhost/clientzZvastai create subaccount --email EMAIL --username USERNAME --password PASSWORD --type TYPEzCreate a subaccounta@  
       Creates a new account that is considered a child of your current account as defined via the API key. 

       vastai create subaccount --email bob@gmail.com --username bob --password password --type host

       vastai create subaccount --email vast@gmail.com --username vast --password password --type host
    c                 C   s   d}| j r| j  dk}| j| j| j|dd}t| ddr'td t| dS t| d}t| |t	|d	}|
  |jd
krG| }t| dS t|j td|j  dS )ziCreates a new account that is considered a child of your current account as defined via the API key.
    Fhostr  )r'  r8  r  	host_only	parent_idr^  zRequest JSON would be: N/users/r  rQ   zFailed with error )rD  rf   r'  r8  r  getattrr+   r`  r   rP   rT   rU   rV   r4   )r   r  r  rW   r   r  r%   r%   r&   create__subaccountR	  s*   	


r  z--team_namezname of the teamz(vastai create-team --team_name TEAM_NAMEzCreate a new teama  
        As of right now creating a team account will convert your current account into a team account. 
        Once you convert your user account into a team account, this change is permanent and cannot be reversed. 
        The created team account will inherit all aspects of your existing user account, including billing information, cloud services, and any other account settings.
        The user who initiates the team creation becomes the team owner. 
        Carefully evaluate the decision to convert your user account into a team account, as this change is permanent.
        For more information see: https://vast.ai/docs/team/introduction
    c                 C   s8   t | d}t| |td| jid}|  t|  d S )N/team/	team_namer  )r`  r   rP   r  rT   r+   rV   r   rW   r   r%   r%   r&   create__team	  s   
r  zname of the rolez--permissionszMfile path for json encoded permissions, look in the docs for more informationz=vastai create team-role --name NAME --permissions PERMISSIONSzAdd a new role to your teamz
        Creating a new team role involves understanding how permissions must be sent via json format.
        You can find more information about permissions here: https://vast.ai/docs/cli/roles-and-permissions
    c                 C   sD   t | d}t| j}t| |t| j|dd}|  t|  d S )Nz/team/roles/r%  r6  r  )	r`  r   r6  r   rP   r%  rT   r+   rV   r   rW   r6  r   r%   r%   r&   create__team_role	  s
   

r  c                   C   s   t ddtdt ddtdt ddtdt dd	tdt d
dtdt ddtdt ddtdt ddddt ddddt ddddt ddtdt ddddt ddtdt ddtdt d d!dd"d#t d$d%tdt d&d'tdt d(d)ddt d*d+tdt d,d-ddgS ).Nr4  name of the templater  r  r  z--image_tagz<docker image tag (can also be appended to end of image_path)z--hrefzlink you want to provider  zlink to repositoryr  zHdocker login arguments for private repo authentication, surround with ''r  z&Contents of the 'Docker options' fieldr  r  r  r  r  r  r  r  r  r  r  r  r  r  rf  zsearch offers filtersrc  rd  re  r  z--disk_spacezdisk storage space, in GBz--readmezreadme stringz--hide-readmezhide the readme from usersz--desczdescription stringz--publicz!make template available to public)r   r]   r%   r%   r%   r&   get_template_arguments	  s*   r  zvastai create templatezCreate a new templatea  
        Create a template that can be used to create instances with

        Example: 
            vastai create template --name "tgi-llama2-7B-quantized" --image "ghcr.io/huggingface/text-generation-inference:1.0.3" 
                                    --env "-p 3000:3000 -e MODEL_ARGS='--model-id TheBloke/Llama-2-7B-chat-GPTQ --quantize gptq'" 
                                    --onstart-cmd 'wget -O - https://raw.githubusercontent.com/vast-ai/vast-pyworker/main/scripts/launch_tgi.sh | bash' 
                                    --search_params "gpu_ram>=23 num_gpus=1 gpu_name=RTX_3090 inet_down>128 direct_port_count>3 disk_space>=192 driver_version>=535086005 rented=False" 
                                    --disk_space 8.0 --ssh --direct
    c                 C   s  t | d}| jo
| j}| jo| j}| jp| j}| jrdn| jr!dnd}| jr1| jd}|d }nd }i }| jsGddidd	iddidd	id
}t| j|t	t
t}	i d| jd| jd| jd| jd| jd| jd| jd|d|d| jd|d|d| jd|d|	d| jd| j| j | j| j d}
| jrtd t|
 t| |t|
d}|  z| }|d rtd |d!   W d S t|d"  W d S  t j!j"y   td# Y d S w )$N
/template/r  r2  r   r"  r   r`  TFr  rC  rE  r@  r%  r  r@   hrefr  r  r  
jup_direct
ssh_directr  r  use_sshr  docker_login_repoextra_filtersrecommended_disk_spacereadme)readme_visibledescprivater  r  r  zNew Template: templater  rx  )#r`  r  r  r2  r  r)   rz  r  rr  offers_fieldsoffers_aliasoffers_multr%  r  	image_tagr  r  r  r  r  r  r  r  hide_readmer  publicr^  r+   r   rP   rT   rV   rR   r:  r|  )r   rW   r  r  r  r  r  r  default_search_queryr  r  r   r  r%   r%   r&   create__template	  s   

	
r  zid of volume offerz-size in GB of volume. Default %(default)s GB.r  )r  r+  rD  zOptional name of volume.z!vastai create volume ID [options]zCreate a new volumez
        Creates a volume from an offer ID (which is returned from "search volumes"). Each offer ID can be used to create multiple volumes,
        provided the size of all volumes does not exceed the size of the offer.
    c                 C   ~   t | jt | jd}| jr| j|d< t| d}| jr#td t| t| |t|d}|	  | j
r4|S td|  d S )Nr  r   r%  	/volumes/r  r  r  r"   r  r   r%  r`  r^  r+   r   rP   rT   r  r   rV   r  r%   r%   r&   create__volume	
     

r  zid of network volume offerz5size in GB of network volume. Default %(default)s GB.z Optional name of network volume.z)vastai create network volume ID [options]zCreate a new network volumez
        Creates a network volume from an offer ID (which is returned from "search network volumes"). Each offer ID can be used to create multiple volumes,
        provided the size of all volumes does not exceed the size of the offer.
    c                 C   r  )Nr  r%  /network_volumes/r  r  r  r  r  r%   r%   r&   create__network_volume+
  r  r  r  z)ID of cluster to create overlay on top ofzoverlay network namez-vastai create overlay CLUSTER_ID OVERLAY_NAMEz4Creates overlay network on top of a physical clusterza
    Creates an overlay network to allow local networking between instances on a physical clusterc                 C   \   | j | jd}| jrtd| t| d}t| ||d}|  | jr$|S t| d  d S )N)r  r%  request json:	/overlay/r?  r  )	r  r%  r^  r+   r`  r   rT   r  rV   r@  r%   r%   r&   create__overlayL
     


r  zid of apikey to removezvastai delete api-key IDzRemove an api-keyc                 C   :   t | dj| jd}t| |td}|  t|  d S Nz/auth/apikeys/{id}/r  rO   r`  r   r   r   rP   rT   r+   rV   r  r%   r%   r&   delete__api_keyf
     r  zid ssh key to deletezvastai delete ssh-key IDzRemove an ssh-keyc                 C   r  )N
/ssh/{id}/r  rO   r  r  r%   r%   r&   delete__ssh_keyq
  r  r  zid of scheduled job to removezvastai delete scheduled-job IDzDelete a scheduled jobc                 C   r  )Nz/commands/schedule_job/{id}/r  rO   r  r  r%   r%   r&   delete__scheduled_job|
  r  r  zID of cluster to deletez vastai delete cluster CLUSTER_IDzDelete Clusterz
        Delete Vast Clusterc                 C   sX   d| j i}| jrtd| t| d}t| ||d}|  | jr"|S t| d  d S )Nr  r  r>  r?  r  )r  r^  r+   r`  r   rT   r  rV   r@  r%   r%   r&   delete__cluster
  s   	

r  zid of group to deletezvastai delete workergroup ID zDelete a workergroup groupz
        Note that deleting a workergroup doesn't automatically destroy all the instances that are associated with your workergroup.
        Example: vastai delete workergroup 4242
    c                 C      | j }t| d| d}d| j d}| jrtd t| t| |t|d}|  d|jdd	v rXztd
|	  W d S  t
jjyW   td t| t|j Y d S w td|jd t|j d S )Nri  r  r  )r  
autojob_idr  r  rN   rw  rc   zworkergroup delete {}rx  ry  r   r`  r^  r+   r   rP   rT   rS   r   rV   rR   r:  r|  r4   r   r   rW   r  r   r%   r%   r&   delete__workergroup
  $   
r  zid of endpoint group to deletezvastai delete endpoint ID zDelete an endpoint groupz
        Note that deleting an endpoint group doesn't automatically destroy all the instances that are associated with your endpoint group, nor all the workergroups.
        Example: vastai delete endpoint 4242
    c                 C   r  )Nr  r  r  )r  endptjob_idr  r  rN   rw  rc   zdelete endpoint {}rx  ry  r  r  r%   r%   r&   delete__endpoint
  r  r  z#Environment variable name to deletezvastai delete env-var <name>z"Delete a user environment variablec                 C   sl   t | d}d| ji}t| |t|d}|  | }|dr)t|dd d	S td|dd  d	S )
z4Delete an environment variable for the current user.rC  r  r  r  r  z*Environment variable deleted successfully.z'Failed to delete environment variable: rE  N)r`  r%  r   rP   rT   rV   rS   r+   rF  r%   r%   r&   delete__env_var
  s   


r  overlay_identifierz+ID (int) or name (str) of overlay to delete)r  r,  z(vastai delete overlay OVERLAY_IDENTIFIERz;Deletes overlay and removes all of its associated instancesc              	   C   s   | j }z
t|}d|i}W n ttfy   d|i}Y nw | jr%td| t| d}t| ||d}|  | j	r:|S t|
 d  d S )Nr  overlay_namer  r  r?  r  )r  r"   r   	TypeErrorr^  r+   r`  r   rT   r  rV   )r   
identifierr  r  r   r   r%   r%   r&   delete__overlay
  s"   

r  z--template-idz!Template ID of Template to Deletez	--hash-idzHash ID of Template to DeletezAvastai delete template [--template-id <id> | --hash-id <hash_id>]zDelete a Templatea  
        Note: Deleting a template only removes the user's replationship to a template. It does not get destroyed
        Example: vastai delete template --template-id 12345
        Example: vastai delete template --hash-id 49c538d097ad6437413b83711c9f61e8
    c                 C   s   t | d}| jrd| ji}n| jrd| ji}ntd d S | jr0td t| t|  t| t| |t|d}t| d|jdd	v rjzt| d
  W d S  t	j
jyi   td t| t|j Y d S w td|jd t|j d S )Nr  hash_idrq  zFERROR: Must Specify either Template ID or Hash ID to delete a templater  r  rN   rw  rc   r  rx  ry  )r`  r  rq  r+   r^  r   rP   rS   rV   rR   r:  r|  r4   r  r%   r%   r&   delete__template  s0   
r  zid of volume contractzvastai delete volume IDzDelete a volumez
        Deletes volume with the given ID. All instances using the volume must be destroyed before the volume can be deleted.
    c                 C   sJ   t | dd| jid}t| |td}|  | jr|S td|  d S )Nr  r   rZ  rO   zDeleted. {})	r`  r   r   rP   rT   r  r+   r   rV   r  r%   r%   r&   delete__volume5  s   	r  c                 C   s   t |dj| d}t||ti d}|  |jr|S |jdkr<| }|d r4tdjd	i t	  d S t|d  d S t|j
 tdjd	i t	  d S )
Nr  r  r  rQ   r  zdestroying instance {id}.r  r  r%   )r`  r   r   rP   rT   r  rU   rV   r+   r  r4   )r   r   rW   r   r  r%   r%   r&   destroy_instanceG  s   

r  zid of instance to deletez;vastai destroy instance id [-h] [--api-key API_KEY] [--raw]z0Destroy an instance (irreversible, deletes data)z
        Perfoms the same action as pressing the "DESTROY" button on the website at https://console.vast.ai/instances/
        Example: vastai destroy instance 4242
    c                 C      t | j|  dS )zPerfoms the same action as pressing the "DESTROY" button on the website at https://console.vast.ai/instances/.

    :param argparse.Namespace args: should supply all the command-line options
    N)r  r   r   r%   r%   r&   destroy__instanceX  s   r  idszids of instance to destroy+z%vastai destroy instances [--raw] <id>z8Destroy a list of instances (irreversible, deletes data)c                 C   s   | j D ]}t||  qdS )
    N)r  r  )r   r   r%   r%   r&   destroy__instancesh  s   
r  zvastai destroy teamzDestroy your teamc                 C   s0   t | d}t| |td}|  t|  d S )Nr  rO   )r`  r   rP   rT   r+   rV   r  r%   r%   r&   destroy__teams  s   
r  
ssh_key_idz'id of the key to detach to the instancez$vastai detach instance_id ssh_key_idz"Detach an ssh key from an instancez0
        Example: vastai detach 99999 12345
    c                 C   s>   t | dj| j| jd}t| |td}|  t|  d S )Nz!/instances/{id}/ssh/{ssh_key_id}/)r   r  rO   )	r`  r   r  r  r   rP   rT   r+   rV   r  r%   r%   r&   detach__ssh}  s   
r  zid of instance to execute onCOMMANDz(bash command surrounded by single quoteszvastai execute id COMMANDz3Execute a (constrained) remote command on a machinea"  
        Examples:
          vastai execute 99999 'ls -l -o -r'
          vastai execute 99999 'rm -r home/delete_this.txt'
          vastai execute 99999 'du -d2 -h'

        available commands:
          ls                 List directory contents
          rm                 Remote files or directories
          du                 Summarize device usage for a set of files

        Return value:
        Returns the output of the command which was executed on the instance, if successful. May take a few seconds to retrieve the results.

    c           	      C   s@  t | dj| jd}d| ji}| jrtd t| t| |t|d}|  | j	rMt
| j| j| j	 d}dj| jd}| j|d< t| |||d	| jd
 dS |jdkr| }|d rtddD ]$}td |d }t|}|jdkr|j|d d}t|  nq_dS dS t| dS t|j tdjdi t  dS )zExecute a (constrained) remote command on a machine.
    :param argparse.Namespace args: should supply all the command-line options
    z/instances/command/{id}/r  r  r  r  executez/api/v0/instances/command/{id}/r  r   r  NrQ   r  r      333333?
result_urlwriteable_pathrc   r  r%   )r`  r   r   r  r^  r+   r   rP   rT   r  r  r  r  r  rU   rV   r   r   r   rR   rS   r4   r4  r  )	r   rW   r  r   r  r  r  r   filtered_textr%   r%   r&   r    s>   






r  z'id of endpoint group to fetch logs fromz--levelzlog detail level (0 to 3)r7   z--tailrc   z,vastai get endpt-logs ID [--api-key API_KEY]z3Fetch logs for a specific serverless endpoint groupz0
        Example: vastai get endpt-logs 382
    c              
   C     | j tkrd | _ | j pdd }| j| jd}| jr| j|d< | jr,t| d t| t| |t|d}|	  ddd	d
d}|j
dkrd }z| }W n tyi } ztt| t|j W Y d }~nd }~ww | jrr|pq|jS || j }|r|rt||  d S d S d S t|j d S )Nhttps://run.vast.aiz/get_endpoint_logs/r   r[  tail with request json: r  info0info1tracedebugr   r7   r  r   rQ   rW   server_url_defaultr   r[  r&  r^  r+   r   rP   rT   rU   rV   r>   r]   r4   r  r   r   rW   r  r   levelsr  r<  dbg_lvlr%   r%   r&   get__endpt_logs  2   



 r2  z-vastai get wrkgrp-logs ID [--api-key API_KEY]z7Fetch logs for a specific serverless worker group groupc              
   C   r#  )Nr$  z/get_autogroup_logs/r%  r&  r'  r  r(  r)  r*  r+  r,  rQ   r-  r/  r%   r%   r&   get__wrkgrp_logs  r3  r4  zemail of user to be invitedz--rolezrole of user to be invitedz.vastai invite member --email EMAIL --role ROLEzInvite a team memberc                 C   sl   t | d| j| jdd}t| |td}|  |jdkr'td| j d d S t|j td|j  d S )	Nz/team/invite/)r'  roler  rO   rQ   zsuccessfully invited z to your current teamfailed with error )	r`  r'  r5  r   rP   rT   rU   r+   r4   r  r%   r%   r&   invite__member!  s   

r7  zID of cluster to add machine tor  zmachine id(s) to join clusterz*vastai join cluster CLUSTER_ID MACHINE_IDSzJoin Machine to Clusterz,
        Join's Machine to Vast Cluster
    c                 C   r  )N)r  r  r  r>  r?  r  )	r  r  r^  r+   r`  r   rT   r  rV   r@  r%   r%   r&   join__cluster2  s   

r8  z)Overlay network name to join instance to.zInstance ID to add to overlay.z,vastai join overlay OVERLAY_NAME INSTANCE_IDz#Adds instance to an overlay networkz6
    Adds an instance to a compatible overlay network.c                 C   r  )N)r%  r  r  r  r?  r  )	r%  r  r^  r+   r`  r   rT   r  rV   r@  r%   r%   r&   join__overlayN  r  r9  zid of instance to labelr  zlabel to setz"vastai label instance <id> <label>z$Assign a string label to an instancec                 C   s   t | dj| jd}d| ji}| jrtd t| t| |t|d}|  |	 }|d r;tdjd
i t
  d	S t|d  d	S )a

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    r  r  r  r  r  r  z(label for {args.id} set to {args.label}.r  Nr%   )r`  r   r   r  r^  r+   r   rP   rT   rV   r  )r   rW   r  r   r  r%   r%   r&   label__instancej  s   
r;  c                 C   s   t | }|  |jS r    )rR   rS   rT   r4   )rW   rX   r%   r%   r&   fetch_url_content  s   
r<  c                  C   s   dt fdd} |  r%ttd}t|}W d   n1 sw   Y  n2d}t | }tj|i d}|  | }ttd}t	|| W d   n1 sRw   Y  d	d
 |d D }|S )zRReturns a set of GPU names available on Vast.ai, with results cached for 24 hours.r   c                  S   s2   t jtsdS t tt jt } | tk S )z>Checks if the cache file exists and is less than 24 hours old.F)	r  r  r  
CACHE_FILEr	   r   r  getmtimeCACHE_DURATION)	cache_ager%   r%   r&   is_cache_valid  s   z&_get_gpu_names.<locals>.is_cache_validr   Nz/api/v0/gpu_names/unique/rO   wc                 S   s    g | ]}| d d ddqS )r"  ro   r.  rl  )r#   r%  r%   r%   r&   r     s    z"_get_gpu_names.<locals>.<listcomp>	gpu_names)
boolr   r=  rV   r   r.  rR   rS   rT   dump)rA  r   rC  endpointrW   r   formatted_gpu_namesr%   r%   r&   _get_gpu_names  s$   rH  z[US, CA]z[BR, AR, CL]zg[SE, UA, GB, PL, PT, SI, DE, IT, CH, LT, GR, FI, IS, AT, FR, RO, MD, HU, NO, MK, BG, ES, HR, NL, CZ, EEzH[CN, JP, KR, ID, IN, HK, MY, IL, TH, QA, TR, RU, VN, TW, OM, SG, AE, KZ]z[AU, NZ]z[EG, ZA])North_AmericaSouth_AmericaEuropeAsiaOceaniaAfricac                 C   sH   | t v rdS | dr"| dr"| dd d}tdd |D S d	S )
zLregion is valid if it is a key in REGIONS or a string list of country codes.T[]r7   r   rh  c                 s   s     | ]}t | d kV  qdS )r  N)r*   r<   )r#   coder%   r%   r&   r'         z#_is_valid_region.<locals>.<genexpr>F)REGIONSr=   r8  r)   all)regioncountry_codesr%   r%   r&   _is_valid_region  s   rW  c                 C   s   | t v rt |  S | S )z<Returns a string in a list format of two-char country codes.)rS  )rU  r%   r%   r&   _parse_region  s   rX  z-gz
--gpu-namez6Name of the GPU model, replace spaces with underscores)rD  requiredr  r  z
--num-gpus)12481214zNumber of GPUs requiredz-rz--regionz%Geographical location of the instancez%Name of the image to use for instance)rY  r  g      0@zDisk space required in GBz--limit)r+  rD  r  z-oz--orderzComma-separated list of fields to sort on. postfix field with - to sort desc. ex: -o 'num_gpus,total_flops-'.  default='score-'score-ztemplate hash which contains all relevant information about an instance. This can be used as a replacement for other parameters describing the instance configurationzlvastai launch instance [--help] [--api-key API_KEY] <gpu_name> <num_gpus> <image> [geolocation] [disk_space]zLLaunch the top instance from the search offers based on the given parametersa  
        Launches an instance based on the given parameters. The instance will be created with the top offer from the search results.
        Besides the gpu_name and num_gpus, you must pass in an '--image' argument as a minimum.

        If you use args/entrypoint launch mode, we create a container from your image as is, without attempting to inject ssh and or jupyter.
        If you use the args launch mode, you can override the entrypoint with --entrypoint, and pass arguments to the entrypoint with --args.
        If you use --args, that must be the last argument, as any following tokens are consumed into the args string.
        For ssh/jupyter launch types, use --onstart-cmd to pass in startup script, instead of --entrypoint and --args.
                    
        Examples:

            # launch a single RTX 3090 instance with the pytorch image and 16 GB of disk space located anywhere
            python vast.py launch instance -g RTX_3090 -n 1 -i pytorch/pytorch
                    
            # launch a 4x RTX 3090 instance with the pytorch image and 32 GB of disk space located in North America
            python vast.py launch instance -g RTX_3090 -n 4 -i pytorch/pytorch -d 32.0 -r North_America
            
        Available fields:

            Name                    Type      Description

            num_gpus:               int       # of GPUs
            gpu_name:               string    GPU model name
            region:                 string    Region of the instance
            image:                  string    Docker image name
            disk_space:             float     Disk space in GB
            ssh, jupyter, direct:   bool      Flags to specify the instance type and connection method.
            env:                    str       Environment variables and port mappings, encapsulated in single quotes.
            args:                   list      Arguments passed to the container's ENTRYPOINT, used only if '--args' is specified.
    c              
   C   s  d| j  d| j }| jr$t| jstd dS t| j}|d| 7 }| jr/|d| j 7 }ddidd	iddidd	id
}t||tt	t
}g }| jdD ]8}| }|sWqNd}|}|d|krid}|d}|d|krwd}|d}|t	v rt	| }|||g qN||d< d|d< |d dkrd|d< | jrt| j|d< | j|d< | jrt| jd}	|	 | _W d   n1 sw   Y  | jdu r| j| _i ddd| jd| j d| jd| jd| jd|d t| jd| jd!| jd"| jd#| jd$| jd%| jd&| jd'| jd(| j| j | j!| j"d)}
| j"du r3t#| }|d*kr/d*S ||
d+< | j$dkr>| j$|
d,< t%| d-& }| j'rQtd. t|
 t(| |t)|
d/}z>|*  |+ }| j,ri|W S td0&|+  |-d1rtd2|-d3  W dS td4|-d5 d6|-d7  W dS  t.j/j0y } ztd8|  W Y d}~dS d}~w t1y } ztd9|  W Y d}~dS d}~ww ):zAllows for a more streamlined and simplified way to create an instance.

    :param argparse.Namespace args: Namespace with many fields relevant to the endpoint.
    z	num_gpus=z
 gpu_name=z)Invalid region or country codes provided.Nz geolocation in z disk_space>=r`  TFr  rh  ascr.  r  r  order	on-demandrD  interruptiblebidlimitallocated_storager   r  r  rx  ru  rU  r  r  qr  r  r  r  r  r  r  r  r  )r  r  r  r7   r  r   z/launch_instance/r  r  r  r  z Instance launched successfully: new_contractzFailed to launch instance: errorz, re  zHTTP error occurred: zAn error occurred: )2ru  rx  rU  rW  r+   rX  r  r  r  r  r  rb  r)   r<   r   rf  r"   r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rp  r  r   r`  r   r^  r   rP   rT   rV   r  rS   rR   r:  	HTTPErrorr>   )r   
args_queryregion_query
base_queryr   rb  r%  	directionr   r  r  r  rW   r   rY   errr%   r%   r&   launch__instance  s   @






	


&rq  INSTANCE_IDzid of instancezANumber of lines to show from the end of the logs (default '1000')z--filterzGrep filter for log entriesz--daemon-logsz2Fetch daemon system logs instead of container logsz"vastai logs INSTANCE_ID [OPTIONS] zGet the logs for an instancec                 C   s.  t | dj| jd}| jrd| jini }| jr|d| ji | jr)|ddi | jr4td t| t	| |t
|d}|  |jd	kr| }td
dD ]1}td |d }td| j d|  t|}|jd	kr|j}tdd|}t|  dS qNt|d  dS t|j td|j  dS )zpGet the logs for an instance
    :param argparse.Namespace args: should supply all the command-line options
    z/instances/request_logs/{id}/r  filterr&  daemon_logsro  r  r  rQ   r   r  r  r   zwaiting on logs for instance z fetching from z\n\s*\nr   r  r6  N)r`  r   rr  rs  r&  ry  rt  r^  r+   r   rP   rT   rU   rV   r   r   r   rR   rS   r4   r   r   )r   rW   r  r   r  r   r?   cleaned_textr%   r%   r&   logse  s6   




rv  zid of instance to prepay forr  zaamount of instance credit prepayment (default discount func of 0.2 for 1 month, 0.3 for 3 months)z vastai prepay instance ID AMOUNTz&Deposit credits into reserved instancec                 C   s   t | dj| jd}d| ji}| jrtd t| t| |t|d}|  |	 }|d rKt
|d d}d	t
|d
 d }tdjdi t  dS t|d  dS )`
    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/instances/prepay/{id}/r  r  r  r  r  	timescaler   g      Y@discount_ratezwprepaid for {timescale} months of instance {args.id} applying ${args.amount} credits for a discount of {discount_rate}%r  Nr%   )r`  r   r   r  r^  r+   r   rP   rT   rV   roundr  )r   rW   r  r   r  rx  ry  r%   r%   r&   prepay__instance  s   
r{  zid of instance to rebootz#vastai reboot instance ID [OPTIONS]zReboot (stop/start) an instancezQ
        Stops and starts container without any risk of losing GPU priority.
    c                 C   s   t | dj| jd}t| |ti d}|  | jr=t| j| j	| j d}dj| jd}d| ji}t
| |||d| jd d	S |jd
kr_| }|d rWtdjdi t  d	S t|d  d	S t|j tdjdi t  d	S )rw  z/instances/reboot/{id}/r  r  zreboot instancez/api/v0/instances/reboot/{id}/r  r   r  NrQ   r  zRebooting instance {args.id}.r  r  r%   )r`  r   r   r   rP   rT   r  r  r  r  r  rU   rV   r+   r  r4   )r   rW   r   r  r  r  r  r%   r%   r&   reboot__instance  s"   


r|  zid of instance to recyclez$vastai recycle instance ID [OPTIONS]z$Recycle (destroy/create) an instancezz
        Destroys and recreates container in place (from newly pulled image) without any risk of losing GPU priority.
    c                 C   s   t | dj| jd}t| |ti d}|  |jdkr8| }|d r0tdjd
i t	  d	S t|d  d	S t|j
 tdjd
i t	  d	S )rw  z/instances/recycle/{id}/r  r  rQ   r  zRecycling instance {args.id}.r  r  Nr%   )r`  r   r   r   rP   rT   rU   rV   r+   r  r4   )r   rW   r   r  r%   r%   r&   recycle__instance  s   

r}  zid of user to removezvastai remove member IDzRemove a team memberc                 C   r  )Nz/team/members/{id}/r  rO   r  r  r%   r%   r&   remove__member  r  r~  r:  zvastai remove team-role NAMEzRemove a role from your teamc                 C   r  )N/team/roles/{id}/r  rO   )r`  r   r:  r   rP   rT   r+   rV   r  r%   r%   r&   remove__team_role   r  r  z
machine idzvastai reports IDz(Get the user reports for a given machinec                 C   sz   t | dj| jd}d| ji}| jrtd t| tj|t|d}|  |j	dkr;tdt
j|
 dd	  d
S d
S )rw  z/machines/{id}/reports/r  r   r  r  rQ   z	reports: r  r  N)r`  r   r   r^  r+   rR   rS   rP   rT   rU   rV   r]  r  r%   r%   r&   r    s   


 r  zvastai reset api-keyz-Reset your api-key (get new key from website)c                 C   s^   t d t| d}ddi}| jrt d t | t| |t|d}|  t d|  dS )	zNCaution: a bad API key will make it impossible to connect to the servers.
    fmlz/commands/reset_apikey/r  r  r  r  zapi-key reset N)r+   r`  r^  r   rP   rT   r   rV   r  r%   r%   r&   reset__api_key#  s   
r  r  c                    s|   fdd}t t |  fddtdt D }t|d}||| W d    d S 1 s7w   Y  d S )Nc                    s   | D ]R}d}|krTzd }t |tr | }n |}|rW n5W n ty8 } ztt| W Y d }~nd }~ww |d7 }dd|  }td| d t| |ks
qd S )Nr   r7   g      ?g?zretrying in rT  )r   r.   r>   r+   r]   r   r   )sub_argsr<  retriesr?   r<  stime)r  max_retriesr%   r&   worker7  s.   


z!exec_with_threads.<locals>.workerc                       g | ]
} ||  qS r%   r%   r#   r   )r   args_per_threadr%   r&   r   M  rh  z%exec_with_threads.<locals>.<listcomp>r   )r  )mathceilr*   r   r   map)r  r   ntr  r  sublistsexecutorr%   )r   r  r  r  r&   exec_with_threads6  s    "r  c                    s8   t  | d |  fddtdt  D }|S )Nr7   c                    r  r%   r%   r  lstsublist_sizer%   r&   r   X  rh  z'split_into_sublists.<locals>.<listcomp>r   )r*   r   )r  r   r  r%   r  r&   split_into_sublistsS  s    r  c                    s     fddt dt D S )z8
    Splits a list into sublists of maximum size k.
    c                    s   g | ]
}||   qS r%   r%   r  r   r  r%   r&   r   a  rh  zsplit_list.<locals>.<listcomp>r   )r   r*   )r  r   r%   r  r&   
split_list]  s    r  c                 C      ddi}t | trt|d}| |d< n	t|dj| d}|jr'td t| t||t|d}|  |j	d	krU|
 }|d
 rMtdjdi t  dS t|d  dS t|j tdjdi t  dS )Nstaterunning/instances/r  r  r  r  r  rQ   r  zstarting instance {id}.r  Tr  Fr%   r   r   r`  r   r^  r+   r   rP   rT   rU   rV   r  r4   r   r   r  rW   r   r  r%   r%   r&   start_instanced  (   




r  zID of instance to start/restartz"vastai start instance ID [OPTIONS]zStart a stopped instancea  
        This command attempts to bring an instance from the "stopped" state into the "running" state. This is subject to resource availability on the machine that the instance is located on.
        If your instance is stuck in the "scheduling" state for more than 30 seconds after running this, it likely means that the required resources on the machine to run your instance are currently unavailable.
        Examples: 
            vastai start instances $(vastai show instances -q)
            vastai start instance 329838
    c                 C   r  r:  N)r  r   r  r%   r%   r&   start__instance  s   r  zids of instance to startz/vastai start instances [OPTIONS] ID0 ID1 ID2...zStart a list of instancesc                    &   t  jd}t fdd|dd dS )z>
    for id in args.IDs:
        start_instance(id, args)
    @   c                    
   t |  S r    )r  r  r  r%   r&   r       
 z"start__instances.<locals>.<lambda>   r  Nr  r  r  r   idlistr%   r  r&   start__instances  s   r  c                 C   r  )Nr  stoppedr  r  r  r  r  r  rQ   r  zstopping instance {id}.r  Tr  Fr%   r  r  r%   r%   r&   stop_instance  r  r  zid of instance to stopz!vastai stop instance ID [OPTIONS]zStop a running instancea  
        This command brings an instance from the "running" state into the "stopped" state. When an instance is "stopped" all of your data on the instance is preserved, 
        and you can resume use of your instance by starting it again. Once stopped, starting an instance is subject to resource availability on the machine that the instance is located on.
        There are ways to move data off of a stopped instance, which are described here: https://vast.ai/docs/gpu-instances/data-movement
    c                 C   r  r  )r  r   r  r%   r%   r&   stop__instance     r  zids of instance to stopz.vastai stop instances [OPTIONS] ID0 ID1 ID2...zStop a list of instancesz
        Examples: 
            vastai stop instances $(vastai show instances -q)
            vastai stop instances 329838 984849
    c                    r  )z=
    for id in args.IDs:
        stop_instance(id, args)
    r  c                    r  r    )r  r  r  r%   r&   r    r  z!stop__instances.<locals>.<lambda>r  r  Nr  r  r%   r  r&   stop__instances  s   r  c                 C   sj   z&|  d\}}}|d}|d}|d}| | | }t|}|W S  ty4   td Y d S w )Nr   r   z5Invalid version string format. Expected format: X.X.X)r)   zfillr"   r   r+   )version_strmajorminorpatchnumeric_version_strr?   r%   r%   r&   rx    s   


rx  >	   r   r%  r  modelr  ru  r   contract_idlast_updatez/Search query in simple query syntax (see below)ri  )r  r,  r+  zEvastai search benchmarks [--help] [--api-key API_KEY] [--raw] <query>z/Search for benchmark results using custom querya  
        Query syntax:

            query = comparison comparison...
            comparison = field op value
            field = <name of a field>
            op = one of: <, <=, ==, !=, >=, >, in, notin
            value = <bool, int, float, string> | 'any' | [value0, value1, ...]
            bool: True, False

        note: to pass '>' and '<' on the command line, make sure to use quotes
        note: to encode a string query value (ie for gpu_name), replace any spaces ' ' with underscore '_'

        Examples:

            # search for benchmarks with score > 100 for llama2_70B model on 2 specific machines
            vastai search benchmarks 'score > 100.0  model=llama2_70B  machine_id in [302,402]'

        Available fields:

              Name                  Type       Description

            contract_id             int        ID of instance/contract reporting benchmark
            id                      int        benchmark unique ID
            image                   string     image used for benchmark
            last_update             float      date of benchmark
            machine_id              int        id of machine benchmarked
            model                   string     name of model used in benchmark
            name                    string     name of benchmark
            num_gpus                int        number of gpus used in benchmark
            score                   float      benchmark score result
    zsearch benchmarks)r  r  rR  r(  c              
   C   s   zi }| j durt| j |t}t|dg}W n ty. } ztd| W Y d}~dS d}~ww t| ddg|d}tj|t	d}|
  | }	 |S )	Creates a query based on search parameters as in the examples above.
    :param argparse.Namespace args: should supply all the command-line options
    Nr  Error: r7   z/benchmarksri  select_colsselect_filtersrO   )r   r  benchmarks_fieldsr   r   r+   r`  rR   rS   rP   rT   rV   r  displayable_fieldsr   r   r<  rW   r   r  r%   r%   r&   search__benchmarks  s"   *

r  >   r   whenrj  r  failedpaid_onserviceuser_idevent_idis_checkrefunded	is_credit
cut_amount
is_delayedcut_percentamount_centsr4  balance_afterstripe_chargestripe_payoutstripe_refundbalance_beforetransfer_grouporiginal_amountpayment_expectedzCvastai search invoices [--help] [--api-key API_KEY] [--raw] <query>av  
        Query syntax:

            query = comparison comparison...
            comparison = field op value
            field = <name of a field>
            op = one of: <, <=, ==, !=, >=, >, in, notin
            value = <bool, int, float, string> | 'any' | [value0, value1, ...]
            bool: True, False

        note: to pass '>' and '<' on the command line, make sure to use quotes
        note: to encode a string query value (ie for gpu_name), replace any spaces ' ' with underscore '_'

        Examples:

            # search for somewhat reliable single RTX 3090 instances, filter out any duplicates or offers that conflict with our existing stopped instances
            vastai search invoices 'amount_cents>3000  '

        Available fields:

      Name                  Type       Description

    id                  int,            
    user_id             int,            
    when                float,          utc epoch timestamp of initial invoice creation
    paid_on             float,          actual payment date (utc epoch timestamp )
    payment_expected    float,          expected payment date (utc epoch timestamp )
    amount_cents        int,            amount of payment in cents
    is_credit           bool,           is a credit purchase
    is_delayed          bool,           is not yet paid
    balance_before      float,          balance before
    balance_after       float,          balance after
    original_amount     int,            original amount of payment
    event_id            string,           
    cut_amount          int,               
    cut_percent         float,            
    extra               json,           
    service             string,         type of payment 
    stripe_charge       json,           
    stripe_refund       json,           
    stripe_payout       json,           
    error               json,           
    paypal_email        string,         email for paypal/wise payments
    transfer_group      string,         
    failed              bool,                   
    refunded            bool,                   
    is_check            bool,                   
    zsearch invoicesc              
   C   s   zi }| j durt| j |t}t|g d}W n ty/ } ztd| W Y d}~dS d}~ww t| ddg|d}tj|t	d}|
  | }	 |S )	r  N)r  r  r  r  r  r  r7   z	/invoicesri  r  rO   )r   r  invoices_fieldsr   r   r+   r`  rR   rS   rP   rT   rV   r  r  r  r%   r%   r&   search__invoicesi  s"   :

r  rQ  rc  zQShow 'on-demand', 'reserved', or 'bid'(interruptible) pricing. default: on-demand)r+  r  z--interruptiblerD  re  store_constzAlias for --type=bid)r  constr   r  z-bz--bidz
--reservedreservedzAlias for --type=reservedz--on-demandzAlias for --type=on-demandzDisable default queryz--newzNew search expz--disable-bundling
Deprecatedz	--storage      @z<Amount of storage to use for pricing, in GiB. default=5.0GiBzeQuery to search for. default: 'external=false rentable=true verified=true', pass -n to ignore defaultzAvastai search offers [--help] [--api-key API_KEY] [--raw] <query>z,Search for instance types using custom querya+  
        Query syntax:

            query = comparison comparison...
            comparison = field op value
            field = <name of a field>
            op = one of: <, <=, ==, !=, >=, >, in, notin
            value = <bool, int, float, string> | 'any' | [value0, value1, ...]
            bool: True, False

        note: to pass '>' and '<' on the command line, make sure to use quotes
        note: to encode a string query value (ie for gpu_name), replace any spaces ' ' with underscore '_'

        Examples:

            # search for somewhat reliable single RTX 3090 instances, filter out any duplicates or offers that conflict with our existing stopped instances
            vastai search offers 'reliability > 0.98 num_gpus=1 gpu_name=RTX_3090 rented=False'

            # search for datacenter gpus with minimal compute_cap and total_flops
            vastai search offers 'compute_cap > 610 total_flops > 5 datacenter=True'

            # search for reliable 4 gpu offers in Taiwan or Sweden
            vastai search offers 'reliability>0.99 num_gpus=4 geolocation in [TW,SE]'

            # search for reliable RTX 3090 or 4090 gpus NOT in China or Vietnam
            vastai search offers 'reliability>0.99 gpu_name in ["RTX 4090", "RTX 3090"] geolocation notin [CN,VN]'

            # search for machines with nvidia drivers 535.86.05 or greater (and various other options)
            vastai search offers 'disk_space>146 duration>24 gpu_ram>10 cuda_vers>=12.1 direct_port_count>=2 driver_version >= 535.86.05'

            # search for reliable machines with at least 4 gpus, unverified, order by num_gpus, allow conflicts
            vastai search offers 'reliability > 0.99  num_gpus>=4 verified=False rented=any' -o 'num_gpus-'

            # search for arm64 cpu architecture
            vastai search offers 'cpu_arch=arm64'
            
        Available fields:

              Name                  Type       Description

            bw_nvlink               float     bandwidth NVLink
            compute_cap:            int       cuda compute capability*100  (ie:  650 for 6.5, 700 for 7.0)
            cpu_arch                string    host machine cpu architecture (e.g. amd64, arm64)
            cpu_cores:              int       # virtual cpus
            cpu_ghz:                Float     # cpu clock speed GHZ
            cpu_cores_effective:    float     # virtual cpus you get
            cpu_ram:                float     system RAM in gigabytes
            cuda_vers:              float     machine max supported cuda version (based on driver version)
            datacenter:             bool      show only datacenter offers
            direct_port_count       int       open ports on host's router
            disk_bw:                float     disk read bandwidth, in MB/s
            disk_space:             float     disk storage space, in GB
            dlperf:                 float     DL-perf score  (see FAQ for explanation)
            dlperf_usd:             float     DL-perf/$
            dph:                    float     $/hour rental cost
            driver_version:         string    machine's nvidia/amd driver version as 3 digit string ex. "535.86.05,"
            duration:               float     max rental duration in days
            external:               bool      show external offers in addition to datacenter offers
            flops_usd:              float     TFLOPs/$
            geolocation:            string    Two letter country code. Works with operators =, !=, in, notin (e.g. geolocation not in ['XV','XZ'])
            gpu_arch                string    host machine gpu architecture (e.g. nvidia, amd)
            gpu_max_power           float     GPU power limit (watts)
            gpu_max_temp            float     GPU temp limit (C)
            gpu_mem_bw:             float     GPU memory bandwidth in GB/s
            gpu_name:               string    GPU model name (no quotes, replace spaces with underscores, ie: RTX_3090 rather than 'RTX 3090')
            gpu_ram:                float     per GPU RAM in GB
            gpu_total_ram:          float     total GPU RAM in GB
            gpu_frac:               float     Ratio of GPUs in the offer to gpus in the system
            gpu_display_active:     bool      True if the GPU has a display attached
            has_avx:                bool      CPU supports AVX instruction set.
            id:                     int       instance unique ID
            inet_down:              float     internet download speed in Mb/s
            inet_down_cost:         float     internet download bandwidth cost in $/GB
            inet_up:                float     internet upload speed in Mb/s
            inet_up_cost:           float     internet upload bandwidth cost in $/GB
            machine_id              int       machine id of instance
            min_bid:                float     current minimum bid price in $/hr for interruptible
            num_gpus:               int       # of GPUs
            pci_gen:                float     PCIE generation
            pcie_bw:                float     PCIE bandwidth (CPU to GPU)
            reliability:            float     machine reliability score (see FAQ for explanation)
            rentable:               bool      is the instance currently rentable
            rented:                 bool      allow/disallow duplicates and potential conflicts with existing stopped instances
            storage_cost:           float     storage cost in $/GB/month
            static_ip:              bool      is the IP addr static/stable
            total_flops:            float     total TFLOPs from all GPUs
            ubuntu_version          string    host machine ubuntu OS version
            verified:               bool      is the machine verified
            vms_enabled:            bool      is the machine a VM instance
    zsearch instancesc              
   C   s>  z| j ri }nddiddiddiddid}| jdur$t| j|ttt}g }| jdD ]8}| }|s5q,d}|}|d|krGd	}|d}|d
|krUd}|d
}|tv r]t| }|	||g q,||d< | j
|d< | jrxt| j|d< | j|d< |d dkrd|d< | jrd|d< W n ty } ztd| W Y d}~dS d}~ww | j}|}|rdg|d}t| d}	t }
| jrtd t| t| |	t|d}t }td||
  d n| jrtd t| t| d}	t| |	t|d}|  |jddkrtd|jd  dS | d }d |v r|d  }t| d! }|| }g }|D ]Q}d}d |v rE|d  durE|d  }|dkrT||krT|	| |d"krc||krc|	| |d#krr||v rr|	| |d$kr||vr|	| q1|}| jr|S | j
d%krt|t dS t|t  dS )&zCreates a query based on search parameters as in the examples above.

    :param argparse.Namespace args: should supply all the command-line options
    r`  TFr  Nrh  ra  r.  r  r  rb  rD  rf  rg  rd  re  disable_bundlingr  r7   ri  )r  rh  z/search/asks/r  r  zrequest took rT  z	/bundles/rw  rN   invalid return Content-Type: offersr@  r   r_  rd  rc  r  )!rz  r   r  r  r  r  rb  r)   r<   r   rD  rf  r"   storager  r   r+   newr`  r   r^  r   rP   r   rT   rS   rV   r   keysr  r  displayable_fields_reservedr  )r   r   rb  r%  ro  r   r<  new_search_eptr  rW   r  r   etimer  filter_q	filter_optargetnew_rowsr  r@  r%   r%   r&   search__offers  s   q












r  >   r   r@   r%  r  r  r  r  r  
creator_idr  r  default_tagrecommendedcount_createdr  recent_create_dater  zDvastai search templates [--help] [--api-key API_KEY] [--raw] <query>z.Search for template results using custom queryal  
        Query syntax:

            query = comparison comparison...
            comparison = field op value
            field = <name of a field>
            op = one of: <, <=, ==, !=, >=, >, in, notin
            value = <bool, int, float, string> | 'any' | [value0, value1, ...]
            bool: True, False

        note: to pass '>' and '<' on the command line, make sure to use quotes
        note: to encode a string query value (ie for gpu_name), replace any spaces ' ' with underscore '_'

        Examples:

            # search for somewhat reliable single RTX 3090 instances, filter out any duplicates or offers that conflict with our existing stopped instances
            vastai search templates 'count_created > 100  creator_id in [38382,48982]'

        Available fields:

      Name                  Type       Description

    creator_id              int        ID of creator
    created_at              float      time of initial template creation (UTC epoch timestamp)
    count_created           int        #instances created (popularity)
    default_tag             string     image default tag
    docker_login_repo       string     image docker repository
    id                      int        template unique ID
    image                   string     image used for template
    jup_direct              bool       supports jupyter direct
    hash_id                 string     unique hash ID of template
    name                    string     displayable name
    recent_create_date      float      last time of instance creation (UTC epoch timestamp)
    recommended_disk_space  float      min disk space required
    recommended             bool       is templated on our recommended list
    ssh_direct              bool       supports ssh direct
    tag                     string     image tag
    use_ssh                 bool       supports ssh (direct or proxy)    zsearch templatesc              
   C   s   zi }| j durt| j |t}t|ddg}W n ty/ } ztd| W Y d}~dS d}~ww t| ddg|d}t| |td	}|j	d
krQt|j
 |  dS d|jdv rn| dg }	 ttj|ddd dS t|j
 tdjdi t  dS )r  Nr  r  r  r7   r  ri  r  rO   rQ   rV   rw  	templatesTr  	sort_keysr  r%   )r   r  templates_fieldsr   r   r+   r`  r   rP   rU   r4   rT   rS   rV   r]  r  r  r   r  r  r%   r%   r&   search__templates  s,   0




r        ?z<Amount of storage to use for pricing, in GiB. default=1.0GiBz}Comma-separated list of fields to sort on. postfix field with - to sort desc. ex: -o 'disk_space,inet_up-'.  default='score-'zeQuery to search for. default: 'external=false verified=true disk_space>=1', pass -n to ignore defaultzBvastai search volumes [--help] [--api-key API_KEY] [--raw] <query>z+Search for volume offers using custom querya
  
        Query syntax:

            query = comparison comparison...
            comparison = field op value
            field = <name of a field>
            op = one of: <, <=, ==, !=, >=, >, in, notin
            value = <bool, int, float, string> | 'any' | [value0, value1, ...]
            bool: True, False

        note: to pass '>' and '<' on the command line, make sure to use quotes
        note: to encode a string query value (ie for gpu_name), replace any spaces ' ' with underscore '_'

        Examples:

            # search for volumes with greater than 50GB of available storage and greater than 500 Mb/s upload and download speed
            vastai search volumes "disk_space>50 inet_up>500 inet_down>500"
            
        Available fields:

              Name                  Type       Description

            cpu_arch:               string    host machine cpu architecture (e.g. amd64, arm64)
            cuda_vers:              float     machine max supported cuda version (based on driver version)
            datacenter:             bool      show only datacenter offers
            disk_bw:                float     disk read bandwidth, in MB/s
            disk_space:             float     disk storage space, in GB
            driver_version:         string    machine's nvidia/amd driver version as 3 digit string ex. "535.86.05"
            duration:               float     max rental duration in days
            geolocation:            string    Two letter country code. Works with operators =, !=, in, notin (e.g. geolocation not in ['XV','XZ'])
            gpu_arch:               string    host machine gpu architecture (e.g. nvidia, amd)
            gpu_name:               string    GPU model name (no quotes, replace spaces with underscores, ie: RTX_3090 rather than 'RTX 3090')
            has_avx:                bool      CPU supports AVX instruction set.
            id:                     int       volume offer unique ID
            inet_down:              float     internet download speed in Mb/s
            inet_up:                float     internet upload speed in Mb/s
            machine_id:             int       machine id of volume offer
            pci_gen:                float     PCIE generation
            pcie_bw:                float     PCIE bandwidth (CPU to GPU)
            reliability:            float     machine reliability score (see FAQ for explanation)
            storage_cost:           float     storage cost in $/GB/month
            static_ip:              bool      is the IP addr static/stable
            total_flops:            float     total TFLOPs from all GPUs
            ubuntu_version:         string    host machine ubuntu OS version
            verified:               bool      is the machine verified
    c              
   C     zv| j ri }nddiddiddid}| jd ur!t| j|ti t}g }| jdD ]8}| }|s2q)d}|}|d	|krDd
}|d	}|d|krRd}|d}|tv rZt| }|	||g q)||d< | j
rpt| j
|d< | j|d< W n ty } ztd| W Y d }~dS d }~ww |}| jrtd t| t| d}t| |t|d}	|	  |	jddkrtd|	jd  d S |	 d }
| jr|
S t|
t d S )Nr`  TFrY  r7   r  rC  r  rh  ra  r.  r  r  rb  rf  rg  r  r  z/volumes/search/r  rw  rN   r  r  )rz  r   r  vol_offers_fieldsr  rb  r)   r<   r  r   rf  r"   r  r   r+   r^  r`  r   rP   rT   rS   rV   r  r  vol_displayable_fieldsr   r   rb  r%  ro  r   r<  r  rW   r   r  r%   r%   r&   search__volumes  sX   8




r  zJvastai search network volumes [--help] [--api-key API_KEY] [--raw] <query>z3Search for network volume offers using custom querya  
        Query syntax:

            query = comparison comparison...
            comparison = field op value
            field = <name of a field>
            op = one of: <, <=, ==, !=, >=, >, in, notin
            value = <bool, int, float, string> | 'any' | [value0, value1, ...]
            bool: True, False

        note: to pass '>' and '<' on the command line, make sure to use quotes
        note: to encode a string query value (ie for gpu_name), replace any spaces ' ' with underscore '_'

        Examples:

            # search for volumes with greater than 50GB of available storage and greater than 500 Mb/s upload and download speed
            vastai search volumes "disk_space>50 inet_up>500 inet_down>500"
            
        Available fields:

              Name                  Type       Description
            duration:               float     max rental duration in days
            geolocation:            string    Two letter country code. Works with operators =, !=, in, notin (e.g. geolocation not in ['XV','XZ'])
            id:                     int       volume offer unique ID
            inet_down:              float     internet download speed in Mb/s
            inet_up:                float     internet upload speed in Mb/s
            reliability:            float     machine reliability score (see FAQ for explanation)
            storage_cost:           float     storage cost in $/GB/month
            verified:               bool      is the machine verified
    c              
   C   r  )Nr`  TFrY  r7   r  rh  ra  r.  r  r  rb  rf  rg  r  r  z/network_volumes/search/r  rw  rN   r  r  )rz  r   r  r  r  rb  r)   r<   r  r   rf  r"   r  r   r+   r^  r`  r   rP   rT   rS   rV   r  r  nw_vol_displayable_fieldsr  r%   r%   r&   search__network_volumes`  sX   (




r   new_api_keyz*Api key to set as currently logged in userzvastai set api-key APIKEYz3Set api-key (get your api-key from the console/CLI)c                 C   s|   t td}|| j W d   n1 sw   Y  tdt tjd}tj	|r<t
| td| dS dS )zCaution: a bad API key will make it impossible to connect to the servers.
    :param argparse.Namespace args: should supply all the command-line options
    rB  Nz!Your api key has been saved in {}rw   z%Your api key has been removed from {})r   APIKEY_FILEwriter  r+   r   r  r  
expanduserr  remove)r   writerAPIKEY_FILE_HOMEr%   r%   r&   set__api_key  s   	
r  z--filez#file path for params in json formatzvastai set user --file FILEzUpdate user data from json filea]  

    Available fields:

    Name                            Type       Description

    ssh_key                         string
    paypal_email                    string
    wise_email                      string
    email                           string
    normalized_email                string
    username                        string
    fullname                        string
    billaddress_line1               string
    billaddress_line2               string
    billaddress_city                string
    billaddress_zip                 string
    billaddress_country             string
    billaddress_taxinfo             string
    balance_threshold_enabled       string
    balance_threshold               string
    autobill_threshold              string
    phone_number                    string
    tfa_enabled                     bool
    c                 C   sn   d }t | jd}t|}W d    n1 sw   Y  t| d}tj|t|d}|  t	|   d S )Nr   r  r  )
r   r   rV   r   r`  rR   r3  rP   rT   r+   )r   paramsr   rW   r   r%   r%   r&   	set__user  s   
r
  zvastai ssh-url IDzssh url helperc                 C   
   t | dS )r:  zssh://_ssh_urlr  r%   r%   r&   ssh_url     
r  zvastai scp-url IDzscp url helperc                 C   r  )r:  zscp://r  r  r%   r%   r&   scp_url  r  r  c                    s  d }z%t td  d j dd}t|}W d    n1 s!w   Y  W n   Y d }d }|d ur<|d }|d }|d u sE|drt dd	d
i}t |}|  | d } jrj fdd|D \}	nt	|dkrvt
d dS |\}	|	di }
|
dd }d}z+|d ur|	d }t|d d }n|	d }d|	d v rt|	d d nt|	d }W n   d}Y |dkrt
| d| d|  nt
d z,t td  d j dd}t||d| W d    W d S 1 sw   Y  W d S    Y d S )Nrr   z/ssh_z.jsonr   ipaddrportz.vast.ai
/instancesr  r  r  c                    s   g | ]}|d   j kr|qS r  r  )r#   r   r  r%   r&   r   1  s    z_ssh_url.<locals>.<listcomp>r7   z Found multiple running instancesr  z22/tcpr   r  r   HostPortr  r  image_runtyper  zroot@r  zerror: ssh port not foundrB  )r  r  )r   DIRSr   rV   r   r8  r`  r   rT   r*   r+   rS   r"   rE  )r   protocoljson_objectopenfiler  r  r   r   r  r  r  port_22doutfiler%   r  r&   r    sZ   
(&r  zid of apikey to getzvastai show api-keyzShow an api-keyc                 C   r  r  )r`  r   r   r   rP   rT   r+   rV   r  r%   r%   r&   show__api_keyR  r  r  zvastai show api-keysz/List your api-keys associated with your accountc                 C   :   t | d}t| |td}|  | jr|S t|  d S )Nr5  rO   r`  r   rP   rT   r  r+   rV   r  r%   r%   r&   show__api_keys]     
r  z2vastai show audit-logs [--api-key API_KEY] [--raw]z.Display account's history of important actionsc                 C   s<   t | d}t| |}|  | }| jr|S t|t dS )
    Shows the history of ip address accesses to console.vast.ai endpoints

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/audit_logs/N)r`  r   rT   rV   r  r  audit_log_fieldsr   r   r   r  r%   r%   r&   show__audit_logsk  s   

r$  c                 C   s   |  ddu rd| d< ng d}|t| d  | d< |  ddu r&d| d< n#t| d }|dk r2dnd	}|d }|d
kr>dn|}| d| | d< |  ddu rVd| d< | S t| d d| d< | S )zV
    Mutates the job dict to replace None values with readable scheduling labels.
    r  NEveryday)SundayMondayTuesday	WednesdayThursdayFridaySaturdayr  z
Every hour   AMPMr   ro   r  zEvery minute02d)rS   r"   )jobr   r  suffixhour_12r%   r%   r&   normalize_schedule_fields  s    

r4  c                 C   s   dd | D S )z7
    Applies normalization to a list of job dicts.
    c                 S   r   r%   )r4  )r#   r1  r%   r%   r&   r     r   z"normalize_jobs.<locals>.<listcomp>r%   )jobsr%   r%   r&   normalize_jobs  s   r6  z6vastai show scheduled-jobs [--api-key API_KEY] [--raw]z"Display the list of scheduled jobsc                 C   sD   t | d}t| |}|  | }| jr|S t|}t|t dS )z
    Shows the list of scheduled jobs for the account.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    r!  N)r`  r   rT   rV   r  r6  r  scheduled_jobs_fieldsr#  r%   r%   r&   show__scheduled_jobs  s   

r8  zvastai show ssh-keysz/List your ssh keys associated with your accountc                 C   r  )NrI  rO   r  r  r%   r%   r&   show__ssh_keys  r   r9  z,vastai show workergroups [--api-key API_KEY]z#Display user's current workergroupsz0
        Example: vastai show workergroups 
    c                 C      t | d}d| jd}| jrtd t| t| |t|d}|  |jdkrL| }|d rD|d }| j	r8|S ttj
|d	d
d d S t|d  d S d S )Nri  r  r  r[  r  r  rQ   r  resultsr7   Tr  r  r`  r[  r^  r+   r   rP   rT   rU   rV   r  r]  r   rW   r  r   r  r  r%   r%   r&   show__workergroups      

r?  z)vastai show endpoints [--api-key API_KEY]z&Display user's current endpoint groupsz,
        Example: vastai show endpoints
    c                 C   r:  )Nr  r  r;  r  r  rQ   r  r<  r7   Tr  r  r=  r>  r%   r%   r&   show__endpoints  r@  rA  z3vastai show connections [--api-key API_KEY] [--raw]z Display user's cloud connectionsc                 C   sH   t | d}t| t| |td}|  | }| jr|S t|t dS )
    Shows the stats on the machine the user is renting.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/users/cloud_integrations/rO   N)	r`  r+   r   rP   rT   rV   r  r  connection_fieldsr#  r%   r%   r&   show__connections  s   
rD  zid of instance to get info forz vastai show deposit ID [options]z,Display reserve deposit info for an instancec                 C   sH   t | dj| jdddi}t| |}|  ttj| ddd dS )	z
    Shows reserve deposit info for an instance.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/instances/balance/{id}/r  r  r  r7   Tr  N)r`  r   r   r   rT   r+   rV   r]  )r   r   r   r%   r%   r&   show__deposit  s   
rE  z-qz--quietzonly display numeric idsz5start date and time for report. Many formats accepted-ez4end date and time for report. Many formats accepted z-mz--machine_idzMachine id (optional)zvastai show earnings [OPTIONS]z#Get machine earning history reportsc              
   C   s  d}d| }d| }d| }t   | }|d }|d }zddl}ddlm}	 W n ty5   td Y nw | jroz|jt| j}
|
 }t 	|

 }|| }W n tyn } ztd	t|  W Y d}~nd}~ww | jrz|jt| j}| }t 	|
 }|| }W n ty   td
t|  Y nw t| dd||| jd}t| |}|  | }ttj|ddd dS )z
    Show earnings history for a time range, optionally per machine. Various options available to limit time range and type of items.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    g      N@g      8@g     v@r  r   Nr   z3
WARNING: Missing dateutil, can't parse time format7Warning: Invalid end date format! Ignoring end date! 
 z;Warning: Invalid start date format! Ignoring start date! 
 z/users/me/machine-earningsr  )r  sdayedaymachidr7   Tr  )r   dateutilr   ImportErrorr+   r  parser]   	isoformatr   r   r   r-  r`  r   r   rT   rV   r]  )r   MinutesHoursDaysYearscdayrI  rJ  rL  r   r  end_date_txtr0  r<  r-  start_date_txtr/  r   r   r  r%   r%   r&   show__earnings&  sJ   
rW  c                 C   s*   d}| D ]}t ||d}||7 }q|S )Nr   )r   rS   )Xr   rb   r   r  r%   r%   r&   suma  s
   
rY  c                 C   s2   t  }| D ]}||d }|d ur|| q|S r    )r  rS   r#  )rX  r   Yr   r6   r%   r%   r&   selecth  s   
r[  z--show-valuesz(Show the values of environment variableszvastai show env-vars [-s]zShow user environment variablesc                 C   s   t | d}t| |td}|  | di }| jr+| js)dd | D }|S |S |s2t	d n#| D ]\}}t	d|  | jrLt	d|  nt	d	 t	d
 q6| js^t	d dS dS )z4Show the environment variables for the current user.rC  rO   secretsc                 S   s   i | ]\}}|d qS )z*****r%   r   r%   r%   r&   r     rn  z"show__env_vars.<locals>.<dictcomp>zNo environment variables found.zName: zValue: zValue: *****z---zI
Note: Values are hidden. Use --show-values or -s option to display them.N)
r`  r   rP   rT   rV   rS   r  show_valuesr   r+   )r   rW   r   env_varsmasked_env_varsr  r   r%   r%   r&   show__env_varsp  s(   


r`  z@start date and time for report. Many formats accepted (optional)z>end date and time for report. Many formats accepted (optional)z-cz--only_chargeszShow only charge items-pz--only_creditszShow only credit itemsz--instance_labelzLFilter charges on a particular instance label (useful for autoscaler groups)zvastai show invoices [OPTIONS]zGet billing history reportsc                 C   sz  t | \}}t| dd||| j d}t| |}|  | d }t| |}|d }|d }d}| jrt|d}t| d	}	| jt	|d
}
| j
rQtd t|
 t| |	t|
d}|  | d }t|d}g }|D ]}|dd}||v r}|| ql|}| d }| jr|D ]}|dd}|durt| qdS | jr|S t| t|t tdt|d  td| dS )a  
    Show current payments and charges. Various options available to limit time range and type
    of items. Default is to show everything for user's entire billing history.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/users/me/invoicesr  )r  sdateedateinc_chargesinvoicesr  header_textNr  z/contracts/fetch/)r  contract_idsr  r  	contractsr   currentzTotal: $r  z	Current: )r+  r`  only_creditsr   rT   rV   filter_invoice_itemsinstance_labelr[  r   r^  r+   r   rP   rS   r   quietr  r  invoice_fieldsrY  )r   rb  rc  r   r   r  invoice_filter_datafilter_headerrg  rW   r  r?   filtered_rowsrows2r  r   current_chargesr%   r%   r&   show__invoices  sV   






rt  zid of instance to getz0vastai show instance [--api-key API_KEY] [--raw]z Display user's current instancesc                 C   s|   t | dj| jdddi}t| |}|  | d }t |d  |d< dd	 |d
 D |d
< | jr6|S t|gt	 dS )rB  r  r  r  r  r  r-  r  c                 S      i | ]	}|d  |d qS r   r7   r%   r#   env_varr%   r%   r&   r     r   z"show__instance.<locals>.<dictcomp>	extra_envN)
r`  r   r   r   rT   rV   r   r  r  instance_fields)r   r   r   r  r%   r%   r&   show__instance  s   
r{  z;vastai show instances [OPTIONS] [--api-key API_KEY] [--raw]c                    s   t | dddi}t| |}|  | d }|D ] }dd | D }t |d  |d< d	d |d
 D |d
< qd v rG fdd|D S | jr_|D ]}|dd}|dur\t| qLdS | j	rd|S t
|t dS )rB  r  r  r  r  c                 S   r   r%   r   r   r%   r%   r&   r     r   z#show__instances.<locals>.<dictcomp>r-  r  c                 S   ru  rv  r%   rw  r%   r%   r&   r     r   ry  r   c                    s   g | ]
}t | d   qS )r   r   r#   r  r  r%   r&   r     rh  z#show__instances.<locals>.<listcomp>r   N)r`  r   rT   rV   r   r   rm  rS   r+   r  r  rz  )r   r  r   r   r  r  r   r%   r}  r&   r      s(   
r   z/vastai show ipaddrs [--api-key API_KEY] [--raw]z&Display user's history of ip addressesc                 C   F   t | dddi}t| |}|  | d }| jr|S t|t dS )r!  z/users/me/ipaddrsr  r  r<  N)r`  r   rT   rV   r  r  ipaddr_fieldsr#  r%   r%   r&   show__ipaddrs$     
r  zvastai show clustersz+Show clusters associated with your account.z9
        Show clusters associated with your account.
    c           
      C   s   t | d}t| |}|  | }| jr|S g }|d  D ]4\}}dd |d D }tdd |d D }||d t|d t|t|d	 |d
 d}	|	|	 qt
|tdd d S )Nz
/clusters/clustersc                 S   s   g | ]}|d  qS r   r%   r#   noder%   r%   r&   r   L  r   z"show__clusters.<locals>.<listcomp>nodesc                 s   s    | ]	}|d  r|V  qdS )is_cluster_managerNr%   r  r%   r%   r&   r'   N  s    z!show__clusters.<locals>.<genexpr>r  r   local_ip)r   r  r  r  r  r  Fr  )r`  r   rT   rV   r  r   nextr*   r]   r   r  cluster_fields)
r   r   r   rY   r  r  cluster_datar  manager_noderow_datar%   r%   r&   show__clusters:  s&   



	r  zvastai show overlaysz+Show overlays associated with your account.z9
        Show overlays associated with your account.
    c              	   C   s   t | d}t| |}|  | }| jr|S g }|D ]&}|d |d |d r+|d nd|d t|d t|d d}|| qt|t	d	d
 d S )Nr  r  r%  internal_subnetN/Ar  r  )r  r%  r  r  r  r  Fr  )
r`  r   rT   rV   r  r*   r]   r   r  overlay_fields)r   r   r   rY   r  overlayr  r%   r%   r&   show__overlays^  s"   



r  z%display subaccounts from current userz!vastai show subaccounts [OPTIONS]zGet current subaccountsc                 C   r~  )
    Shows stats for logged-in user. Does not show API key.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/subaccountsr  r  usersN)r`  r   rT   rV   r  r  user_fieldsr#  r%   r%   r&   show__subaccounts|  r  r  zvastai show memberszShow your team membersc                 C   r  )Nz/team/members/rO   r  r  r%   r%   r&   show__members     
r  zvastai show team-role NAMEzShow your team rolec                 C   sF   t | dj| jd}t| |td}|  ttj| ddd d S )Nr  r  rO   r7   Tr  )	r`  r   r:  r   rP   rT   r+   rV   r]  r  r%   r%   r&   show__team_role  s   r  zvastai show team-roleszShow roles for a teamc                 C   r  )Nz/team/roles-full/rO   r  r  r%   r%   r&   show__team_roles  r  r  zdisplay information about userzvastai show user [OPTIONS]zGet current user datazt
        Shows stats for logged-in user. These include user balance, email, and ssh key. Does not show API key.
    c                 C   sN   t | dddi}t| |}|  | }|d | jr|S t|gt dS )r  z/users/currentr  r  r[  N)r`  r   rT   rV   rw  r  r  r  )r   r   r   	user_blobr%   r%   r&   
show__user  s   

r  zUvolume type to display. Default to all. Possible values are "local", "all", "network"rT  zvastai show volumes [OPTIONS]zShow stats on owned volumes.z)
        Show stats on owned volumes
    c                 C   s   dddd}| | jd}t| dd|d}t| |}|  | d	 }g }|D ]}d
d | D }t |d  |d< || q)| j	rI|S t
|tdd d S )Nlocal_volumenetwork_volume
all_volume)r  networkrT  rT  z/volumesr  )r  rD  volumesc                 S   r   r%   r   r   r%   r%   r&   r     r   z!show__volumes.<locals>.<dictcomp>r-  r  Fr  )rS   rD  r`  r   rT   rV   r   r   r   r  r  volume_fields)r   typesrD  r   r   r  	processedr  r%   r%   r&   show__volumes  s"   

r  z.ID of cluster you want to remove machine from.r   z%ID of machine to remove from cluster.new_manager_idz?ID of machine to promote to manager. Must already be in clusterzGvastai remove-machine-from-cluster CLUSTER_ID MACHINE_ID NEW_MANAGER_IDzRemoves machine from clusterzcRemoves machine from cluster and also reassigns manager ID, 
    if we're removing the manager nodec                 C   sl   | j | jd}| jr| j|d< | jrtd| t| d}t| ||d}|  | jr,|S t|	 d  d S )N)r  r   r  r  z/cluster/remove_machine/r?  r  )
r  r   r  r^  r+   r`  r   rT   r  rV   r@  r%   r%   r&   remove_machine_from_cluster  s   


r  	recipientz"email (or id) of recipient accountz$dollars of credit to transfer z--skipzskip confirmation)r  r   r+  z'vastai transfer credit RECIPIENT AMOUNTz#Transfer credits to another accountzJ
        Transfer (amount) credits to account with email (recipient).
    c                 C   s   t | d}| js#td| j d| j d td}|  dkr#d S d| j| jd}| jr6td	 t| t	| |t
|d
}|  |jdkrk| }|d rctd| j d| j d|  d S t|d  d S t|j tdjdi t  d S )Nz/commands/transfer_credit/z
Transfer $z credit to account z?  This is irreversible.Continue? [y/n] rb   r  )senderr  r  r  r  rQ   r  zSent ra   r"  r  r  r%   )r`  skipr+   r  r  re   r<   rf   r^  r   rP   rT   rU   rV   r   r4   r  )r   rW   okr  r   r  r%   r%   r&   transfer__credit  s,   

(
r  zid of autoscale group to updateztemplate hash (**Note**: if you use this field, you can skip search_params, as they are automatically inferred from the template)ztemplate idzlaunch args  string for create instance  ex: "--onstart onstart_wget.sh  --env '-e ONSTART_PATH=https://s3.amazonaws.com/public.vast.ai/onstart_OOBA.sh' --image atinoda/text-generation-webui:default-nightly --disk 64"zLvastai update workergroup WORKERGROUP_ID --endpoint_id ENDPOINT_ID [options]z"Update an existing autoscale groupa  
        Example: vastai update workergroup 4242 --min_load 100 --target_util 0.9 --cold_mult 2.0 --search_params "gpu_ram>=23 num_gpus=2 gpu_name=RTX_4090 inet_down>200 direct_port_count>2 disk_space>=64" --launch_args "--onstart onstart_wget.sh  --env '-e ONSTART_PATH=https://s3.amazonaws.com/public.vast.ai/onstart_OOBA.sh' --image atinoda/text-generation-webui:default-nightly --disk 64" --gpu_ram 32.0 --endpoint_name "LLama" --endpoint_id 2
    c                 C   s"  | j }t| d| d}| jrd}nd}| jd ur| j| }d| j | j| j| j| j| j| j	| j
|| j| j| j| jd}| jrFtd t| t| |t|d}|  d	|jd
dv rztd|  W d S  tjjy   td t| t|j Y d S w td|jd
 t|j d S )Nri  r  rc   rj  r  )r  r   rk  rl  rm  rn  ro  rp  rq  rr  rs  rA  rt  ru  r  r  rN   rw  zworkergroup update {}rx  ry  )r   r`  rz  rr  rk  rl  rm  rn  ro  rp  rq  rs  rA  rt  ru  r^  r+   r   rP   rT   rS   r   rV   rR   r:  r|  r4   )r   r   rW   r   r  r   r%   r%   r&   update__workergroup>  s.   

:r  zid of endpoint group to updatez#vastai update endpoint ID [OPTIONS]z!Update an existing endpoint groupz{
        Example: vastai update endpoint 4242 --min_load 100 --target_util 0.9 --cold_mult 2.0 --endpoint_name "LLama"
    c              	   C   s   | j }t| d| d}d| j | j| j| j| j| j| jd}| jr)t	d t	| t
| |t|d}|  d|jdd	v rdzt	d
|  W d S  tjjyc   t	d t	| t	|j Y d S w t	d|jd t	|j d S )Nr  r  r  )r  r  rk  rl  rm  rn  r  rt  r  r  rN   rw  rc   zupdate endpoint {}rx  ry  )r   r`  rk  rl  rm  rn  r  rt  r^  r+   r   rP   rT   rS   r   rV   rR   r:  r|  r4   r  r%   r%   r&   update__endpointm  s$   $r  z#Environment variable name to updatezNew environment variable valuez$vastai update env-var <name> <value>z,Update an existing user environment variablec                 C   rB  )
z=Update an existing environment variable for the current user.rC  rD  r  r  r  z*Environment variable updated successfully.z'Failed to update environment variable: rE  N)	r`  r%  r   r   rP   rT   rV   rS   r+   rF  r%   r%   r&   update__env_var  rH  r  zid of instance to updatez.new template ID to associate with the instancez--template_hash_idz3new template hash ID to associate with the instanceznew image UUID for the instanceznew arguments for the instancez*new environment variables for the instancez#new onstart script for the instancez#vastai update instance ID [OPTIONS]z7Update recreate an instance from a new/updated templatezf
        Example: vastai update instance 1234 --template_hash_id 661d064bbda1f2a133816b6d55da07c3
    c                 C   s0  t | d| j d}d| ji}| jr| j|d< | jr| j|d< | jr'| j|d< | jr/| j|d< | jr7| j|d< | jr?| j|d	< | jrJt	d
 t	| t
| |t|d}|jdkr| }|drvt	d| j d t	d t	|d dS t	d| j d|d  dS t	d| j d|j d|j  dS )rw  z/instances/update_template/r  r   rq  r  r  r   r  r  r  r  rQ   r  	Instance z updated successfully.zUpdated instance details:updated_instancezFailed to update instance : r  z with error N)r`  r   rq  r  r  r   r  r  r^  r+   r   rP   rU   rV   rS   r4   )r   rW   r  r   rY   r%   r%   r&   update__instance  s4   








 $r  zid of the roler  z@vastai update team-role ID --name NAME --permissions PERMISSIONSzUpdate an existing team rolec                 C   sb   t | dj| jd}t| j}t| |t| j|dd}|  | j	r$|S t
tj| dd d S )Nr  r  r  r  r7   r  )r`  r   r   r   r6  r   rP   r%  rT   r  r+   rV   r]  r  r%   r%   r&   update__team_role  s   
r  HASH_IDzhash id of the templatezvastai update template HASH_IDzUpdate an existing templatea  
        Update a template

        Example: 
            vastai update template c81e7ab0e928a508510d1979346de10d --name "tgi-llama2-7B-quantized" --image "ghcr.io/huggingface/text-generation-inference:1.0.3" 
                                    --env "-p 3000:3000 -e MODEL_ARGS='--model-id TheBloke/Llama-2-7B-chat-GPTQ --quantize gptq'" 
                                    --onstart-cmd 'wget -O - https://raw.githubusercontent.com/vast-ai/vast-pyworker/main/scripts/launch_tgi.sh | bash' 
                                    --search_params "gpu_ram>=23 num_gpus=1 gpu_name=RTX_3090 inet_down>128 direct_port_count>3 disk_space>=192 driver_version>=535086005 rented=False" 
                                    --disk 8.0 --ssh --direct
    c              
   C   s  t | d}| jo
| j}| jo| j}| jp| j}| jrdn| jr!dnd}| jr1| jd}|d }nd }i }| jsGddidd	iddidd	id
}t| j|t	t
t}	i d| jd| jd| jd| jd| jd| jd| jd| jd|d|d| jd|d|d| jd|d|	d| j| j| j | j| j d}
|
}| jrtd t| t| |t|d}|  z |  }|d rtd t j!|d! d"d#  W d S td$ W d S  t"j#j$y } ztt%| t|j& W Y d }~d S d }~ww )%Nr  r  r2  r   r"  r   r`  TFr  r  r%  r  r@   r  r  r  r  r  r  r  r  r  r  r  r  r  )r  r  r  r  r  r  r  zupdated template: r  r7   r  ztemplate update failed)'r`  r  r  r2  r  r)   rz  r  rr  r  r  r  r  r%  r  r  r  r  r  r  r  r  r  r  r  r  r  r^  r+   r   rP   rT   rV   r]  rR   r:  r|  r]   rU   )r   rW   r  r  r  r  r  r  r  r  r  r  r   r  r<  r%   r%   r&   update__template  s   

	
"r  zid of the ssh key to updatezvalue of the ssh_keyz vastai update ssh-key id ssh_keyzUpdate an existing ssh keyc                 C   sJ   t | j}t| dj| jd}t| |td|id}|  t|	  d S )Nr  r  r5  r  )
r  r5  r`  r   r   r   rP   rT   r+   rV   )r   r5  rW   r   r%   r%   r&   update__ssh_key6  s
   
r  c              
   C   s  d}t   }t   d }d}d}dd l}ddlm} | jrOz|jt| j}| }t | }W n t	yN }	 zt
dt|	  W Y d }	~	nd }	~	ww | jrz|jt| j}
|
 }t |
 }W ||fS  t	y }	 zt
dt|	  W Y d }	~	||fS d }	~	ww ||fS )Nrc   iQ r   rG  rH  z9Warning: Invalid start date format! Ignoring end date! 
 )r   rL  r   r  rN  r]   rO  r   r   r   r+   r-  )r   selector_flagr0  r/  rV  rU  rL  r   r  r<  r-  r%   r%   r&   r+  C  s8   r+  c                    s  zddl }ddl m} W n ty   td Y nw 	 d}d dd}d}| jrLz|jt| j}| }t	|
  W n tyK   td Y nw | jrsz|jt| j}| }t	|
 W n tyr   td Y nw | jrd	}	d
}dd n| jrd}	d}dd nd}	dd | jr| jrd| d| d}
nd| d}
n| jrd| d}
nd}
|
d |	 }
tt fdd|}|rd| }|rd| }t }|jd |j d }ttdd t||||g}dd| d }||
|d S )!ak  This applies various filters to the invoice items. Currently it filters on start and end date and applies the
    'only_charge' and 'only_credits' options.invoice_number

    :param argparse.Namespace args: should supply all the command-line options
    :param List rows: The rows of items in the invoice

    :rtype List: Returns the filtered list of rows.

    r   NrG  a,  
WARNING: The 'vast_pdf' library is not present. This library is used to print invoices in PDF format. If
        you do not need this feature you can ignore this message. To get the library you should download the vast-python
        github repository. Just do 'git@github.com:vast-ai/vast-python.git' and then 'cd vast-python'. Once in that
        directory you can run 'vast.py' and it will have access to 'vast_pdf.py'. The library depends on a Python
        package called Borb to make the PDF files. To install this package do 'pip3 install borb'.
rc   l   c(	 z4Warning: Invalid end date format! Ignoring end date!z8Warning: Invalid start date format! Ignoring start date!zOnly showing charges.only_chargesc                 S      | d dkrdS dS )NrD  chargeTFr%   r  r%   r%   r&   type_filter_fn     z,filter_invoice_items.<locals>.type_filter_fnzOnly showing credits.rj  c                 S   r  )NrD  paymentTFr%   r  r%   r%   r&   r    r  c                 S   r   )NTr%   r  r%   r%   r&   r    r   zInvoice items after z and before r   zInvoice items before r"  c                    s8    | d pd  kokn  o| ot | d dkS )Nr   r~  r  r   r   r  r0  r/  r  r%   r&   r    s   8 z&filter_invoice_items.<locals>.<lambda>zS:zE:r-  r7   c                 S   s   | dkrdS dS )Nrc   FTr%   )fldr%   r%   r&   r    r  invoice_r.  z.pdf)r  rf  pdf_filename)rL  r   rM  r+   r  rN  r]   rO  r   r   r   r   r-  r  rj  r   rs  r   todayyearmonthr   )r   r  rL  r   r  rV  rU  r  r-  type_txtrf  r   invoice_numberpdf_filename_fieldsfilenamer%   r  r&   rk  `  s|   


rk  z*id of machine to cancel maintenance(s) forzvastai cancel maint idz[Host] Cancel maint windowz
        For deleting a machine's scheduled maintenance window(s), use this cancel maint command.    
        Example: vastai cancel maint 8207
    c                 C   s   t | dj| jd}td| j d td}|  dkr!dS d| jd	}| jr2td
 t| t| |t	|d}|
  t|j td| j d|  dS )rw  z/machines/{id}/cancel_maint/r  z7Cancelling scheduled maintenance window(s) for machine r   r  rb   Nr  )r  r   r  r  z3Cancel maintenance window(s) scheduled for machine  success)r`  r   r   r+   re   r<   rf   r^  r   rP   rT   r4   rV   )r   rW   r  r  r   r%   r%   r&   cancel__maint  s   
 r  c                 C   s   t | d| d}| jrtd t| |ti d}|jdkr?| }|d r2ttj| dd d S | jr7|S t|d	  d S t|j	 td
j
di t  d S )N
/machines/z	/cleanup/r  r  rQ   r  r7   r  r  r  r%   )r`  r^  r+   r   rP   rU   rV   r]  r  r4   r   r  )r   r   r   r   r  r%   r%   r&   cleanup_machine  s   

r  zid of machine to cleanupz#vastai cleanup machine ID [options]zN[Host] Remove all expired storage instances from the machine, freeing up spacea  
        Instances expire on their end date. Expired instances still pay storage fees, but can not start.
        Since hosts are still paid storage fees for expired instances, we do not auto delete them.
        Instead you can use this CLI/API function to delete all expired storage instances for a machine.
        This is useful if you are running low on storage, want to do maintenance, or are subsidizing storage, etc.
    c                 C   s   t | | j dS )rw  N)r  r   r  r%   r%   r&   cleanup__machine0  r  r  zid of machine to deletezvastai delete machine <id>z[Host] Delete machine if the machine is not being used by clients. host jobs on their own machines are disregarded and machine is force deleted.c                 C      t | dj| jd}t| |td}|jdkr1| }|d r)tdj| jd d	S t|d  d	S t|j tdjd
i t	  d	S )z
    Deletes machine if the machine is not in use by clients. Disregards host jobs on their own machines and force deletes a machine.
    z$/machines/{machine_id}/force_delete/r  rO   rQ   r  z<deleted machine_id ({machine_id}) and all related contracts.r  r  Nr%   )
r`  r   r   r   rP   rU   rV   r+   r4   r  r   r   r   r  r%   r%   r&   delete__machineC  s   	

r  c                 C   sf  t | d}|| j| j| j| j| j| jt| j| j	| j
| j| jd}| jr,td t| t| |t|d}|jdkr| }|d r| jd urKt| jnd}t| j}t| j}t| j}	t| j}
t| j	}t| j
}| jrp|S tdjdi t  |d	d
}|d
krtd| d| j  d S d S | jr|S t|d  d S t|j tdjdi t  d S )Nz/machines/create_asks/)r1  	price_gpu
price_diskprice_inetuprice_inetdprice_min_bid	min_chunkr  r  r  vol_size	vol_pricer  r  rQ   r  defzoffers created/updated for machine {id},  @ ${price_gpu_}/gpu/hr, ${price_inetu_}/GB up, ${price_inetd_}/GB down, {min_chunk_}/min gpus, max discount_rate {discount_rate_}, till {end_date_}, duration {duration_}extendedr   z	extended z client contracts to r  r  r%   )r`  r  r  r  r  r  r  r   r  ry  r  r  r  r^  r+   r   rP   rU   rV   r]   r  r   r  rS   r4   )r   r   r   r  r   r  
price_gpu_price_inetu_price_inetd_
min_chunk_	end_date_discount_rate_	duration_num_extendedr%   r%   r&   list_machineY  sP   








r  zid of machine to listz--price_gpuz<per gpu rental price in $/hour  (price for active instances)z--price_diskzSstorage price in $/GB/month (price for inactive instances), default: $0.10/GB/monthz-uz--price_inetuz+price for internet upload bandwidth in $/GBz--price_inetdz-price for internet download bandwidth in $/GBz--price_min_bidz)per gpu minimum bid price floor in $/hourz--discount_ratez:Max long term prepay discount rate fraction, default: 0.4 z--min_chunkzminimum amount of gpuszmcontract offer expiration - the available until date (optional, in unix float timestamp or MM/DD/YYYY format)z-lz
--durationzUpdates end_date daily to be duration from current date. Cannot be combined with end_date. Format is: `n days`, `n weeks`, `n months`, `n years`, or total intended duration in seconds.-vz
--vol_sizezpSize for volume contract offer. Defaults to half of available disk. Set 0 to not create a volume contract offer.z-zz--vol_pricezZPrice for disk on volume contract offer. Defaults to price_disk. Invalid if vol_size is 0.z vastai list machine ID [options]z[Host] list a machine for renta  
        Performs the same action as pressing the "LIST" button on the site https://cloud.vast.ai/host/machines.
        On the end date the listing will expire and your machine will unlist. However any existing client jobs will still remain until ended by their owners.
        Once you list your machine and it is rented, it is extremely important that you don't interfere with the machine in any way. 
        If your machine has an active client job and then goes offline, crashes, or has performance problems, this could permanently lower your reliability rating. 
        We strongly recommend you test the machine first and only list when ready.
    c                 C   s   t | | jS )rw  )r  r   r  r%   r%   r&   list__machine  s   r  zids of instance to listzJper gpu on-demand rental price in $/hour (base price for active instances)z"vastai list machines IDs [options]z[Host] list machines for renta*  
        This variant can be used to list or update the listings for multiple machines at once with the same args.
        You could extend the end dates of all your machines using a command combo like this:
        ./vast.py list machines $(./vast.py show machines -q) -e 12/31/2024 --retry 6
    c                    s    fdd j D S )r  c                    s   g | ]}t  |qS r%   )r  r#   r   r  r%   r&   r     rn  z"list__machines.<locals>.<listcomp>)r  rX  r  r%   r  r&   list__machines  s   r  machineszRids of machines to add disk to, that is networked to be on the same LAN as machiner  zmount path of disk to addz	--disk_idz7id of network disk to attach to machines in the clusterz5vastai add network-disk MACHINES MOUNT_PATH [options]z,[Host] Add Network Disk to Physical Cluster.a  
        This variant can be used to add a network disk to a physical cluster.
        When you add a network disk for the first time, you just need to specify the machine(s) and mount_path.
        When you add a network disk for the second time, you need to specify the disk_id.
        Example:
        vastai add network-disk 1 /mnt/disk1
        vastai add network-disk 1 /mnt/disk1 -d 12345
    c                 C   s   dd | j D | jd}| jd ur| j|d< t| d}| jr&td t| t| |t|d}|  | j	r7|S tdt
| d   d S )	Nc                 S   r   r%   r!   r  r%   r%   r&   r     r   z%add__network_disk.<locals>.<listcomp>)r  r  disk_id/network_disk/r  r  z,Attached network disk to machines. Disk id: )r  r  r  r`  r^  r+   r   rP   rT   r  r]   rV   r  r%   r%   r&   add__network_disk  s   


r  zvastai show network-disksz0Show network disks associated with your account.z>
        Show network disks associated with your account.
    c              	   C   s   t | d}t| |}|  | }| jr|S |d D ];}td|d   t|d tdd g }|d D ]}|||d	 	t
|d
d q5t  t|tdd td qd S )Nr  r  zCluster ID: r  network_disksFr  r  mountsr  )r   r  r   )r`  r   rT   rV   r  r+   r  network_disk_fieldsr   rS   r]   network_disk_machine_fields)r   r   r   rY   r  machine_rowsr   r%   r%   r&   show__network_disks  s(   


r  r  zid of network disk to listz=storage price in $/GB/month, default: $%(default).2f/GB/monthr   z~contract offer expiration - the available until date (optional, in unix float timestamp or MM/DD/YYYY format), default 1 monthzCsize of disk space allocated to offer in GB, default %(default)s GBz,vastai list network volume DISK_ID [options]z3[Host] list disk space for rent as a network volumec                 C   s|   | j | j| jd}| jrt| j|d< t| d}| jr#td t| t| |t	|d}|
  | jr4|S t| d  d S )N)r  r  r  r  r  r  r  r  )r  r  r  r  r   r`  r^  r+   r   rP   rT   r  rV   r  r%   r%   r&   list__network_volume  s   

r  z$id of network volume offer to unlistz%vastai unlist network volume OFFER_IDzUnlists network volume offerc                 C   s`   d| j i}t| d}| jrtd t| t| |t|d}|  | jr&|S t| d  d S )Nr   z/network_volumes/unlist/r  r  r  	r   r`  r^  r+   r   rP   rT   r  rV   r  r%   r%   r&   unlist__network_volume+  s   
r  皙?zcontract offer expiration - the available until date (optional, in unix float timestamp or MM/DD/YYYY format), default 3 monthsr  r+  zvastai list volume ID [options]z8[Host] list disk space for rent as a volume on a machinezP
        Allocates a section of disk on a machine to be used for volumes.  
    c                 C   s   t | jt | jt| jd}| jrt| j|d< t| d}| jr)t	d t	| t
| |t|d}|  | jr:|S t	d|  d S )Nr  r1  r  r  r  r  r  r  )r"   r  r   r   r  r  r   r`  r^  r+   r   rP   rT   r  r   rV   r  r%   r%   r&   list__volumeB  s   
r  zid of machines listz vastai list volume IDs [options]z7[Host] list disk space for rent as a volume on machineszO
        Allocates a section of disk on machines to be used for volumes.  
    c                 C   s   t | jdd | jD t| jd}| jrt| j|d< t| d}| jr,t	d t	| t
| |t|d}|  | jr=|S t	d|  d S )	Nc                 S   r   r%   r!   r  r%   r%   r&   r   t  r   z!list__volumes.<locals>.<listcomp>r  r  r  r  r  r  )r"   r  r  r   r  r  r   r`  r^  r+   r   rP   rT   r  r   rV   r  r%   r%   r&   list__volumese  s   
r  zvolume ID you want to unlistzvastai unlist volume IDz[Host] unlist volume offerc                 C   s\   | j }d|i}t| d}| jrtd| t| |t|}|  | jr$|S t| d  d S )Nr   z/volumes/unlistr  r  r  )r   r   r  rW   r   r%   r%   r&   unlist__volume  s   

r   z-id of machine to remove default instance fromzvastai remove defjob idz[Host] Delete default jobsc                 C   r  )zb


    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/machines/{machine_id}/defjob/r  rO   rQ   r  z2default instance for machine {machine_id} removed.r  r  Nr%   
r`  r   r   r   rP   rU   rV   r+   r4   r  r  r%   r%   r&   remove__defjob  s   

r  c                 C   s   t d dS )r:  z
set asks!
N)r+   r  r%   r%   r&   set_ask  s   r  z+id of machine to launch default instance onzper gpu rental price in $/hourz,list of arguments passed to container launchzvastai set defjob id [--api-key API_KEY] [--price_gpu PRICE_GPU] [--price_inetu PRICE_INETU] [--price_inetd PRICE_INETD] [--image IMAGE] [--args ...]z([Host] Create default jobs for a machinez
        Performs the same action as creating a background job at https://cloud.vast.ai/host/create.       
                    
    c                 C   s   t | d}| j| j| j| j| j| jd}| jrtd t| t	| |t
|d}|jdkrI| }|d rAtdjdi t  d
S t|d  d
S t|j td	jdi t  d
S )r:  z/machines/create_bids/)r1  r  r  r  r  r   r  r  rQ   r  zxbids created for machine {args.id},  @ ${args.price_gpu}/gpu/day, ${args.price_inetu}/GB up, ${args.price_inetd}/GB downr  r  Nr%   )r`  r   r  r  r  r  r   r^  r+   r   rP   rU   rV   r   r  r4   )r   r   r  r   r  r%   r%   r&   set__defjob  s   


r  c                 C   s   d}d}g }g }| D ]4}||kr|s|s| d| g }q
|dkr,| }| | q
|dkr9| }| | q
| | q
| d| |S )NFrc   r   rk  )r   r   )rT  charin_double_quotesin_single_quotesr/   ri  cr%   r%   r&   smart_split  s"   r	  c                 C   s*  i }| d u r|S t | d}d }|D ]}|d u r |dv r|}q	 q|dkr6t|tdr4d|d| < n\	 nZ|dkrd|d}t|d	krb|d
 }t|d	krXd|d
d  }|d||d < n.	 n,|dkrxt|tdrwd|d| < n|dkrt|tdrd|d| < n|||< d }q|S )Nr"  >   -hrF  rc  ra  r  ra  z0123456789:tcp/udprZ  z-p rF  ra  r  r7   z'"r   r  zBabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:./_z-v rc  z%abcdefghijklmnopqrstuvwxyz0123456789-z-n )r	  r  issubsetr)   r*   r   r<   )envsr?   r  prevr<  kvr   r%   r%   r&   r    sB   

r  c              
   C   s<   t dd| jd | j ddd | j D | j d S )Nz{}
{}
{}

{}z-----------START-----------r"  z
c                 s   s     | ]\}}d  ||V  qdS )z{}: {}N)r   r   r%   r%   r&   r'   5  rR  z$pretty_print_POST.<locals>.<genexpr>)r+   r   r   rW   r   rP   r   body)r   r%   r%   r&   pretty_print_POST1  s   
r  z&id of machine to set min bid price forzper gpu min bid price in $/hourz%vastai set min_bid id [--price PRICE]z5[Host] Set the minimum bid/rental price for a machinezF
        Change the current min bid price of machine id to PRICE.
    c                 C   sd   t | dj| jd}d| jd}| jrtd t| t| |t|d}|  td|	  dS )	r:  z/machines/{id}/minbid/r  r  r  r  r  zPer gpu min bid price changedN)
r`  r   r   r  r^  r+   r   rP   rT   rV   r  r%   r%   r&   set__min_bid:  s   r  z)id of machine to schedule maintenance forz--sdatez7maintenance start date in unix epoch time (UTC seconds)zmaintenance duration in hoursz--maintenance_categoryzF(optional) can be one of [power, internet, disk, gpu, software, other]znot providedzsvastai schedule maintenance id [--sdate START_DATE --duration DURATION --maintenance_category MAINTENANCE_CATEGORY]z%[Host] Schedule upcoming maint windowa  
        The proper way to perform maintenance on your machine is to wait until all active contracts have expired or the machine is vacant.
        For unplanned or unscheduled maintenance, use this schedule maint command. That will notify the client that you have to take the machine down and that they should save their work. 
        You can specify a date, duration, reason and category for the maintenance.         

        Example: vastai schedule maint 8207 --sdate 1677562671 --duration 0.5 --maintenance_category "power"
    c                 C   s   t | dj| jd}t| j}td| d| j d td td}|	 
 dkr.d	S d
t| j| j| j| jd}| jrGtd t| t| |t|d}|  td| d|  d	S )rw  z/machines/{id}/dnotify/r  z'Scheduling maintenance window starting z	 lasting z hoursz-This will notify all clients of this machine.r  rb   Nr  )r  rb  r  maintenance_reasonr  r  r  z!Maintenance window scheduled for r  )r`  r   r   r	   utcfromtimestamprb  r+   r  re   r<   rf   r   r  r  r^  r   rP   rT   rV   )r   rW   dtr  r  r   r%   r%   r&   schedule__maintS  s   r  r  zid of machine to displayz vastai show machine ID [OPTIONS]z[Host] Show hosted machinesc                 C   sz   t | d| j ddi}t| |}|  | }| jr|S | jr6dd |D }tddd |D  d	S t	|t
 d	S )
z
    Show a machine the host is offering for rent.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    r  r  r  c                 S      g | ]}|d   qS r  r%   r|  r%   r%   r&   r     rn  z!show__machine.<locals>.<listcomp>r"  c                 s       | ]}|V  qd S r    r%   r  r%   r%   r&   r'         z show__machine.<locals>.<genexpr>N)r`  r  r   rT   rV   r  rm  r+   r   r  machine_fieldsr   r   r   r  r  r%   r%   r&   show__machinex  s   
r  zvastai show machines [OPTIONS]c                 C   sv   t | dddi}t| |}|  | d }| jr|S | jr4dd |D }tddd	 |D  d
S t|t	 d
S )z
    Show the machines user is offering for rent.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z	/machinesr  r  r  c                 S   r  r  r%   r|  r%   r%   r&   r     rn  z"show__machines.<locals>.<listcomp>r"  c                 s   r  r    r%   r  r%   r%   r&   r'     r  z!show__machines.<locals>.<genexpr>N)
r`  r   rT   rV   r  rm  r+   r   r  r  r  r%   r%   r&   show__machines  s   
r  z-idszNcomma seperated string of machine_ids for which to get maintenance informationz7only display numeric ids of the machines in maintenancezp
vastai show maints -ids 'machine_id_1' [OPTIONS]
vastai show maints -ids 'machine_id_1, machine_id_2' [OPTIONS]z5[Host] Show maintenance information for host machinesc                 C   s   | j d}ttt|}t| dd|d}t| |}|  | }| j	r(|S | j
r@dd |D }tddd	 |D  d
S t|t d
S )z
    Show the maintenance information for the machines

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    rh  z/machines/maintenancesr  )r  r  c                 S   r  r  r%   r|  r%   r%   r&   r     rn  z show__maints.<locals>.<listcomp>r"  c                 s   r  r    r%   r  r%   r%   r&   r'     r  zshow__maints.<locals>.<genexpr>N)r  r)   r   r  r"   r`  r   rT   rV   r  rm  r+   r   r  maintenance_fields)r   r  r   r   r  r  r%   r%   r&   show__maints  s   
r  zid of machine to unlistzvastai unlist machine <id>z[Host] Unlist a listed machinec                 C   r  )z
    Removes machine from list of machines for rent.

    :param argparse.Namespace args: should supply all the command-line options
    :rtype:
    z/machines/{machine_id}/asks/r  rO   rQ   r  z>all offers for machine {machine_id} removed, machine delisted.r  r  Nr%   r  r  r%   r%   r&   unlist__machine  s   

r  c               	   c   sZ    t tjd} tj}| t_zdV  W |t_n|t_w W d   dS 1 s&w   Y  dS )a  
    A context manager to suppress standard output (stdout) within its block.

    This is useful for silencing output from functions or blocks of code that 
    print to stdout, especially when such output is not needed or should be 
    hidden from the user.

    Usage:
        with suppress_stdout():
            # Code block with suppressed stdout
            some_function_that_prints()

    Yields:
        None
    rB  N)r   r  devnullr,   r;   )r   
old_stdoutr%   r%   r&   suppress_stdout  s   "r"  c                 C   sv  d}t d|d D ]}za|jrSttjd5}t|! t| t| | W d   n1 s/w   Y  W d   n1 s>w   Y  W d   n1 sMw   Y  nt| | |jsftd|  d| d dd	iW   S  t	y } z|jstd
|  d|  W Y d}~nd}~ww ||k r|jstd| d| d t
d q	|jstd|  d| d ddd  S dS )a!  
    Silently destroys a specified instance, retrying up to three times if it fails.

    This function calls the `destroy_instance` function to terminate an instance.
    If the `args.raw` flag is set to True, the output of the destruction process
    is suppressed to keep the console output clean.

    Args:
        id (str): The ID of the instance to destroy.
        args (argparse.Namespace): Command-line arguments containing necessary flags.

    Returns:
        dict: A dictionary with a success status and error message, if any.
    r  r7   rB  Nr  z# destroyed successfully on attempt r   r  TzError destroying instance r  z#Retrying in 10 seconds... (Attempt r  )zFailed to destroy instance z after z
 attempts.FzMax retries exceeded)r  rj  )r   r  r   r  r   r   r   r  r+   r>   r   r   )r   r   r  attemptr   r<  r%   r%   r&   destroy_instance_silent  s:   "  
r%  c                 G   s   | j s	t|  dS dS )a.  
    Prints progress messages to the console based on the `raw` flag.

    This function ensures that progress messages are only printed when the `raw`
    output mode is not enabled. This is useful for controlling the verbosity of
    the script's output, especially in machine-readable formats.

    Args:
        args (argparse.Namespace): Parsed command-line arguments containing flags
                                  and options such as `raw`.
        *args_to_print: Variable length argument list of messages to print.

    Returns:
        None
    N)r  r+   r   args_to_printr%   r%   r&   progress_print*  s   r(  c                 G   s    | j r| jst|  dS dS dS )av  
    Prints debug messages to the console based on the `debugging` and `raw` flags.

    This function ensures that debug messages are only printed when debugging is
    enabled and the `raw` output mode is not active. It helps in providing detailed
    logs for troubleshooting without cluttering the standard output during normal
    operation.

    Args:
        args (argparse.Namespace): Parsed command-line arguments containing flags
                                  and options such as `debugging` and `raw`.
        *args_to_print: Variable length argument list of debug messages to print.

    Returns:
        None
    N)	debuggingr  r+   r&  r%   r%   r&   debug_print=  s   r*  c              
   C   s  t |dsd|_| sdS tj| ||j|jdd|jd}zt|}|s%W dS |dp.|d}|dv r6W dS W dS  tj	j
ye } z|jjdkrOW Y d }~dS |jrZt|d	|  W Y d }~dS d }~w ty } z|jrwt|d
|  W Y d }~dS d }~ww )Nr)  FT)r   r[  rW   r   r^  r  r)  intended_statusr  )	destroyed
terminatedofflinei  z,HTTPError when checking instance existence: zCNo instance found or Unexpected error checking instance existence: )hasattrr)  r   	NamespacerW   r   r{  rS   rR   r:  rk  rX   rU   r*  r>   )r  r[  r   	show_argsinstance_infor  r<  r%   r%   r&   instance_existQ  sD   
	r3  c                    s  t t jj t|}tdsd_ fdd}tj dddj	jd}|dkr<jr7t
d	| d
 t| t }	d}
t d}d}z|t |	 dk r||}jrft
d| d|  |dkrd}td| d|  t|| d}tdd}|| d| d| d W d   n1 sw   Y  d|fW |s|rt| |rt|| td| d|  td S z@jrt
d|  d| d tjd|  d| dddd}|jd kr|std! d}|j }jrt
d"| d# W n# tjjy( } zjrtd$|  d%}W Y d}~nd}~ww |r|d}fd&d'|D }|D ]}|d(krtd) td*d}|| d W d   n	1 saw   Y  td+ t|| d} W |s|rt| |rt|| td| d|  td d,S |d-r t| tdd}|| d| d| d W d   n	1 sw   Y  td.| d/ t|| d}d|f  W |s|rt| |rt|| td| d|  td S t| | q<d}
n|
d07 }
jr t
d1|
 d/ |d2kr|
d3krtdd}|| d| d4| d5 W d   n	1 sIw   Y  td6 t|| d}W |sm|rmt| |rmt|| td| d|  td d7S jrt
d8 td0 t |	 dk sTjrt
d9| d/ W |s|rt| |rt|| td| d|  td d:S |s|rt| |rt|| td| d|  td w );a  
    Executes machine testing by connecting to the specified IP and port, monitoring
    the instance's status, and handling test completion or failures.

    This function performs the following steps:
        1. Disables SSL warnings.
        2. Optionally delays the start of testing.
        3. Continuously checks the instance status and attempts to connect to the
           `/progress` endpoint to monitor test progress.
        4. Handles different response messages, such as completion or errors.
        5. Implements timeout logic to prevent indefinite waiting.
        6. Ensures instance cleanup in case of failures or completion.

    Args:
        ip_address (str): The public IP address of the instance to test.
        port (int): The port number to connect to for testing.
        instance_id (str): The ID of the instance being tested.
        machine_id (str): The machine ID associated with the instance.
        delay (int): The number of seconds to delay before starting the test.
        args (argparse.Namespace): Parsed command-line arguments containing flags
                                  and options such as `debugging` and `raw`.
        api_key (str, optional): API key for authentication. Defaults to None.

    Returns:
        tuple:
            - bool: `True` if the test was successful, `False` otherwise.
            - str: Reason for failure if the test was not successful, empty string otherwise.
    r)  Fc              
      s   t j| d dddjd}z1t|}jrtd|  |r$t|ts/jr,td W dS |d	d}|d
v r<|W S dW S  ty\ } zjrQtd|  W Y d}~dS d}~ww )z)Check instance status via show__instance.Fr   r   T)r   r^  r[  rW   r   r  r)  z/is_instance(): Output from vast show instance: z6is_instance(): No valid instance information received.unknownr  )r  r.  exitedcreatedzis_instance(): Error: N)	r   r0  r)  r{  r*  r   r   rS   r>   )r  r1  r2  r  r<  r[  r   r%   r&   is_instance  s2   	
z&run_machinetester.<locals>.is_instancer   r   )r[  rW   r   r^  r  	debbugingr   zSleeping for z seconds before starting tests.iX  r  	 status: r.  Instance offline during testingz went offline. TzError_testresults.logr  r  r"  r   Nz	Machine: z% Done with testing remote.py results r+  zSending GET request to https://z	/progresszhttps://r  )verifytimeoutrQ   z8Successfully established HTTPS connection to the server.zReceived message: 'r   zError making HTTPS request: rc   c                    s   g | ]}| vr|qS r%   r%   )r#   line)printed_linesr%   r&   r     rm  z%run_machinetester.<locals>.<listcomp>DONETest completed successfully.zPass_testresults.logzTest passed.)Trc   ERRORzTest failed with error: r   r  z8No message received. Incremented no_response_seconds to r  x   z No response from port z  for 120s with running instance
zNo response for 120s with running instance. This may indicate a misconfiguration of ports on the machine. Network error or system stall or crashed. )FzNo response for 120 seconds with running instance. The system might have crashed or stalled during stress test. Use the self-test machine function in vast cliz-Waiting for 20 seconds before the next check.z(Time limit reached. Destroying instance )Fz+Test did not complete within the time limit)urllib3disable_warningsr:  InsecureRequestWarningr"   r/  r)  r   r0  r  r*  r   r   r  r(  r%  r   r  r3  warningssimplefilterrR   rS   rU   r4   r<   r;  r)   r=   r#  )r   r  r  r   delayr   r[  r8  destroy_argsr  no_response_secondsfirst_connection_establishedinstance_destroyedr  reasonr  re  rX   r<  lines	new_linesr>  r%   )r[  r   r?  r&   run_machinetester|  s   


C







#









K

rQ  c              	   C   s0   | du rdS zt | W S  ttfy   Y dS w )z
    Convert value to float, returning 0 if value is None.
    
    Args:
        value: The value to convert to float
        
    Returns:
        float: The converted value, or 0 if value is None
    Nr   )r   r   r
  r   r%   r%   r&   
safe_float"  s   

rR  c                 C   s  g }t jd|  dddgdddddddd	d
|j||j|jd}z)t|}|jr.t|d| |sG|d|  d t	|d|  d d|fW S t
|dd d
d}|d }|jr]t|d| t|ddk rk|d t|ddkry|d t|ddkr|d t|ddkr|d t|d d!kr|d" t|d#d!kr|d$ t|d%d&kr|d' t|d(}t|d)}	|	|k r|d* |jrt|d+|	 d, t|d-| d, tt|d.}
tt|d/}|
d0| k r	|d1 |jrt|d2|
  t|d3|  |r<t	|d|  d4 |D ]}t	|d5|  q+d|fW S t	|d|  d6 d
g fW S  ty| } z&t	|d7t|  |jrht|d8|  dd9t| gfW  Y d}~S d}~ww ):a  
    Validates whether a machine meets the specified hardware and performance requirements.

    This function queries the machine's offers and checks various criteria such as CUDA
    version, reliability, port count, PCIe bandwidth, internet speeds, GPU RAM, system
    RAM, and CPU cores relative to the number of GPUs. If any of these requirements are
    not met, it records the reasons for the failure.

    Args:
        machine_id (str): The ID of the machine to check.
        api_key (str): API key for authentication with the VAST API.
        args (argparse.Namespace): Parsed command-line arguments containing flags
                                  and options such as `debugging` and `raw`.

    Returns:
        tuple:
            - bool: `True` if the machine meets all requirements, `False` otherwise.
            - list: A list of reasons why the machine does not meet the requirements.
    machine_id=verified=anyrentable=true
rented=anyrc  FNr  r`  T)r   rD  rm  rz  r  rf  r  r  rb  r  r^  r[  rW   r   z$Captured offers from search__offers:Machine ID  not found or not rentable.c                 S      |  ddS Nr  r   rS   r  r%   r%   r&   r  g  r  z$check_requirements.<locals>.<lambda>r  reverser   zTop offer found:rr  g'@zCUDA version < 11.8r  r  zReliability <= 0.90r  r   zDirect port count <= 3rz  g@zPCIe bandwidth <= 2.85r  r  zDownload speed <= 10 Mb/sr  zUpload speed <= 10 Mb/srA  r  zGPU RAM <= 7 GBrO  r  z#System RAM is less than total VRAM.z	CPU RAM: z MBzTotal GPU RAM: rG  ru  r  z:Number of CPU cores is less than twice the number of GPUs.zCPU Cores: zNumber of GPUs: z  does not meet the requirements:- z meets all the requirements.zAn unexpected error occurred: Exception details: zUnexpected error: )r   r0  r^  rW   r   r  r)  r*  r   r(  sortedrR  rS   r"   r>   r]   )r   r[  r   unmet_reasonssearch_argsr  sorted_offers	top_offerrO  r  rG  ru  rN  r<  r%   r%   r&   check_requirements3  s   











 re    c              
   C   s`  t |dsd|_t }tj| dd|j||j|j|jd}|jr&t|d|  t | |k r!zt	|}|sFt
|d|  d t| W q&|dd	}	|	rd
|	v rd|  d|	  }
t
||
 t| ||rvt| | t
|d|  d n	t
|d|  d d|
fW S |dd}|dkrd}
t
||
 t| ||rt| | t
|d|  d n	t
|d|  d d|
fW S |ddkr|dkr|jrt|d|  d |dfW S t
|d|  d| d t| W n2 ty } z%t
|d|  d| d |jr	t|dt|  t| W Y d}~nd}~ww t | |k s/d| d}
t
||
 d|
fS )z]
    Waits for an instance to reach a running state and monitors its status for errors.

    r)  FT)r   rm  r  r^  r[  rW   r   r)  z#Starting wait_for_instance with ID:z%No information returned for instance z. Retrying...
status_msgrc   Errorr  z encountered an error: z! has been destroyed due to error.z* could not be destroyed or does not exist.r  r4  r.  r;  z) has been destroyed due to being offline.r+  r  z is now running.Nr:  z!... waiting for 'running' status.z#Error retrieving instance info for r  r_  z'Instance did not become running within zV seconds. Verify network configuration. Use the self-test machine function in vast cli)r/  r)  r   r   r0  r^  rW   r   r*  r{  r(  r   rS   r<   r3  r%  r>   r]   )r  r[  r   rJ  r=  intervalr  r1  r2  rg  rN  r  r<  r%   r%   r&   wait_for_instance  sr   








9
rj  r  z--debuggingzEnable debugging output	--explainzIOutput verbose explanation of mapping of CLI calls to HTTPS API endpoints--rawzOutput machine-readable JSON--urlzServer REST API URL--retryzRetry limitz--ignore-requirementszGIgnore the minimum system requirements and run the self test regardlesszvastai self-test machine <machine_id> [--debugging] [--explain] [--api_key API_KEY] [--url URL] [--retry RETRY] [--raw] [--ignore-requirements]z3[Host] Perform a self-test on the specified machineam  
        This command tests if a machine meets specific requirements and 
        runs a series of tests to ensure it's functioning correctly.

        Examples:
         vast self-test machine 12345
         vast self-test machine 12345 --debugging
         vast self-test machine 12345 --explain
         vast self-test machine 12345 --api_key <YOUR_API_KEY>
    c                    s  d}ddd}t dsd_zzjsHtjd}tj|r?t|d}| 	 _W d   n1 s9w   Y  n	t
d d	|d
< j  sQtdtj jjdjjd}tj \}}|sƈjst
dj d |D ]
}t
d|  qzd||d
< |W W z|rt| |rt|| W S W S W S  ty }	 zjrtd|	  W Y d}	~	S W Y d}	~	S d}	~	ww |sjrt
dj d |D ]}t
d|  t
d qdd }
 fdd}|j}|s	t
dj  d|d
< n|d }|d }|
|}tjdYi 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d,dd-dd.dd/d0d1dd2dd3dd4dd5d(d6jd7 d8jd9jdjd:dd;dd<d}zmt
d=|  t|}t|tjr|jd>krz| }jrtd?| W nA tjy }	 zt
d@|	  tdA|j   tdBd}	~	ww t
dC|j  tdD|j   tdE|j tdFW n] tyI }	 zPt
dG|	  dH|d
< |W  Y d}	~	W W z|rt| |rt|| W S W S W S  tyD }	 zjr:td|	  W Y d}	~	S W Y d}	~	S d}	~	ww d}	~	ww |!dI}|s\t
dJ dK|d
< nVt"| |\}}|sm||d
< nE|!dL}|szdM|d
< n8|!dNi !dOg }|r|dP !dQnd}|sdR|d
< ndS}t#||t$|j| dT\}}||dU< ||d
< W n ty }	 zd|dU< t$|	|d
< W Y d}	~	nd}	~	ww W z|rt| |rt|| W nZ ty }	 zjrtd|	  W Y d}	~	n@d}	~	ww z|rt| |rt|| W w W w W w  ty= }	 zjr3td|	  W Y d}	~	w W Y d}	~	w d}	~	ww jrPt%t&| t'(dP dS |dU r`t%dV t'(dP dS t%dW|d
   t'(dX dS )Zz
    Performs a self-test on the specified machine to verify its compliance with
    required specifications and functionality.
    NFrc   )r  rN  r)  rw   r   zJNo API key found. Please set it using 'vast set api-key YOUR_API_KEY_HERE'zAPI key not found.rN  zAPI key is missing.)r[  rW   r   r^  r  r)  rW  z* does not meet the following requirements:r^  z; zError during cleanup: zKContinuing despite unmet requirements because --ignore-requirements is set.c                 S   s   d}t | trt| } dddddd}| |v r | d||   S t| }t|d	 d
}|tdd | D kr]t|}||v rI| d||  S t|d	 d
}|tdd | D ks8td|  d)zz
            Maps a CUDA version to a Docker image tag, falling back to the next lower version until failure.
            zvastai/testcu118cu121cu124cu126cu128)z11.8z12.1z12.4z12.6z12.8z:self-test-r  r7   c                 s   r   r    r  )r#   r6   r%   r%   r&   r'   m  r(   z@self_test__machine.<locals>.cuda_map_to_image.<locals>.<genexpr>zNo CUDA version found for z or any lower version)r   r   r]   rz  rl  r  KeyError)cuda_versiondocker_repodocker_tag_map
cuda_floatnext_versionnext_version_strr%   r%   r&   cuda_map_to_imageS  s(   
z-self_test__machine.<locals>.cuda_map_to_imagec                    s   t jd i dd|  dddgdddd	d
d	dd	dd dd	dddddddjd djdjdjdj}t|}|sStd|  d d S t	|dd dd}|rb|d S d S )!Nr   rS  rT  rU  rV  rD  rc  rm  Frz  r  rf  r  r  r  rb  r`  r  Tr^  r[  rW   r   r   r)  rW  rX  c                 S   rY  rZ  r[  r  r%   r%   r&   r    r  zGself_test__machine.<locals>.search_offers_and_get_top.<locals>.<lambda>r\  r   r%   )
r   r0  r^  rW   r   r   r)  r  r(  r`  )r   rb  r  rc  r7  r%   r&   search_offers_and_get_topv  sN   
	
z5self_test__machine.<locals>.search_offers_and_get_topz%No valid offers found for Machine ID zNo valid offers found.r   rr  r6  r  r  (   r  r  r  r  r  z/verification/remote.shr  r2  r  Tr  r  r  r  r  r  r  z0-e TZ=PDT -e XNAME=XX4 -p 5000:5000 -p 1234:1234r   r  r  rp  r  r^  r[  rW   r   r  r  r  zStarting test with rQ   z-Captured instance_info from create__instance:zError parsing JSON response: zRaw response content: z5Failed to parse JSON from instance creation response.z%HTTP error during instance creation: zResponse text: z%Instance creation failed with status z/Unexpected response type from create__instance.zError creating instance: zjFailed to create instance. Check the docker configuration. Use the self-test machine function in vast cli ri  z:Instance creation response did not contain 'new_contract'.zInstance creation failed.r  z%Failed to retrieve public IP address.r  z5000/tcpr   r  zFailed to retrieve mapped port.15rc  r  rA  zTest failed: r7   r%   ))r/  r)  r[  r  r  r  r  r   r  r<   r(  r>   r   r0  rW   r   r  re  r   ignore_requirementsr   r3  r%  r*  r^  r  r   rR   ResponserU   rV   r|  r4   rS   rj  rQ  r]   r+   r]  r,   rg   )r   r  r?   api_key_filer  rJ  meets_requirementsra  rN  r<  r{  r|  rd  ask_contract_idru  docker_imagecreate_argsrX   r2  wait_reasonr   port_mappingsr  rI  r  r%   r7  r&   self_test__machine  s  




 . 
#

	
 $$









r  z


login via the command line is no longer supported.
go to https://console.vast.ai/cli in a web browser to get your api key, then run:

    vast set api-key YOUR_API_KEY_HERE
c                	       s:   e Zd Zdee dedee dee f fddZ  ZS )MyAutocompletecompletionscword_prequotelast_wordbreak_posr   c                    s    t  |||}t|dd dS )Nc                 S   s
   |  dS )Nr.  )r=   r  r%   r%   r&   r  )  r  z2MyAutocomplete.quote_completions.<locals>.<lambda>)r  )rM  quote_completionsr`  )r   r  r  r  prerO  r%   r&   r  &  s   z MyAutocomplete.quote_completions)	r{   r|   r}   r   r]   r   r"   r  rQ  r%   r%   rO  r&   r  %  s    2r  c                  C   s  t jddtd t jdddd t jddd	d
 t jdddd
 t jdddd
 t jddttdtdtd t jdddt	d t 
  a} | jtu r| jrWtdt  tjtr| jrgtdt  ttd}|  | _W d    n1 s~w   Y  nd | _| jrd| j td< | jstrzt rt  W n ty } ztd|  W Y d }~nd }~ww trt }|t j  z2| | }| jrzttj|ddd  W n   ttj| ddd  Y t d! t | W d S  t!j"j#y6 } z3z
|j$ %d"}W n t&y   |j$j'd#krd$}nd%}Y nw td&jd'i t(  W Y d }~d S d }~w t)yM } zt| W Y d }~d S d }~ww )(Nrm  zserver REST api urlr  rn  zretry limitr   rl  r  zoutput machine-readable jsonr  rk  zIoutput verbose explanation of mapping of CLI calls to HTTPS API endpointsz--curlz#show a curl equivalency to the callz	--api-keyz/api key. defaults to using the one stored in {}FVAST_API_KEY)r  rD  rY  r+  z	--versionzshow versionr   )r  r   r   z	checking zreading key from r   ra  rb  zError checking for update: r7   Tr  r   r  r(  zPlease log in or sign upz(no detail message supplied)z4failed with error {e.response.status_code}: {errmsg}r%   )*r   r  r.  r   r  r]   r  rX  api_key_guardVERSIONrF  r   r[  r^  r+   r  r  r   r  r<   rP   r  should_check_for_updaterF   rp   r>   TABCOMPLETEr  r	  rV   r]  r,   rg   rR   r:  rk  rX   rS   r|  rU   r  r   )r   r  r<  myautoccrX  errmsgr%   r%   r&   main.  sr   "




$r  __main__)NN)NNNNr    )T)F)r  r  )rf  r  (N  
__future__r   r   r   rV   r,   r   r  r   typingr   r   r   r   r	   r   r
   r   hashlibr  	threadingconcurrent.futuresr   rR   getpassr9   r   r   rD  atexit
contextlibr   r   ior   shutilloggingtextwrappathlibr   rG  importlib.metadatarC   rH   r  r   r  argcompleter   rM  urllibr   urllib.parser|  AttributeErrorr   	raw_inputre   	NameErrorrX  r.  basicConfigWARNr]   r.   r"   r0   rA   rE   rF   rJ   rK   r   rZ   r`   rp   APP_NAMEr  xdgxdg_config_homexdg_cache_homer  r  r   r  r  r  makedirsr=  r?  r  r  r  copyfileobjectr  rP   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  RawTextHelpFormatterr
  r   rX  r0  r`  rd  rn  r  r  r  r  r  rz  r  r  r  r  r  r  r  r  r"  r7  rn  r  rC  r?  r  r  r  r  r   rD  r  r>   r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r.  r=  rA  rG  rM  rJ  r}  r  r  r  r  SUPPRESS	REMAINDERr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r2  r4  r7  r8  r9  r;  r<  rH  rS  rW  rX  rq  rv  r{  r|  r}  r~  r  r  r  r  r  r  r  r  r  r  r  r  rx  r  r  r  r  r  r  r  r  r   r  r
  r  r  r  r  r  r$  r4  r6  r8  r9  r?  rA  rD  rE  rW  rY  r[  r`  rt  r{  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  loadsr  r  r  r  r+  rk  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r	  r  r  r  r  r  r  r  r  r"  r%  r(  r*  r3  rQ  rR  re  rj  r  login_deprecated_messageCompletionFinderr  r  r{   KeyboardInterruptBrokenPipeErrorr%   r%   r%   r&   <module>   s  
	
""	#


	o , 			
	 <
 v+""#H6#V/0q A?$
8



		
		'
 
 			 ;k%
	



 &

06    
Zk
r
&,7:'9		9
	3
F

	
'< 	3






,		-+ ' U o	 ;