
    3j!              &       
   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJ	r	  SSK
JrJr  SSKJrJr  SSKJr  SSKJrJrJr  SS	KJrJr  SS
KJr  SSKJrJrJrJrJrJ r J!r!  SSK"J#r#  \(       a  SSK$J%r%  \RL                  " \'5      r(Sr)Sr*\ " S S5      5       r+\ " S S5      5       r,\ " S S5      5       r-\ " S S5      5       r.\" SS9 " S S5      5       r/\ " S S5      5       r0\ " S S5      5       r1\ " S  S!5      5       r2S"\3S#\4S$ jr4S"\3S#\54S% jr6\ " S& S'5      5       r7\ " S( S)5      5       r8 " S* S+5      r9S,\3S#\:\;\3\34      4S- jr<S"\3S#\;\=\>4   S-  4S. jr?S/\3S#\	\;\3\=\>4      4S0 jr@S1S2S3\3S4\3S#\	\;\3\=\>\4      4S5 jrAS6\>S#\34S7 jrBSS8.S"\3S9\S:   S;\=S<\>S=\=S>\>S?\3S@\3SA\5SB\5SC\5SD\S-  S#\74SE jjrC       S_SG\3SH\3S1S2SI\5SB\5SA\5SJ\5SC\5SK\9S-  SL\S-  S#\84SM jjrDSN\8S#S4SO jrESN\8SP\3S#S4SQ jrFSP\3S#\84SR jrGS`SN\8S1S2SS\5SL\S-  S#S4
ST jjrHSN\8S#S4SU jrI  SaSFSFSFSFSFSSSSSSFSFSFSSV.SG\3S-  SH\3S-  S1S2SI\5SB\5SA\5SJ\5SC\5SW\:\3   S-  SX\:\3   S-  SY\3S-  SN\3S-  SZ\3S-  S[\5SS\5S\\5S]\5\3-  S-  S#\84$S^ jjjrJg)bzzShared logic for bucket operations.

This module contains the core buckets logic used by both the CLI and the Python API.
    N)Iterator)	dataclassfield)datetimetimezone)Path)TYPE_CHECKINGAnyLiteral   )	constantslogging)BucketNotFoundError)HfUri
StatusLineXetFileDatadisable_progress_barsenable_progress_barsparse_datetimeparse_hf_uri)_looks_like_hf_urlHfApizhf://buckets/  c                   R    \ rS rSr% Sr\\S'   \\S'   \\S'   \	\S'   \	\S'   S r
S	rg
)
BucketInfo>   a  
Contains information about a bucket on the Hub. This object is returned by [`bucket_info`] and [`list_buckets`].

Attributes:
    id (`str`):
        ID of the bucket.
    private (`bool`):
        Is the bucket private.
    created_at (`datetime`):
        Date of creation of the bucket on the Hub.
    size (`int`):
        Size of the bucket in bytes.
    total_files (`int`):
        Total number of files in the bucket.
idprivate
created_atsizetotal_filesc                 *   UR                  S5      U l        UR                  S5      U l        [        UR                  S5      5      U l        UR                  S5      U l        UR                  S5      U l        U R                  R                  " S0 UD6  g )Nr   r   	createdAtr!   
totalFiles )	popr   r   r   r    r!   r"   __dict__update)selfkwargss     R/home/wildlama/miniconda3/lib/python3.13/site-packages/huggingface_hub/_buckets.py__init__BucketInfo.__init__V   sm    **T"zz),(K)@AJJv&	!::l3&v&    )r    r   r   r!   r"   N)__name__
__module____qualname____firstlineno____doc__str__annotations__boolr   intr-   __static_attributes__r&   r/   r,   r   r   >   s)      	GM
I'r/   r   c                       \ rS rSr% \\-  \-  \S'   \\S'   \" SS9r	\S-  \S'   \" SS9r
\S-  \S'   \" SS	9r\\S
'   \" SS	9r\S-  \S'   SS jrSrg)_BucketAddFile_   sourcedestinationNdefaultxet_hashr!   Finitmtimecontent_typec                    S U l         [        U R                  [        [        45      (       a(  [
        R                  " U R                  5      S   U l         U R                   c(  [
        R                  " U R                  5      S   U l         [        [        U R                  [        5      (       d,  [        R                  R                  U R                  5      S-  O[        R                  " 5       S-  5      U l        g Nr   r   )rE   
isinstancer=   r5   r   	mimetypes
guess_typer>   r8   bytesospathgetmtimetimerD   r*   s    r,   __post_init___BucketAddFile.__post_init__i   s     dkkC;// ) 4 4T[[ A! DD$ ) 4 4T5E5E Fq ID8B4;;PU8V8VBGGT[[)D0\`\e\e\gjn\n

r/   rE   rD   returnN)r0   r1   r2   r3   r5   r   rK   r6   r   rA   r!   r8   rD   rE   rQ   r9   r&   r/   r,   r;   r;   _   sd    $J .HcDj.T*D#**E"E3"$%0L#*0	
r/   r;   c                       \ rS rSr% \\S'   \\S'   \\S'   \\S'   \" SS9r\S-  \S'   \" S	S
9r	\\S'   \" S	S
9r
\S-  \S'   SS jrSrg)_BucketCopyFileu   r>   rA   source_repo_typesource_repo_idNr?   r!   FrB   rD   rE   c                     [         R                  " U R                  5      S   U l        [	        [
        R
                  " 5       S-  5      U l        g rG   )rI   rJ   r>   rE   r8   rO   rD   rP   s    r,   rQ   _BucketCopyFile.__post_init__   s7    %001A1AB1Et+,
r/   rS   rT   )r0   r1   r2   r3   r5   r6   r   r!   r8   rD   rE   rQ   r9   r&   r/   r,   rW   rW   u   sS    MT*D#**E"E3"$%0L#*0-r/   rW   c                        \ rS rSr% \\S'   Srg)_BucketDeleteFile   rM   r&   N)r0   r1   r2   r3   r5   r6   r9   r&   r/   r,   r^   r^      s    
Ir/   r^   T)frozenc                   .    \ rS rSr% Sr\\S'   \\S'   Srg)BucketFileMetadata   a	  Data structure containing information about a file in a bucket.

Returned by [`get_bucket_file_metadata`].

Args:
    size (`int`):
        Size of the file in bytes.
    xet_file_data (`XetFileData`):
        Xet information for the file (hash and refresh route).
r!   xet_file_datar&   N)	r0   r1   r2   r3   r4   r8   r6   r   r9   r&   r/   r,   rb   rb      s    	 Ir/   rb   c                   ~    \ rS rSr% Sr\\S'   Sr\\S'   \" SS9r	\\S'   \" SS9r
\\S	'   \" SS9r\\S
'   SS jrSrg)	BucketUrl   a  Describes a bucket URL on the Hub.

`BucketUrl` is returned by [`create_bucket`]. At initialization, the URL is parsed to populate properties:
- endpoint (`str`)
- namespace (`str`)
- bucket_id (`str`)
- url (`str`)
- uri (`HfUri`)

Args:
    url (`str`):
        String value of the bucket url.
    endpoint (`str`, *optional*):
        Endpoint of the Hub. Defaults to <https://huggingface.co>.
url endpointFrB   	namespace	bucket_iduriNc                    U R                   =(       d    [        R                  U l         U R                  R	                  U R                   S5      R                  S5      nUR                  S5      (       a  U[        S5      S  n[        U5      nUR                  (       a  [        SU R                   35      eUR                  R                  S5      S   U l        UR                  U l        X l        g )Nri   /zbuckets/zUnable to parse bucket URL: r   )rj   r   ENDPOINTrh   replacestrip
startswithlen_parse_bucket_uripath_in_repo
ValueErrorr   splitrk   rl   rm   )r*   url_pathparseds      r,   rQ   BucketUrl.__post_init__   s    ;);); 88##DMM26<<SAz**J 12H"8,;DHH:FGG-a0r/   )rl   rj   rk   rm   rT   )r0   r1   r2   r3   r4   r5   r6   rj   r   rk   rl   rm   r   rQ   r9   r&   r/   r,   rf   rf      sJ      
HHc&Is&&Is&E"C"r/   rf   c                   n    \ rS rSr% Sr\S   \S'   \\S'   \\S'   \\S'   \	S-  \S	'   \	S-  \S
'   S r
Srg)
BucketFile   z
Contains information about a file in a bucket on the Hub. This object is returned by [`list_bucket_tree`].

Similar to [`RepoFile`] but for files in buckets.
filetyperM   r!   rA   NrD   uploaded_atc                 l   UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        UR                  SS 5      nU(       a  [        U5      OS U l        UR                  SS 5      nU(       a  [        U5      U l        g S U l        g )Nr   rM   r!   xetHashrD   
uploadedAt)r'   r   rM   r!   rA   r   rD   r   )r*   r+   rD   r   s       r,   r-   BucketFile.__init__   s    JJv&	JJv&	JJv&	

9-

7D).3^E*
jjt4:E>+64r/   )rD   rM   r!   r   r   rA   )r0   r1   r2   r3   r4   r   r6   r5   r8   r   r-   r9   r&   r/   r,   r}   r}      s<     &/
I
IMd?D Pr/   r}   c                   J    \ rS rSr% Sr\S   \S'   \\S'   \S-  \S'   S r	S	r
g)
BucketFolder   z
Contains information about a directory in a bucket on the Hub. This object is returned by [`list_bucket_tree`].

Similar to [`RepoFolder`] but for directories in buckets.
	directoryr   rM   Nr   c                 ,   UR                  S5      U l        UR                  S5      U l        UR                  SS 5      =(       d    UR                  SS 5      nU(       a/  [        U[        5      (       a  UU l        g [        U5       U l        g S U l        g )Nr   rM   r   r   )r'   r   rM   rH   r   r   r   )r*   r+   r   s      r,   r-   BucketFolder.__init__   s    JJv&	JJv&	jjt4W

=RV8W  '{H==[ 	CQR]C^ 	  	r/   )rM   r   r   )r0   r1   r2   r3   r4   r   r6   r5   r   r-   r9   r&   r/   r,   r   r      s(     +

ID 
r/   r   rM   rU   c                    U R                  [        R                  5      (       d  [        U 5      (       a-  [	        U 5      nUR
                  (       d  [        SU  S35      eU$ U R                  SS5      n[        U5      S:  d  US   (       a
  US   (       d  [        SU  S35      eUS    SUS    3nSR                  USS	 5      n[        S
X4S9$ )zParse a bucket path into a HfUri.

Accepts:
- `hf://buckets/namespace/name(/path/in/repo)` URIs,
- Hugging Face web URLs such as `https://huggingface.co/buckets/namespace/name(/tree/path)`,
- plain `namespace/name(/path/in/repo)` paths.
zInvalid bucket path: z*. Must be a bucket URI (hf://buckets/...).ro      r   r   zInvalid bucket path: 'z)'. Expected format: namespace/bucket_nameNbucket)r   r   rv   )rs   r   HF_PROTOCOLr   r   	is_bucketrw   rx   rt   joinr   )rM   rz   partsrl   prefixs        r,   ru   ru      s     y,,--1CD1I1Id#4TF:deffJJsAE
5zA~U1XU1X1$7`abb8*AeAhZ(IXXeABi Fh9BBr/   c                 v    U R                  [        R                  5      (       d  g[        U 5      R                  $ )zCheck if a path is a bucket path.

Do not raise if the path is not a hf:// URI.
Raise if the path is a hf:// URI but with an incorrect format.
F)rs   r   r   r   r   )rM   s    r,   _is_bucket_pathr     s-     ??90011'''r/   c                       \ rS rSr% Sr\S   \S'   \\S'   Sr\	S-  \S'   Sr
\\S	'   Sr\S-  \S
'   Sr\S-  \S'   Sr\S-  \S'   Srg)SyncOperationi  z,Represents a sync operation to be performed.)uploaddownloaddeleteskipactionrM   Nr!   ri   reasonlocal_mtimeremote_mtimebucket_filer&   )r0   r1   r2   r3   r4   r   r6   r5   r!   r8   r   r   r   r   r}   r9   r&   r/   r,   r   r     sY    6:;;
ID#*FC"Kt"#L#*#%)Kd")r/   r   c                   r    \ rS rSr% Sr\\S'   \\S'   \\S'   \" \S9r	\\
   \S'   S\\\\-  4   4S	 jrS
rg)SyncPlani+  z Represents a complete sync plan.r=   dest	timestamp)default_factory
operationsrU   c                 *   [        S U R                   5       5      n[        S U R                   5       5      n[        S U R                   5       5      n[        S U R                   5       5      n[        S U R                   5       5      nUUUUUS.$ )Nc              3   H   #    U  H  oR                   S :X  d  M  Sv   M     g7f)r   r   Nr   .0ops     r,   	<genexpr>#SyncPlan.summary.<locals>.<genexpr>5       K/BYY(5Jaa/   "	"c              3   H   #    U  H  oR                   S :X  d  M  Sv   M     g7f)r   r   Nr   r   s     r,   r   r   6  s     OObyyJ7NOr   c              3   H   #    U  H  oR                   S :X  d  M  Sv   M     g7f)r   r   Nr   r   s     r,   r   r   7  r   r   c              3   H   #    U  H  oR                   S :X  d  M  Sv   M     g7f)r   r   Nr   r   s     r,   r   r   8  s     G"993FAAr   c              3   n   #    U  H+  oR                   S ;   d  M  UR                  =(       d    Sv   M-     g7f)r   r   r   N)r   r!   r   s     r,   r   r   9  s&     g"99PfCfAs   55)uploads	downloadsdeletesskips
total_size)sumr   )r*   r   r   r   r   r   s         r,   summarySyncPlan.summary4  s    K$//KKODOOOO	K$//KKGGGggg
"$
 	
r/   r&   N)r0   r1   r2   r3   r4   r5   r6   r   listr   r   dictr8   r   r9   r&   r/   r,   r   r   +  sA    *K
IN&+D&AJ]#A
c39n- 
r/   r   c            
       x    \ rS rSrSr   SS\\   S-  S\\   S-  S\\\\4      S-  4S jjrS\S	\	4S
 jr
Srg)FilterMatcheriH  z4Matches file paths against include/exclude patterns.Ninclude_patternsexclude_patternsfilter_rulesc                 d    U=(       d    / U l         U=(       d    / U l        U=(       d    / U l        g)zInitialize the filter matcher.

Args:
    include_patterns: Patterns to include (from --include)
    exclude_patterns: Patterns to exclude (from --exclude)
    filter_rules: Rules from filter file as list of ("+"/"-", pattern) tuples
Nr   r   r   )r*   r   r   r   s       r,   r-   FilterMatcher.__init__K  s+     !1 6B 0 6B(.Br/   rM   rU   c                 V   U R                    H'  u  p#[        R                  " X5      (       d  M"  US:H  s  $    U R                   H   n[        R                  " X5      (       d  M     g   U R                   H   n[        R                  " X5      (       d  M     g   U R                  (       a  gg)zCheck if a path should be included based on the filter rules.

Filtering rules:
- Filters are evaluated in order, first matching rule decides
- If no rules match, include by default (unless include patterns are specified)
+FT)r   fnmatchr   r   )r*   rM   signpatterns       r,   matchesFilterMatcher.matches\  s     "..MDt--s{" /
 ,,Gt-- - ,,Gt-- -
    r/   )r   r   r   )NNN)r0   r1   r2   r3   r4   r   r5   tupler-   r7   r   r9   r&   r/   r,   r   r   H  sh    > .2-159	/s)d*/ s)d*/ 5c?+d2	/"C D r/   r   filter_filec                    / n[        U 5       nU H  nUR                  5       nU(       a  UR                  S5      (       a  M2  UR                  S5      (       a&  UR                  SUSS R                  5       45        Mn  UR                  S5      (       a&  UR                  SUSS R                  5       45        M  UR                  SU45        M     SSS5        U$ ! , (       d  f       U$ = f)zParse a filter file and return a list of (sign, pattern) tuples.

Filter file format:
- Lines starting with "+" are include patterns
- Lines starting with "-" are exclude patterns
- Empty lines and lines starting with "#" are ignored
#r   r   N-)openrr   rs   append)r   rulesflines       r,   _parse_filter_filer   y  s     E	k	aD::<D4??3//s##c48>>#345%%c48>>#345 c4[)  
 L 
	 Ls   CC
C+c                      [         R                  " U 5      n[        R                  " UR                  5      (       a  gUR
                  UR                  S-  4$ ! [         a     gf = f)zStat a local file and return (size, mtime_ms).

Returns None if the path is missing or is a directory. Uses a single
``os.stat`` call so callers don't pay for multiple syscalls per file.
Nr   )rL   statOSErrorS_ISDIRst_modest_sizest_mtime)rM   sts     r,   _stat_localr     sX    WWT] ||BJJ::r{{T)))	  s   A 
A&%A&
local_pathc              #     #    [         R                  R                  U 5      n [         R                  R                  U 5      (       d  [	        SU  35      e[         R
                  " U 5       H  u  pnU H}  n[         R                  R                  X5      n[        U5      nUc  M2  [         R                  R                  XP5      nUR                  [         R                  S5      nXvS   US   4v   M     M     g7f)zgList all files in a local directory.

Yields:
    tuple: (relative_path, size, mtime_ms) for each file
z Local path must be a directory: Nro   r   r   )rL   rM   abspathisdirrw   walkr   r   relpathrq   sep)r   root_filesfilename	full_path	stat_inforel_paths           r,   _list_local_filesr     s      ,J77==$$;J<HII''*-HT4I#I.I wwy=H''4HaL)A,66  .s   C6C8apir   rl   r   c              #     #    U R                  X=(       d    SSS9 H  n[        U[        5      (       a  M  UR                  nU(       aP  UR	                  US-   5      (       a  U[        U5      S-   S nO'XB:X  a  SU;   a  UR                  SS5      S   OUnOM}  UnUR                  (       a  UR                  R                  5       S-  OSnXSR                  Xc4v   M     g7f)	zList all files in a bucket with a given prefix.

Yields:
    tuple: (relative_path, size, mtime_ms, bucket_file) for each file.
        bucket_file is the BucketFile object from list_bucket_tree.
NT)r   	recursivero   r   r   r   )
list_bucket_treerH   r   rM   rs   rt   rsplitrD   r   r!   )r   rl   r   itemrM   r   mtime_mss          r,   _list_remote_filesr     s      $$Y~QU$VdL))yy v|,,Fa 1269Tk4;;sA.r2t H48JJ4::'')D0A		811' Ws   CC r   c                 j    [         R                  " U S-  [        R                  S9R	                  5       $ )z3Convert mtime in milliseconds to ISO format string.r   )tz)r   fromtimestampr   utc	isoformat)r   s    r,   _mtime_to_isor     s&    !!(T/hllCMMOOr/   )r   r   r   source_sizesource_mtime	dest_size
dest_mtimesource_newer_labeldest_newer_labelignore_sizesignore_timesignore_existingr   c                    [        US:X  a  UOU5      n[        US:X  a  UOU5      nU UUUS.nU
(       a  [        SSSS.UD6$ X$:g  nX5-
  [        :  nU(       a9  U(       a  [        SXUS.UD6$ XS-
  [        :  nU(       a  UOSn[        SSUS.UD6$ U	(       a$  U(       a  [        SUSUS.UD6$ [        SSS	S.UD6$ U(       d  U(       a  U(       a  SOUn[        SUUUS.UD6$ [        SSS
S.UD6$ )aS  Compare source and dest files and return the appropriate sync operation.

This is a unified helper for both upload and download directions.

Args:
    path: Relative file path
    action: "upload" or "download"
    source_size: Size of the source file (bytes)
    source_mtime: Mtime of the source file (milliseconds)
    dest_size: Size of the destination file (bytes)
    dest_mtime: Mtime of the destination file (milliseconds)
    source_newer_label: Label when source is newer (e.g., "local newer" or "remote newer")
    dest_newer_label: Label when dest is newer (e.g., "remote newer" or "local newer")
    ignore_sizes: Only compare mtime
    ignore_times: Only compare size
    ignore_existing: Skip files that exist on receiver
    bucket_file: BucketFile object (for downloads only)

Returns:
    SyncOperation describing the action to take
r   )rM   r!   r   r   r   z&exists on receiver (--ignore-existing))r   r   )r   r   r   z
same mtimezsize differsz	same size	identicalr&   )r   r   _SYNC_TIME_WINDOW_MS)rM   r   r  r  r  r  r  r  r  r  r	  r   local_mtime_isoremote_mtime_isobase_kwargssize_differssource_newer
dest_newerskip_reasonr   s                       r,   _compare_files_for_syncr    s-   H $Fh4FLJWO$6X3EZ<X &(	#K kF3[k_jkk+L -1EEL rWbrfqrr$37KKJ.8*lK R{RkRR	 n~S^nbmnn R{RkRR<'3^9KF fv;fZeff R{RkRRr/   Fr=   r   r   existingfilter_matcherstatusc
                 b   U=(       d
    [        5       n[        U 5      (       + =(       a    [        U5      n
[        U 5      =(       a    [        U5      (       + nU
(       d  U(       d  [        S5      e[        U U[        R
                  " [        R                  5      R                  5       S9nSnU
(       GaT  [        R                  R                  U 5      n[        U5      nUR                  UR                  nn[        R                  R                  U5      (       d  [        SU 35      e0 n[!        U5       HK  u  nnnUR#                  U5      (       a  UU4UU'   U	(       d  M-  U	R%                  S['        U5       S35        MM     U	(       a  U	R)                  S['        U5       S35        0 nU	(       a   UR+                  U5      R,                  n [1        UUU5       HX  u  nnnnUR#                  U5      (       a  UU4UU'   U	(       d  M.  Ub  SU 3OSnU	R%                  S	['        U5       U S35        MZ     U	(       a  U	R)                  S	['        U5       S35        [9        UR;                  5       5      [9        UR;                  5       5      -  nU	(       a  U	R)                  S['        U5       S35        [=        U5       GHA  nUR?                  U5      nUR?                  U5      nU(       a|  U(       du  U(       a7  UR@                  RC                  [E        SUUS   S[G        US   5      S95        Mr  UR@                  RC                  [E        SUUS   S[G        US   5      S95        M  U(       a?  U(       a8  Uu  nnUu  nn UR@                  RC                  [I        USUUUU SSUUUS95        M  U(       a  M  U(       d  GM  U(       d  GM  UR@                  RC                  [E        SUUS   S[G        US   5      S95        GMD     U$ [        U 5      nUR                  UR                  nn[        R                  R                  U5      n0 n0 n!U	(       a   UR+                  U5      R,                  n[1        UUU5       H]  u  nnnn"UR#                  U5      (       a  UU4UU'   U"U!U'   U	(       d  M3  Ub  SU 3OSnU	R%                  S	['        U5       U S35        M_     U	(       a  U	R)                  S	['        U5       S35        0 n[        R                  R                  U5      (       a  U(       a[  [!        U5       HK  u  nnnUR#                  U5      (       a  UU4UU'   U	(       d  M-  U	R%                  S['        U5       S35        MM     OeU H_  n[        R                  RK                  UU5      n#[M        U#5      n$U$c  M3  U$UU'   U	(       d  MA  U	R%                  S['        U5       S35        Ma     U	(       a  U	R)                  S['        U5       S35        [9        UR;                  5       5      [9        UR;                  5       5      -  nU	(       a  U	R)                  S['        U5       S35        [=        U5       GHc  nUR?                  U5      nUR?                  U5      nU(       a  U(       d  U(       a7  UR@                  RC                  [E        SUUS   S[G        US   5      S95        Mr  UR@                  RC                  [E        SUUS   S[G        US   5      U!R?                  U5      S95        M  U(       aP  U(       aI  Uu  nn Uu  nnUR@                  RC                  [I        USUU UUSSUUUU!R?                  U5      S95        GM  U(       a  GM  U(       d  GM$  U(       d  GM.  UR@                  RC                  [E        SUUS   S[G        US   5      S95        GMf     U$ ! [.         a     GN"f = f! [2         a    [4        R7                  S
U S35         GNf = f! [.         a     GNf = f)zvCompute the sync plan by comparing source and destination.

Returns:
    SyncPlan with all operations to be performed
z[One of source or dest must be a bucket path (hf://buckets/...) and the other must be local.r=   r   r   NzSource must be a directory: zScanning local directory (z files)ro   ri   zScanning remote bucket (zBucket 'z' not found, treating as empty.zComparing files (z paths)r   r   znew file (--existing)r   )r   rM   r!   r   r   r   znew filezlocal newerzremote newer)rM   r   r  r  r  r  r  r  r  r  r	  r   znot in source (--delete))r   rM   r!   r   r   r   )r   rM   r!   r   r   r   )rM   r   r  r  r  r  r  r  r  r  r	  r   )'r   r   rw   r   r   nowr   r   r   rL   rM   r   ru   r   rv   r   r   r   r)   rt   donebucket_infor"   	Exceptionr   r   loggerdebugsetkeyssortedgetr   r   r   r   r  r   r   )%r=   r   r   r   r  r  r  r	  r  r  	is_uploadis_downloadplanremote_totalr   rz   rl   r   local_filesr   r!   r   remote_filesr   	total_str	all_pathsrM   
local_inforemote_info
local_sizer   remote_sizer   bucket_file_mapr   
local_filer   s%                                        r,   _compute_sync_planr2  *  s   " $6}N#F++E0EI!&)G/$2G.GK[vww,,x||,668D  $LWW__V,
"4("IIv':':6	ww}}Z((;J<HII (9*(E$HdH%%h//)-x(8H%v :3{;K:LGTU	 )F
 KK4S5E4FgNO"y9EE		P/A#yRX/Y+$!!))(33.2H-=L*66B6N!L> 2TVIMM$<S=N<OPY{Za"bc 0Z KK23|3D2EWMN ((*+c,2C2C2E.FF	KK+C	N+;7CD9%D$.J&**40K+OO**%#)!%!+A#:(5jm(D OO**%#+!%!+A#-(5jm(D *4'
K,7)\&&+!'$.%0"-#/+8)7%1%1(7  ZKKFF&&!'!(^9%2;q>%Ba &V K_ #6*"IIv':':6	WW__T*
 *,"y9EE 6HYX^5_1HdHk%%h//*.)9X&,7)v2>2Ja~.PR	 8\9J8KI;V]^_ 6` KK23|3D2EWMN77==$$0A*0M,HdH%--h7715x0@H-v(B3{CSBTT[&\]	 1N !-H!#j(!CJ +J 7I ( ,5K)v(B3{CSBTT[&\] !- KK4S5E4FgNO ))+,s;3C3C3E/FF	KK+C	N+;7CD9%D&**40K$.J:OO**%#)!%!,Q#:)6{1~)F OO**%#-!%!,Q#-)6{1~)F(7(;(;D(A	 ,7)\*4'
K&&+!)$/%1",#.+9)6%1%1(7$3$7$7$=  ![ZZFF&&!'!']9$1*Q-$@e &x K}   # 	PLL8I;.MNO	P`  s<   5_% 7_6 ._6 `  %
_32_36#`` 
`.-`.r&  c                 $   SU R                   U R                  U R                  U R                  5       S.nUR	                  [
        R                  " U5      S-   5        U R                   H  nSUR                  UR                  UR                  S.nUR                  b  UR                  US'   UR                  b  UR                  US'   UR                  b  UR                  US	'   UR	                  [
        R                  " U5      S-   5        M     g)
z1Write a sync plan as JSONL to a file-like object.header)r   r=   r   r   r   
	operation)r   r   rM   r   Nr!   r   r   )r=   r   r   r   writejsondumpsr   r   rM   r   r!   r   r   )r&  r   r4  r   op_dicts        r,   _write_planr;  &  s     ++		^^<<>F GGDJJv%& ooiiGGii	#
 77 ggGFO>>%%'^^GM"??&&(ooGN#	

7#d*+ r/   	plan_filec                 f    [        US5       n[        X5        SSS5        g! , (       d  f       g= f)z!Save a sync plan to a JSONL file.wN)r   r;  )r&  r<  r   s      r,   
_save_planr?  C  s"    	i	D 
		s   "
0c                 |   [        U 5       nUR                  5       nSSS5        W(       d  [        SU  35      e[        R                  " US   5      nUR                  S5      S:w  a  [        S5      e[        US   US   US	   S
9nUSS  H  n[        R                  " U5      nUR                  S5      S:w  a  M0  UR                  R                  [        US   US   UR                  S5      UR                  SS5      UR                  S5      UR                  S5      S95        M     U$ ! , (       d  f       GN= f)z#Load a sync plan from a JSONL file.NzEmpty plan file: r   r   r4  z0Invalid plan file: expected header as first liner=   r   r   r  r   r6  r   rM   r!   r   ri   r   r   )r   rM   r!   r   r   r   )
r   	readlinesrw   r8  loadsr#  r   r   r   r   )r<  r   linesr4  r&  r   r:  s          r,   
_load_planrD  I  s$   	iA 
 ,YK899 ZZa!Fzz&X%KLLhF^%D ab	**T";;v+-x(V_[[({{8R0#KK6$[[8		
	  KC 
s   D,,
D;verbosec                    [        U R                  5      (       + =(       a    [        U R                  5      n[        U R                  5      =(       a    [        U R                  5      (       + nU(       Gaf  [        R                  R                  U R                  5      n[        U R                  5      nUR                  UR                  p/ n
/ nU R                   GHH  nUR                  =S:X  a    [        R                  R                  XlR                  5      nU	(       a  U	 SUR                   3OUR                  nU(       a&  [        SUR                   SUR                   S35        U
R                  X45        M  =S:X  af    U	(       a  U	 SUR                   3OUR                  nU(       a&  [        SUR                   SUR                   S35        UR                  U5        GM  S:X  d  GM  U(       d  GM"  [        S	UR                   SUR                   S35        GMK     U
(       d  U(       a  U(       az  / nU
(       a  UR                  S
[        U
5       S35        U(       a  UR                  S[        U5       S35        UR!                  SR                  U5      R#                  5       5        UR%                  UU
=(       d    SU=(       d    SS9  ggU(       GaZ  [        U R                  5      nUR                  UR                  p[        R                  R                  U R                  5      n[        R&                  " USS9  / n/ nU R                   GH  nUR                  S:X  a  [        R                  R                  XlR                  5      n[        R&                  " [        R                  R)                  U5      SS9  U(       a&  [        SUR                   SUR                   S35        UR*                  b  UR                  UR*                  U45        M  U	(       a  U	 SUR                   3OUR                  nUR                  X45        GM  UR                  S:X  aj  [        R                  R                  XlR                  5      nU(       a&  [        SUR                   SUR                   S35        UR                  U5        GM{  UR                  S:X  d  GM  U(       d  GM  [        S	UR                   SUR                   S35        GM     [        U5      S:  a7  U(       a  UR!                  S[        U5       S35        UR-                  UU5        U(       a%  U(       a  UR!                  S[        U5       S35        U H  n[        R                  R/                  U5      (       d  M)  [        R0                  " U5        [        R                  R)                  U5      nUU:w  d  Mf   [        R2                  " U5        [        R                  R)                  U5      nUU:w  a  M>  M     gg! [4         a     M  f = f)zExecute a sync plan.r   ro   z  Uploading: z ()r   z  Deleting: r   z  Skipping: z
uploading z filesz	deleting z, N)addr   T)exist_okr   z  Downloading: r   zDownloading z	Deleting z local files)r   r=   r   rL   rM   r   ru   r   rv   r   r   r   printr   r   rt   r  
capitalizebatch_bucket_filesmakedirsdirnamer   download_bucket_filesexistsremovermdirr   )r&  r   rE  r  r$  r%  r   rz   rl   r   	add_filesdelete_pathsr   r1  remote_pathr   download_filesdelete_files	file_pathparents                       r,   _execute_planrZ  t  s   #DKK00O_TYY5OI!$++.Qtyy7Q3QKWW__T[[1
"499-"IIv':':6 ;=	"$//B))!#j''!BJ;AVHAbggY"7rwwKbggYb1EF$$j%>?;AVHAbggY"7rwwKRWWIR		{!DE ''4wwL	BII;a@A "" LL:c)n-=V!DELL9S->,?v!FGDIIe,779:""%#+t #  % 
"4;;/"IIv':':6WW__TYY/
 	J. EG"$//ByyJ&WW\\*gg>
BGGOOJ7$GOBGG9BryykCD>>-"))2>>:*FG;AVHAbggY"7rwwK"));*CDh&WW\\*gg>
L	BII;a@A##J/f$RWWIR		{!<=' ", ~"l3~+>*?vFG%%i@ lKK)C$5#6lCD%Iww~~i((		)$3
*(!#!8 
* &U 
f # s   ;5X>>
YYc                     U R                  5       n[        SU R                   SU R                   35        [        SUS    35        [        SUS    35        [        SUS    35        [        S	US
    35        g)z!Print a summary of the sync plan.zSync plan: z -> z  Uploads: r   z  Downloads: r   z  Deletes: r   z	  Skips: r   N)r   rJ  r=   r   )r&  r   s     r,   _print_plan_summaryr\    s~    llnG	K}D
45	K	*+
,-	M'+./
01	K	*+
,-	Igg&'
()r/   )r   r  r  r  r	  includeexcludefilter_fromr&  applydry_runrE  quiettokenr]  r^  r_  r`  ra  rb  rc  c                   Ub  SSK Jn  U" US9nU(       GaA  U (       d  U(       a  [        S5      eUb  [        S5      eU(       a  [        S5      eU(       a  [        S5      eU(       a  [        S	5      eU(       a  [        S
5      eU	(       a  [        S5      eU
(       a  [        S5      eU(       a  [        S5      eU(       a  [        S5      eU(       a  [        S5      e[        U5      n[	        U(       + S9nU(       d  [        U5        [        S5        U(       a
  [        5          [        UX.US9  U(       a
  [        5         U(       d  [        S5        U$ U (       a  U(       d  [        S5      e[        U 5      n[        U5      nU(       a  U(       a  [        S5      eU(       d  U(       d  [        S5      eU(       a  U(       a  [        S5      eU(       a  U(       a  [        S5      eU(       a  U(       a  [        S5      eU(       aW  [        R                  R                  U5      (       a2  [        R                  R                  U5      (       d  [        SU 35      eO2[        R                  R                  U 5      (       d  [        SU  35      eSnU
(       a  [        U
5      n[!        UU	US9n[	        U(       + =(       a    U(       + S9n[#        U UUUUUUUUUS9
nU(       a  [%        U[&        R(                  5        U$ U(       a.  [+        UU5        U(       d  [        U5        [        SU 35        U$ U(       d  [        U5        UR-                  5       nUS   S :X  a&  US!   S :X  a  US"   S :X  a  U(       d  [        S#5        U$ U(       d  [        S$5        U(       a
  [        5          [        UX.US9  U(       a
  [        5         U(       d  [        S5        U$ ! U(       a  [        5         f f = f! U(       a  [        5         f f = f)%a  Sync files between a local directory and a bucket.

This is equivalent to the ``hf buckets sync`` CLI command. One of ``source`` or ``dest`` must be a bucket path
(``hf://buckets/...``) and the other must be a local directory path.

Args:
    source (`str`, *optional*):
        Source path: local directory or ``hf://buckets/namespace/bucket_name(/prefix)``.
        Required unless using ``apply``.
    dest (`str`, *optional*):
        Destination path: local directory or ``hf://buckets/namespace/bucket_name(/prefix)``.
        Required unless using ``apply``.
    api ([`HfApi`]):
        The HfApi instance to use for API calls.
    delete (`bool`, *optional*, defaults to `False`):
        Delete destination files not present in source.
    ignore_times (`bool`, *optional*, defaults to `False`):
        Skip files only based on size, ignoring modification times.
    ignore_sizes (`bool`, *optional*, defaults to `False`):
        Skip files only based on modification times, ignoring sizes.
    existing (`bool`, *optional*, defaults to `False`):
        Skip creating new files on receiver (only update existing files).
    ignore_existing (`bool`, *optional*, defaults to `False`):
        Skip updating files that exist on receiver (only create new files).
    include (`list[str]`, *optional*):
        Include files matching patterns (fnmatch-style).
    exclude (`list[str]`, *optional*):
        Exclude files matching patterns (fnmatch-style).
    filter_from (`str`, *optional*):
        Path to a filter file with include/exclude rules.
    plan (`str`, *optional*):
        Save sync plan to this JSONL file instead of executing.
    apply (`str`, *optional*):
        Apply a previously saved plan file. When set, ``source`` and ``dest`` are not needed.
    dry_run (`bool`, *optional*, defaults to `False`):
        Print sync plan to stdout as JSONL without executing.
    verbose (`bool`, *optional*, defaults to `False`):
        Show detailed per-file operations.
    quiet (`bool`, *optional*, defaults to `False`):
        Suppress all output and progress bars.
    token (Union[bool, str, None], optional):
        A valid user access token. If not provided, the locally saved token will be used.

Returns:
    [`SyncPlan`]: The computed (or loaded) sync plan.

Raises:
    `ValueError`: If arguments are invalid (e.g., both paths are remote, conflicting options).

Example:
    ```python
    >>> from huggingface_hub import HfApi
    >>> api = HfApi()

    # Upload local directory to bucket
    >>> api.sync_bucket("./data", "hf://buckets/username/my-bucket")

    # Download bucket to local directory
    >>> api.sync_bucket("hf://buckets/username/my-bucket", "./data")

    # Sync with delete and filtering
    >>> api.sync_bucket(
    ...     "./data",
    ...     "hf://buckets/username/my-bucket",
    ...     delete=True,
    ...     include=["*.safetensors"],
    ... )

    # Dry run: preview what would be synced
    >>> plan = api.sync_bucket("./data", "hf://buckets/username/my-bucket", dry_run=True)
    >>> plan.summary()
    {'uploads': 3, 'downloads': 0, 'deletes': 0, 'skips': 1, 'total_size': 4096}

    # Save plan for review, then apply
    >>> api.sync_bucket("./data", "hf://buckets/username/my-bucket", plan="sync-plan.jsonl")
    >>> api.sync_bucket(apply="sync-plan.jsonl")
    ```
Nr   r   )rc  z,Cannot specify source/dest when using apply.z#Cannot specify both plan and apply.z'Cannot specify delete when using apply.z-Cannot specify ignore_times when using apply.z-Cannot specify ignore_sizes when using apply.z(Cannot specify include when using apply.z(Cannot specify exclude when using apply.z,Cannot specify filter_from when using apply.z)Cannot specify existing when using apply.z0Cannot specify ignore_existing when using apply.z(Cannot specify dry_run when using apply.)enabledzExecuting plan...)rE  r  zSync completed.z7Both source and dest are required (unless using apply).z?Remote to remote sync is not supported. One path must be local.z?One of source or dest must be a bucket path (hf://buckets/...).z2Cannot specify both ignore_times and ignore_sizes.z1Cannot specify both existing and ignore_existing.z%Cannot specify both dry_run and plan.z!Destination must be a directory: z&Source must be an existing directory: r   )
r=   r   r   r   r  r  r  r	  r  r  zPlan saved to: r   r   r   r   zNothing to sync.z
Syncing...)hf_apir   rw   rD  r   r\  rJ  r   rZ  r   r   rL   rM   rP  r   r   r   r2  r;  sysstdoutr?  r   )r=   r   r   r   r  r  r  r	  r]  r^  r_  r&  r`  ra  rE  rb  rc  r   	sync_planr  source_is_bucketdest_is_bucketr   r  r   s                            r,   sync_bucket_internalrl    sg   F !% TKLLBCCFGGLMMLMMGHHGHHKLLHIIOPPGHHu%	I.	*%&!#	')S&I$&#$ RSS&v.$T*NNZ[[NZ[[MNNOLMM4@AA 77>>$d(;(;@GHHww}}V$$EfXNOO L)+6"  !N E	 9'k:F"!!'%I Iszz*9d#	*OD6*+ I&!GyQ7;#71#<ASWXAX$%l#ifE " G $& z  " s   )O /O6 O36P
)FFFFFNN)FN)NN)Kr4   r   r8  rI   rL   r   rg  rO   collections.abcr   dataclassesr   r   r   r   pathlibr   typingr	   r
   r   ri   r   r   errorsr   utilsr   r   r   r   r   r   r   utils._hf_urisr   rf  r   
get_loggerr0   r  BUCKET_PREFIXr  r   r;   rW   r^   rb   rf   r}   r   r5   ru   r7   r   r   r   r   r   r   r   r8   floatr   r   r   r   r  r2  r;  r?  rD  rZ  r\  rl  r&   r/   r,   <module>rw     sf  
    	  
  $ ( '  . .   '   /  
		H	%    ' ' '@ 
 
 
* - - -    $    $ $ $N P P P2 
 
 
6CC CE C,(# ($ (  	* 	* 	* 
 
 
8. .bC DsCx,A :*c *eCJ/$6 *7# 7(5c53I*J 7,2G 2 2S 2XeTWY\^cehThNiEj 2DPE Pc P$ #ES
ES ()ES 	ES
 ES ES ES ES ES ES ES ES tES ESX !+/tt
t 
t 	t
 t t t t "D(t $Jt tx,h ,d ,:X # $ ## #( #Va aw a asUYz aei aH*h *4 *  n
 ! $ $"#%n$Jn
*n 
	n
 n n n n n #Yn #Yn tn *n :n n  !n" #n$ #:%n& 'nr/   