Ë
    Q^(h×D  ã                   óT  — d 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	m
Z
mZmZmZmZmZmZ ddlmZmZmZmZ d	d
lmZ d	dlmZ 	 ddlmZ ddlmZ ddlmZ dZ ed   Z"dedefd„Z#dZ$ G d„ de«      Z%d.dedee"   fd„Z&e#	 d.dedee'   dee"   dee'   fd„«       Z(e#d/de'de)de)fd „«       Z*	 d.d!ee   dee'   dee"   defd"„Z+	 d.dedee'   dee"   dee'   fd#„Z,d/de'de)de)fd$„Z-ded%ee'   de'fd&„Z.d'e'dee'   fd(„Z/d)e$› d*e$› d+�ja                  «       Z1d,ede
fd-„Z2y# e!$ r dZ Y ŒÌw xY w)0as  Contains command to delete some revisions from the HF cache directory.

Usage:
    huggingface-cli delete-cache
    huggingface-cli delete-cache --disable-tui
    huggingface-cli delete-cache --dir ~/.cache/huggingface/hub
    huggingface-cli delete-cache --sort=size

NOTE:
    This command is based on `InquirerPy` to build the multiselect menu in the terminal.
    This dependency has to be installed with `pip install huggingface_hub[cli]`. Since
    we want to avoid as much as possible cross-platform issues, I chose a library that
    is built on top of `python-prompt-toolkit` which seems to be a reference in terminal
    GUI (actively maintained on both Unix and Windows, 7.9k stars).

    For the moment, the TUI feature is in beta.

    See:
    - https://github.com/kazhala/InquirerPy
    - https://inquirerpy.readthedocs.io/en/latest/
    - https://github.com/prompt-toolkit/python-prompt-toolkit

    Other solutions could have been:
    - `simple_term_menu`: would be good as well for our use case but some issues suggest
      that Windows is less supported.
      See: https://github.com/IngoMeyer441/simple-term-menu
    - `PyInquirer`: very similar to `InquirerPy` but older and not maintained anymore.
      In particular, no support of Python3.10.
      See: https://github.com/CITGuru/PyInquirer
    - `pick` (or `pickpack`): easy to use and flexible but built on top of Python's
      standard library `curses` that is specific to Unix (not implemented on Windows).
      See https://github.com/wong2/pick and https://github.com/anafvana/pickpack.
    - `inquirer`: lot of traction (700 stars) but explicitly states "experimental
      support of Windows". Not built on top of `python-prompt-toolkit`.
      See https://github.com/magmax/python-inquirer

TODO: add support for `huggingface-cli delete-cache aaaaaa bbbbbb cccccc (...)` ?
TODO: add "--keep-last" arg to delete revisions that are not on `main` ref
TODO: add "--filter" arg to filter repositories by name ?
TODO: add "--limit" arg to limit to X repos ?
TODO: add "-y" arg for immediate deletion ?
See discussions in https://github.com/huggingface/huggingface_hub/issues/1025.
é    N)Ú	NamespaceÚ_SubParsersAction©Úwraps)Úmkstemp)ÚAnyÚCallableÚIterableÚListÚLiteralÚOptionalÚUnioné   )ÚCachedRepoInfoÚCachedRevisionInfoÚHFCacheInfoÚscan_cache_diré   )ÚBaseHuggingfaceCLICommand)ÚANSI)Úinquirer)ÚChoice)Ú	SeparatorTF©ÚalphabeticalÚlastUpdatedÚlastUsedÚsizeÚfnÚreturnc                 ó.   ‡ — t        ‰ «      ˆ fd„«       }|S )z4Decorator to flag methods that require `InquirerPy`.c                  ó6   •— t         st        d«      ‚ ‰| i |¤ŽS )NzÂThe `delete-cache` command requires extra dependencies to work with the TUI.
Please run `pip install huggingface_hub[cli]` to install them.
Otherwise, disable TUI using the `--disable-tui` flag.)Ú_inquirer_py_availableÚImportError)ÚargsÚkwargsr   s     €úc/var/www/skyplay_api_hub/venv/lib/python3.12/site-packages/huggingface_hub/commands/delete_cache.pyÚ_innerz#require_inquirer_py.<locals>._innerV   s+   ø€ å%ÜðQóð ñ �4Ð"˜6Ñ"Ð"ó    r   )r   r(   s   ` r'   Úrequire_inquirer_pyr*   R   s"   ø€ ô ˆ2ƒYó#ó ð#ð €Mr)   ÚCANCEL_DELETIONc                   ó8   — e Zd Zedefd„«       Zdeddfd„Zd„ Zy)ÚDeleteCacheCommandÚparserc                 óÞ   — | j                  dd¬«      }|j                  dt        d d¬«       |j                  ddd	¬
«       |j                  ddg d¢d¬«       |j                  t        ¬«       y )Nzdelete-cachez*Delete revisions from the cache directory.)Úhelpz--dirzEcache directory (optional). Default to the default HuggingFace cache.)ÚtypeÚdefaultr0   z--disable-tuiÚ
store_truezrDisable Terminal User Interface (TUI) mode. Useful if your platform/terminal doesn't support the multiselect menu.)Úactionr0   z--sortú?r   z¡Sort repositories by the specified criteria. Options: 'alphabetical' (A-Z), 'lastUpdated' (newest first), 'lastUsed' (most recent first), 'size' (largest first).)ÚnargsÚchoicesr0   )Úfunc)Ú
add_parserÚadd_argumentÚstrÚset_defaultsr-   )r.   Údelete_cache_parsers     r'   Úregister_subcommandz&DeleteCacheCommand.register_subcommandi   s�   € à$×/Ñ/°ÐEqÐ/ÓrÐà×(Ñ(ØÜØØXð	 	)ô 	
ð 	×(Ñ(ØØðKð	 	)ô 	
ð 	×(Ñ(ØØÚGð*ð 	)ô 	
ð 	×(Ñ(Ô.@Ð(ÕAr)   r%   r    Nc                 ój   — |j                   | _        |j                  | _        |j                  | _        y ©N)ÚdirÚ	cache_dirÚdisable_tuiÚsortÚsort_by)Úselfr%   s     r'   Ú__init__zDeleteCacheCommand.__init__Œ   s&   € Ø(,¯©ˆŒØ!%×!1Ñ!1ˆÔØ26·)±)ˆ�r)   c           	      ó2  — t        | j                  «      }| j                  rt        |g | j                  ¬«      }nt        |g | j                  ¬«      }t        |«      dkD  r¬t        |vr¤t        ||«      dz   }| j                  rt        |«      }nt        |«      }|rp |j                  |Ž }t        d«       |j                  «        t        dt        |j                  «      › dt        |j                  «      › d|j                   › d�«       y	t        d
«       y	)z/Run `delete-cache` command with or without TUI.)ÚpreselectedrE   r   z Confirm deletion ?zStart deletion.zDone. Deleted z repo(s) and z revision(s) for a total of ú.Nz"Deletion is cancelled. Do nothing.)r   rB   rC   Ú_manual_review_no_tuirE   Ú_manual_review_tuiÚlenÚ_CANCEL_DELETION_STRÚ_get_expectations_strÚ_ask_for_confirmation_no_tuiÚ_ask_for_confirmation_tuiÚdelete_revisionsÚprintÚexecuteÚreposÚ	snapshotsÚexpected_freed_size_str)rF   Úhf_cache_infoÚselected_hashesÚconfirm_messageÚ	confirmedÚstrategys         r'   ÚrunzDeleteCacheCommand.run‘   s  € ô ' t§~¡~Ó6ˆð ×ÒÜ3°MÈrÐ[_×[gÑ[gÔh‰Oä0°ÈBÐX\×XdÑXdÔeˆOô ˆÓ !Ò#Ô(<ÀOÑ(SÜ3°MÀ?ÓSÐVkÑkˆOð ×ÒÜ8¸ÓI‘	ä5°oÓF�	ñ Ø9˜=×9Ñ9¸?ÐK�ÜÐ'Ô(Ø× Ñ Ô"ÜØ$¤S¨¯©Ó%8Ð$9ð :Ü˜H×.Ñ.Ó/Ð0ð 1Ø ×8Ñ8Ð9¸ð<ôð
 ô 	Ð2Õ3r)   )	Ú__name__Ú
__module__Ú__qualname__Ústaticmethodr   r>   r   rG   r]   © r)   r'   r-   r-   h   s8   „ Øð BÐ$5ò  Bó ð BðD<˜Yð <¨4ó <ó
"4r)   r-   ÚreporE   c                 ó  — |dk(  r&| j                   | j                  j                  «       fS |dk(  rt        d„ | j                  D «       «       S |dk(  r| j
                   S |dk(  r| j                   S | j                   | j                  fS )Nr   r   c              3   ó4   K  — | ]  }|j                   –— Œ y ­wr@   ©Úlast_modified)Ú.0Úrevs     r'   ú	<genexpr>z(_get_repo_sorting_key.<locals>.<genexpr>º   s   è ø€ Ò@¨#�C×%Õ%Ñ@ùs   ‚r   r   )Ú	repo_typeÚrepo_idÚlowerÚmaxÚ	revisionsÚlast_accessedÚsize_on_disk©rc   rE   s     r'   Ú_get_repo_sorting_keyrs   ¶   s‡   € Ø�.Ò Ø—‘ §¡× 2Ñ 2Ó 4Ð5Ð5Ø	�MÒ	!ÜÑ@°·±Ô@Ó@Ð@Ð@Ø	�JÒ	Ø×"Ñ"Ð"Ð"Ø	�FÒ	Ø×!Ñ!Ð!Ð!à—‘ §¡Ð-Ð-r)   rX   rI   c                 óŽ  ‡ ‡— t        ‰ j                  ||¬«      }t        j                  d|ddt	        ‰ |D �cg c],  }t        |t        «      sŒ|j                  sŒ!|j                  ‘Œ. c}¬«      dd„ ¬«      Šdˆˆ fd	„}‰j                  d
   j                  d|i«       	 ‰j                  «       S c c}w # t        $ r g cY S w xY w)zzAsk the user for a manual review of the revisions to delete.

    Displays a multi-select menu in the terminal (TUI).
    )rU   rI   rE   zSelect revisions to delete:Féd   ©rY   zWPress <space> to select, <enter> to validate and <ctrl+c> to quit without modification.c                 ó   — t        | «      › d�S )Nz revision(s) selected.)rM   )Úresults    r'   ú<lambda>z$_manual_review_tui.<locals>.<lambda>á   s   € ¤c¨&£k ]Ð2HÐ#I€ r)   )Úmessager7   ÚcycleÚheightÚinstructionÚlong_instructionÚtransformerc                 óŠ   •— t        ‰‰j                  j                  D �cg c]  }|d   sŒ	|d   ‘Œ c}¬«      ‰_        y c c}w )NÚenabledÚvaluerv   )rO   Úcontent_controlr7   Ú_instruction)Ú_ÚchoiceÚcheckboxrX   s     €€r'   Ú_update_expectationsz0_manual_review_tui.<locals>._update_expectationsæ   s?   ø€ ô !6ØØ;C×;SÑ;S×;[Ñ;[Öq°Ð_eÐfoÓ_p˜V G›_Òqô!
ˆÕùâqs
    
A 
«A 
Útoggler8   )r    N)Ú_get_tui_choices_from_scanrU   r   r‡   rO   Ú
isinstancer   r�   r‚   Úkb_func_lookupÚappendrT   ÚKeyboardInterrupt)rX   rI   rE   r7   Úcrˆ   r‡   s   `     @r'   rL   rL   Ã   sÌ   ù€ ô )Ø×!Ñ!ØØô€Gô
 × Ñ Ø-ØØØô *ØØ.5Ö]¨¼ÀAÄvÕ9NÐST×S\ÓS\˜QŸW›WÒ]ô
ð
 sáIô€Hö&
ð ×Ñ˜HÑ%×,Ñ,¨fÐ6JÐ-KÔLðØ×ÑÓ!Ð!ùò- ^øô. ò ØŠ	ðús#   ¸B1ÁB1ÁB1Â!B6 Â6CÃCrz   r2   c                 óL   — t        j                  | |¬«      j                  «       S )z$Ask for confirmation using Inquirer.©r2   )r   ÚconfirmrT   )rz   r2   s     r'   rQ   rQ   ÷   s    € ô ×Ñ˜G¨WÔ5×=Ñ=Ó?Ð?r)   rU   c                 óf  ‡— g }|j                  t        t        dd¬«      «       t        | ˆfd„¬«      }|D ]÷  }|j                  t	        d|j
                  j                  «       › d|j                  › d|j                  › d	|j                  › d
�	«      «       t        |j                  t        ¬«      D ]z  }|j                  t        |j                  |j                  dd › ddj                  t        |j                  «      «      xs d› d|j                  › �|j                  |v ¬«      «       Œ| Œù |S )aë  Build a list of choices from the scanned repos.

    Args:
        repos (*Iterable[`CachedRepoInfo`]*):
            List of scanned repos on which we want to delete revisions.
        preselected (*List[`str`]*):
            List of revision hashes that will be preselected.
        sort_by (*Optional[SortingOption_T]*):
            Sorting direction. Choices: "alphabetical", "lastUpdated", "lastUsed", "size".

    Return:
        The list of choices to pass to `inquirer.checkbox`.
    z=None of the following (if selected, nothing will be deleted).F)Únamer�   c                 ó   •— t        | ‰«      S r@   ©rs   rr   s    €r'   ry   z,_get_tui_choices_from_scan.<locals>.<lambda>  s   ø€ Ô2GÈÈgÓ2V€ r)   ©Úkeyú
ú ú (ú, used ú)Né   z: ú, ú
(detached)ú # modified )r�   r   rN   Úsortedr   rk   Ú
capitalizerl   Úsize_on_disk_strÚlast_accessed_strro   Ú_revision_sorting_orderÚcommit_hashÚjoinÚrefsÚlast_modified_str)rU   rI   rE   r7   Úsorted_reposrc   Úrevisions     `    r'   rŠ   rŠ   ý   s>  ø€ ð$ /1€Gð ‡N�NÜÜ ØPØô	
ôô ˜%Ó%VÔW€Làò ˆà�‰ÜØ�T—^‘^×.Ñ.Ó0Ð1°°4·<±<°.ÀÀ4×CXÑCXÐBYð ZØ×/Ñ/Ð0°ð3óô	
ô ˜tŸ~™~Ô3JÔKò 	ˆHà�N‰NÜØ×(Ñ(à#×/Ñ/°°Ð3Ð4ð 5Ø ŸI™I¤f¨X¯]©]Ó&;Ó<ÒLÀÐMð N%Ø%-×%?Ñ%?Ð$@ðBð %×0Ñ0°KÐ?ôõ
ñ	ðð. €Nr)   c                 ó0  ‡— t        d¬«      \  }}t        j                  |«       g }t        | j                  ˆfd„¬«      }|D ]Ü  }|j                  d|j                  j                  «       › d|j                  › d|j                  › d|j                  › d	�	«       t        |j                  t        ¬«      D ]h  }|j                  |j                  |v rd
nd› d|j                  › ddj                  t        |j                  «      «      xs d› d|j                   › �«       Œj ŒÞ t#        |d«      5 }	|	j%                  t&        «       |	j%                  dj                  |«      «       ddd«       dt)        j*                  |«      › d�}
t-        dj                  d„ |
j/                  «       j1                  d«      D «       «      «       	 t3        |«      }t5        t7        | |«      dz   d¬«      rnŒ't        j8                  |«       t        |«      S # 1 sw Y   Œ¨xY w)z³Ask the user for a manual review of the revisions to delete.

    Used when TUI is disabled. Manual review happens in a separate tmp file that the
    user can manually edit.
    z.txt)Úsuffixc                 ó   •— t        | ‰«      S r@   r–   rr   s    €r'   ry   z'_manual_review_no_tui.<locals>.<lambda>G  s   ø€ Ô@UÐVZÐ\cÓ@d€ r)   r—   z
# rš   r›   rœ   r�   Ú ú#z    z	 # Refs: rŸ   r    r¡   Úwr™   Na*  
    TUI is disabled. In order to select which revisions you want to delete, please edit
    the following file using the text editor of your choice. Instructions for manual
    editing are located at the beginning of the file. Edit the file, save it and confirm
    to continue.
    File to edit: z
    c              3   ó<   K  — | ]  }|j                  «       –— Œ y ­wr@   )Ústrip)rh   Úlines     r'   rj   z(_manual_review_no_tui.<locals>.<genexpr>e  s   è ø€ ÒN T�D—J‘J—LÑNùs   ‚z Continue ?Fr‘   )r   ÚosÚcloser¢   rU   r�   rk   r£   rl   r¤   r¥   ro   r¦   r§   r¨   r©   rª   ÚopenÚwriteÚ"_MANUAL_REVIEW_NO_TUI_INSTRUCTIONSr   ÚboldrS   r´   ÚsplitÚ_read_manual_review_tmp_filerP   rO   Úremove)rX   rI   rE   ÚfdÚtmp_pathÚlinesr«   rc   r¬   ÚfÚinstructionsrY   s     `         r'   rK   rK   7  sÿ  ø€ ô  &Ô)�L€BˆÜ‡H�HˆR„Là€Eä˜-×-Ñ-Ó3dÔe€Làò ˆØ�‰Ø�4—>‘>×,Ñ,Ó.Ð/¨q°·±°¸bÀ×AVÑAVÐ@Wð XØ×+Ñ+Ð,¨Að/ô	
ô ˜tŸ~™~Ô3JÔKò 		ˆHØ�L‰Là!×-Ñ-°Ñ<‘2À#ÐFð GØ×(Ñ(Ð)ð *à—I‘Iœf X§]¡]Ó3Ó4ÒD¸ÐEð Fà×.Ñ.Ð/ð1õñ		ðô  
ˆh˜Ó	ð " Ø	�‰Ô2Ô3Ø	�‰�—	‘	˜%Ó Ô!÷"ð
ô
 —9‘9˜XÓ&Ð'ð (ð€Lô 
ˆ$�)‰)ÑN¨\×-?Ñ-?Ó-A×-GÑ-GÈÓ-MÔNÓ
NÔOð Ü6°xÓ@ˆÜ'Ü! -°ÓAÀMÑQØõ
ð ð ô ‡I�IˆhÔÜ�/Ó"Ð"÷3"ð "ús   Ä/6HÈHc                 ó¦   — d}d}d}||z   |fz   }| |rdndz   }	 t        |«      j                  «       }||k(  r|S ||v ry||v ryt        d|› �«       Œ9)	z'Ask for confirmation using pure-python.)ÚyÚyesÚ1)ÚnÚnoÚ0r°   z (Y/n) z (y/N) TFzInvalid input. Must be one of )Úinputrm   rS   )rz   r2   ÚYESÚNOÚDEFAULTÚALLÚfull_messageÚanswers           r'   rP   rP   u  s{   € à
€CØ	€BØ€GØ
�‰(�g�ZÑ
€CØ©7™i¸	ÑB€LØ
Ü�|Ó$×*Ñ*Ó,ˆØ�WÒØˆNØ�S‰=ØØ�R‰<ØÜÐ.¨s¨eÐ4Ô5ð r)   rY   c                 óh   — t         |v ry | j                  |Ž }t        |«      › d|j                  › d�S )zÔFormat a string to display to the user how much space would be saved.

    Example:
    ```
    >>> _get_expectations_str(hf_cache_info, selected_hashes)
    '7 revisions selected counting for 4.3G.'
    ```
    zNothing will be deleted.z! revisions selected counting for rJ   )rN   rR   rM   rW   )rX   rY   r\   s      r'   rO   rO   ‡  sC   € ô ˜Ñ.Ø)Ø-ˆ}×-Ñ-¨Ð?€HÜ�/Ó"Ð#Ð#DÀX×EeÑEeÐDfÐfgÐhÐhr)   rÀ   c                 óÀ  — t        | «      5 }|j                  «       }ddd«       j                  d«      D �cg c]  }|j                  «       ‘Œ }}|D �cg c]  }|j	                  d«      rŒ|‘Œ }}|D �cg c]$  }|j                  d«      d   j                  «       ‘Œ& }}|D �cg c]  }t        |«      dkD  sŒ|‘Œ c}S # 1 sw Y   Œ¤xY wc c}w c c}w c c}w c c}w )aÏ  Read the manually reviewed instruction file and return a list of revision hash.

    Example:
        ```txt
        # This is the tmp file content
        ###

        # Commented out line
        123456789 # revision hash

        # Something else
        #      a_newer_hash # 2 days ago
            an_older_hash # 3 days ago
        ```

        ```py
        >>> _read_manual_review_tmp_file(tmp_path)
        ['123456789', 'an_older_hash']
        ```
    Nr™   r±   r   )r¸   Úreadr¼   r´   Ú
startswithrM   )rÀ   rÂ   Úcontentrµ   rÁ   Úselected_linesrY   Úhashs           r'   r½   r½   –  sÏ   € ô* 
ˆh‹ð ˜1Ø—&‘&“(ˆ÷ð '.§m¡m°DÓ&9Ö:˜dˆT�Z‰Z�\Ð:€EÐ:ð (-ÖI˜t°D·O±OÀCÕ4H’dÐI€NÐIð ?MÖM°d�t—z‘z #“ qÑ)×/Ñ/Õ1ÐM€OÐMð -Ö>�T´°D³	¸A³ŠDÒ>Ð>÷ð üò ;ùò Jùò Nùò ?s.   ŒC ¸CÁCÁ,CÁ6)CÂ%CÂ9CÃ C	aí  
# INSTRUCTIONS
# ------------
# This is a temporary file created by running `huggingface-cli delete-cache` with the
# `--disable-tui` option. It contains a set of revisions that can be deleted from your
# local cache directory.
#
# Please manually review the revisions you want to delete:
#   - Revision hashes can be commented out with '#'.
#   - Only non-commented revisions in this file will be deleted.
#   - Revision hashes that are removed from this file are ignored as well.
#   - If `aa  ` line is uncommented, the all cache deletion is cancelled and
#     no changes will be applied.
#
# Once you've manually reviewed this file, please confirm deletion in the terminal. This
# file will be automatically removed once done.
# ------------

# KILL SWITCH
# ------------
# Un-comment following line to completely cancel the deletion process
# z,
# ------------

# REVISIONS
# ------------
r¬   c                 ó   — | j                   S r@   rf   )r¬   s    r'   r¦   r¦   Ø  s   € à×!Ñ!Ð!r)   r@   )T)3Ú__doc__r¶   Úargparser   r   Ú	functoolsr   Útempfiler   Útypingr   r	   r
   r   r   r   r   Úutilsr   r   r   r   r°   r   Ú
_cli_utilsr   Ú
InquirerPyr   ÚInquirerPy.base.controlr   ÚInquirerPy.separatorr   r#   r$   ÚSortingOption_Tr*   rN   r-   rs   r;   rL   ÚboolrQ   rŠ   rK   rP   rO   r½   r´   rº   r¦   rb   r)   r'   ú<module>ræ      s7  ðñ*óX 
ß 1Ý Ý ß J× JÑ Jç SÓ SÝ 'Ý ð#Ý#Ý.Ý.à!Ðð ÐKÑL€ð˜Hð ¨ó ð& )Ð ôK4Ð2ô K4ñ\
. ð 
.¸À/Ñ9Ró 
.ð ð *.ñ0Øð0à�c‘ð0ð �oÑ&ð0ð 
ˆ#�Yò	0ó ð0ðf ñ@ sð @°Tð @ÀTò @ó ð@ð *.ñ7Ø�NÑ#ð7à�c‘ð7ð �oÑ&ð7ð 
ó	7ðz *.ñ;#Øð;#à�c‘ð;#ð �oÑ&ð;#ð 
ˆ#�Yó	;#ñ|6¨#ð 6¸ð 6Èó 6ð$i¨ð iÀtÈCÁyð iÐUXó ið"?¨3ð "?°4¸±9ó "?ðJ*ð  Ð
 ð 
!ð Ðð ð+&÷4 
�EƒGð5 #ð:"Ð&8ð "¸Sô "øðY ò #Ø"Òð#ús   ÁD ÄD'Ä&D'