
    hX                        S SK J r Jr  S SKrS SKrS SK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   S SKJr  SS	KJrJr  SS
KJr  SSKJr  SSKJr  SSK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+  S SK,J-r.  S SK/J0r0J1r1  S SK2J-r3  \" S5       " S S\5      5       r6S r7\6Rp                  \6l        g! \ a	    S SKJr   Nf = f! \4 a    S\S   l5         NOf = f)    )datetime	timedeltaN)
HTTPStatus)Path)AnyCallableDictIterableOptionalTupleUnion)islice)cast   )Clientregister_client_class)implementation_registry)FileCacheMode)MissingCredentialsError   )AzureBlobPath)HttpResponseErrorResourceNotFoundError)AzureNamedKeyCredential)
BlobPrefixBlobSasPermissionsBlobServiceClientBlobPropertiesContentSettingsgenerate_blob_sas)SharedKeyCredentialPolicy)DataLakeServiceClientFilePropertiesFazurec                     ^  \ rS rSrSrSSSSSSS\R                  4S\\   S\\	   S\\   S\S   S	\S
   S\\
\\4      S\\
\\R                  4      S\\   4U 4S jjjrS\S\\   4S jrS\S\4S jrS\S\
SS\\\	4   4   4S jr\S\4S j5       rS\S\
\\R                  4   S\4S jrS\S\\   4S jrS\S\4S jr S+S\S\S\\\\4      4S jjr S,S\S\S\S\4S  jjr S-S\S!\S"\SS4S# jjr S,S\S$\SS4S% jjr!S\
\\R                  4   S\S\4S& jr"S\S\4S' jr# S.S\S(\$S\4S) jjr%S*r&U =r'$ )/AzureBlobClient/   a
  Client class for Azure Blob Storage which handles authentication with Azure for
[`AzureBlobPath`](../azblobpath/) instances. See documentation for the
[`__init__` method][cloudpathlib.azure.azblobclient.AzureBlobClient.__init__] for detailed
authentication options.
Naccount_url
credentialconnection_stringblob_service_clientr   data_lake_clientr"   file_cache_modelocal_cache_dircontent_type_methodc	                 |  > [         T	U ]  UUUS9  Uc  [        R                  " SS5      nSU l        Ub  X@l        Uc  [        UR                  [        5      (       d  UR                  O3[        UR                  R                  UR                  R                  5      n[        U R
                  R                  R                  SSS5      US9U l        GOcXPl        GO[Ub  XPl        Uc  [        UR                  [        5      (       d  UR                  O3[        UR                  R                  UR                  R                  5      n[!        U R                  R                  R                  SSS5      US9U l        OUb3  [         R"                  " X2S9U l        [        R"                  " X2S9U l        OUbw  SU;   a.  [!        UR                  SS5      US9U l        [        XS9U l        ONSU;   a.  [!        XS9U l        [        UR                  SS5      US9U l        O[!        XS9U l        O[%        S	5      eSU l        g)
a{  Class constructor. Sets up a [`BlobServiceClient`](
https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python).
Supports the following authentication methods of `BlobServiceClient`.

- Environment variable `""AZURE_STORAGE_CONNECTION_STRING"` containing connecting string
with account credentials. See [Azure Storage SDK documentation](
https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python#copy-your-credentials-from-the-azure-portal).
- Connection string via `connection_string`, authenticated either with an embedded SAS
token or with credentials passed to `credentials`.
- Account URL via `account_url`, authenticated either with an embedded SAS token, or with
credentials passed to `credentials`.
- Instantiated and already authenticated [`BlobServiceClient`](
https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python) or
[`DataLakeServiceClient`](https://learn.microsoft.com/en-us/python/api/azure-storage-file-datalake/azure.storage.filedatalake.datalakeserviceclient).

If multiple methods are used, priority order is reverse of list above (later in list takes
priority). If no methods are used, a [`MissingCredentialsError`][cloudpathlib.exceptions.MissingCredentialsError]
exception will be raised raised.

Args:
    account_url (Optional[str]): The URL to the blob storage account, optionally
        authenticated with a SAS token. See documentation for [`BlobServiceClient`](
        https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python).
    credential (Optional[Any]): Credentials with which to authenticate. Can be used with
        `account_url` or `connection_string`, but is unnecessary if the other already has
        an SAS token. See documentation for [`BlobServiceClient`](
        https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python)
        or [`BlobServiceClient.from_connection_string`](
        https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python#from-connection-string-conn-str--credential-none----kwargs-).
    connection_string (Optional[str]): A connection string to an Azure Storage account. See
        [Azure Storage SDK documentation](
        https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python#copy-your-credentials-from-the-azure-portal).
    blob_service_client (Optional[BlobServiceClient]): Instantiated [`BlobServiceClient`](
        https://docs.microsoft.com/en-us/python/api/azure-storage-blob/azure.storage.blob.blobserviceclient?view=azure-python).
    data_lake_client (Optional[DataLakeServiceClient]): Instantiated [`DataLakeServiceClient`](
        https://learn.microsoft.com/en-us/python/api/azure-storage-file-datalake/azure.storage.filedatalake.datalakeserviceclient).
        If None and `blob_service_client` is passed, we will create based on that.
        Otherwise, will create based on passed credential, account_url, connection_string, or AZURE_STORAGE_CONNECTION_STRING env var
    file_cache_mode (Optional[Union[str, FileCacheMode]]): How often to clear the file cache; see
        [the caching docs](https://cloudpathlib.drivendata.org/stable/caching/) for more information
        about the options in cloudpathlib.eums.FileCacheMode.
    local_cache_dir (Optional[Union[str, os.PathLike]]): Path to directory to use as cache
        for downloaded files. If None, will use a temporary directory. Default can be set with
        the `CLOUDPATHLIB_LOCAL_CACHE_DIR` environment variable.
    content_type_method (Optional[Callable]): Function to call to guess media type (mimetype) when
        writing a file to the cloud. Defaults to `mimetypes.guess_type`. Must return a tuple (content type, content encoding).
)r.   r/   r-   NAZURE_STORAGE_CONNECTION_STRINGz.blob.z.dfs.r   )r(   r)   )conn_strr)   ziAzureBlobClient does not support anonymous instantiation. Credentials are required; see docs for options.)super__init__osgetenvr,   service_client
isinstancer)   BlobSharedKeyCredentialPolicyr   account_nameaccount_keyr"   urlreplace!DataLakeSharedKeyCredentialPolicyr   from_connection_stringr   _hns_enabled)
selfr(   r)   r*   r+   r,   r-   r.   r/   	__class__s
            Y/home/james-whalen/.local/lib/python3.13/site-packages/cloudpathlib/azure/azblobclient.pyr4   AzureBlobClient.__init__7   sf   t 	+ 3+ 	 	
 $ "		*KT R  	 *"5  ' &+668U  (22 1+66CC+66BB  )> $ 3 3 7 7 ? ?'ST U))%
 )9%)$4!"* &(335V  %// 1(33@@(33??  '8 $ 5 5 9 9 A A'8UV W)'#
 *"3"J"J*#D %:$P$P*%D! $+%&7 + 3 3GX FS]'# )> +)% [(&7 +'# )> + 3 3Hg FS])%
 '8 +'#
 *B 
 -1    
cloud_pathreturnc                 v   U R                   c>   U R                  R                  5       nUR                  SS5      U l         U R                   $ U R                   $ ! [         a    U R                  U5      s $ [         a:  nUR                  [        R                  :X  a  U R                  U5      s S nA$ e S nAff = f)Nis_hns_enabledF)
r@   r7   get_account_informationgetr   _check_hns_root_metadatar   status_coder   	FORBIDDEN)rA   rF   account_infoerrors       rC   
_check_hnsAzureBlobClient._check_hns   s    $#22JJL$0$4$45Eu$M!    t    ) A44Z@@$ $$
(<(<<88DD	s)   1A B85	B8>.B3,B82B33B8c                    U R                   R                  UR                  SS9nUR                  5       =(       a-    UR	                  5       R
                  R                  SS5      S:H  U l        [        [        U R                  5      $ )N/	containerblobhdi_isfolderFtrue)
r7   get_blob_clientrV   existsget_blob_propertiesmetadatarK   r@   r   bool)rA   rF   root_dirs      rC   rL   (AzureBlobClient._check_hns_root_metadata   sx    &&66AUAU\_6` OO ],,.77;;NERV\\ 	
 D$++,,rE   r   r#   c                    U R                  U5      (       ay  U R                  R                  UR                  5      nUb)  UR	                  UR
                  5      R                  5       nWR                  SSS 05      R                  S5      US'   U$ U R                  R                  UR                  UR
                  S9nUR                  5       nUR                  R                  US'   U$ )Ncontent_settingscontent_typerU   )rQ   r,   get_file_system_clientrV   get_file_clientrW   get_file_propertiesrK   r7   rZ   r\   rb   rc   )rA   rF   fsc
propertiesrW   s        rC   _get_metadataAzureBlobClient._get_metadata   s     ??:&& ''>>z?S?STC 00AUUW
 *4"^T$:*c.! ~&  &&66$..Z__ 7 D 113J)3)D)D)Q)QJ~&rE   c                 0    [        [        U 5      S-   5      $ )Nz.part)r   str)
local_paths    rC   _partial_filename!AzureBlobClient._partial_filename  s    C
Og-..rE   rm   c                    U R                   R                  UR                  UR                  S9nUR	                  5       n[        U5      nUR                  R                  SSS9   U R                  U5      nUR                  S5       nUR                  U5        S S S 5        UR                  U5        U$ ! , (       d  f       N!= f!   WR                  5       (       a  UR                  5         e = f)NrU   T)exist_okparentswb)r7   rZ   rV   rW   download_blobr   parentmkdirrn   openreadintor=   r[   unlink)rA   rF   rm   rW   download_streampartial_local_pathdatas          rC   _download_fileAzureBlobClient._download_file  s     ""22 ** 3 
 ,,.*%
t<
	!%!7!7
!C#((.$((. / &&z2  /.	!((**"))+s$   %"C B4C 4
C>C (C-c                    UR                   (       d  g U R                  U5      nUR                  SS5      (       d'  UR                  S0 5      R                  SS5      (       a  S$ S$ ! [         a    UR                   nU(       a  UR	                  S5      (       d  US-  nU R
                  R                  UR                  5      n [        UR                  US95         g! [         a      g f = ff = f)	Ndiris_directoryFr]   rX   filerT   name_starts_with)rW   ri   rK   r   endswithr7   get_container_clientrV   next
list_blobsStopIteration)rA   rF   metaprefixcontainer_clients        rC   _is_file_or_dirAzureBlobClient._is_file_or_dir#  s    	%%j1D
 88NE2288J+//FF  	 % 	__Ffooc22#  $22GG
H\H\]%00&0IJ  	s1   AA' %A' 'AC1C
C-)C1,C--C1c                     UR                   (       d3  U R                  R                  UR                  5      R	                  5       $ U R                  U5      S;   $ )N)r   r   )rW   r7   r   rV   r[   r   )rA   rF   s     rC   _existsAzureBlobClient._existsB  sE    &&;;J<P<PQXXZZ##J/?BBrE   	recursivec              #   t  #    UR                   (       d  U R                  R                  5        Hx  nU R                  UR                   UR
                   35      S4v   U(       d  M9  U R                  U R                  UR                   UR
                   35      SS9 S h  vN   Mz     g U R                  R                  UR                   5      nUR                  nU(       a  UR                  S5      (       d  US-  nU R                  U5      (       a  U R                  R                  UR                   5      nUR                  UR                  US9nU HG  nU R                  UR                   UR                    SUR
                   35      UR                  4v   MI     g U(       d  UR                  US9n	OUR!                  US9n	U	 Hg  n
U
R
                  R#                  S5      nU R                  UR                   UR                    SU 35      nUU(       d  [%        U
[&        5      OS4v   Mi     g  GN7f)NTr   rT   )pathr   r   F)rV   r7   list_containers	CloudPathcloud_prefixname	_list_dirr   rW   r   rQ   r,   rd   	get_pathsr   
walk_blobsr   rstripr8   r   )rA   rF   r   rV   r   r   file_system_clientpathsr   blobsrW   	blob_pathblob_cloud_paths                rC   r   AzureBlobClient._list_dirI  s     ##!00@@B	nn
(?(?'@@P%QRTXXX >>NNj&=&=%>y~~>N#OP\` *    C ..CCJDXDXY&//#..cMF??:&&!%!6!6!M!MjNbNb!c&00jooQZ0[Enn!../
0D0D/EQtyykR$$% %  (33V3L(33V3L II,,S1	"&..!../
0D0D/EQykR# &$ tZ0  5s   BH8!H5"FH8srcdst
remove_srcc                 :   X:X  ap  U R                   R                  UR                  UR                  S9nUR	                  [        [        [        R                  " 5       R                  5       5      S9S9  U$ U(       Ga  UR                  UR                  L a  U R                  U5      (       a  U R                  R                  UR                  5      nUR                  5       (       aE  UR                  UR                  5      R!                  UR                   SUR                   35        U$ UR"                  R%                  SSS9  UR'                  UR                  5      R)                  UR                   SUR                   35         U$ U R                   R                  UR                  UR                  S9nU R                   R                  UR                  UR                  S9nUR+                  UR,                  5        U(       a  U R/                  U5        U$ )NrU   )last_modified)r]   rT   T)rr   rq   )r7   rZ   rV   rW   set_blob_metadatadictrl   r   utcnow	timestampclientrQ   r,   rd   is_dirget_directory_clientrename_directoryru   rv   re   rename_filestart_copy_from_urlr<   _remove)rA   r   r   r   blob_clientrg   targetsources           rC   
_move_fileAzureBlobClient._move_filez  s    :--==--chh > K ))C0A0K0K0M,NO * 0 
' SZZ3::54??3;O;O''>>s}}MCzz||((2CCs}}oUVWZW_W_V`Dab 
 

   =##CHH-99S]]O1SXXJ:WX 
 ((883==WZW_W_8`F((883==WZW_W_8`F&&vzz2S!
rE   rr   rq   c                    U R                  U5      (       a  U R                  R                  UR                  5      nUR	                  UR
                  5      nU(       d#  UR                  5       (       a  [        SU 35      eU(       d9  U R                  UR                  5      (       d  [        SUR                   S35      eUR                  5         g g )NzDirectory already exists: z!Parent directory does not exist (z4). To create parent directories, use `parents=True`.)rQ   r,   rd   rV   r   rW   r[   FileExistsErrorr   ru   FileNotFoundErrorcreate_directory)rA   rF   rr   rq   r   directory_clients         rC   _mkdirAzureBlobClient._mkdir  s     ??:&&!%!6!6!M!MjNbNb!c1FFzW 0 7 7 9 9%(B:,&OPP||J$5$566+;J<M<M;N  OC  D  --/ rE   
missing_okc                 x   U R                  U5      nUS:X  a  U R                  U5      (       a,  [        U R                  UR                  UR
                  5        g S U R                  USS9 5       nU R                  R                  UR                  5      n[        [        US5      5      =n(       a.  UR                  " U6   [        [        US5      5      =n(       a  M-  g g US:X  a?  U R                  R                  UR                  UR
                  S9nUR                  5         g U(       d  [        SU 35      eg )	Nr   c              3   P   #    U  H  u  pU(       a  M  UR                   v   M     g 7f)N)rW   ).0br   s      rC   	<genexpr>*AzureBlobClient._remove.<locals>.<genexpr>  s      (R91Z`(Rs   &&Tr      r   rU   zFile does not exist: )r   rQ   _hns_rmtreer,   rV   rW   r   r7   r   tupler   delete_blobsrZ   delete_blobr   )rA   rF   r   file_or_dirr   r   batchrW   s           rC   r   AzureBlobClient._remove  s!   **:6%z**D11:3G3GY(,zT(RE  $22GG
H\H\] s!344%4 --u5 !s!344%44F"&&66$..Z__ 7 D  '*?
|(LMM rE   c                 v   U R                   R                  UR                  UR                  S9n0 nU R                  b*  U R	                  [        U5      5      u  pVUb  XTS'   Ub  XdS'   [        S0 UD6n[        U5      R                  S5       nUR                  USUS9  S S S 5        U$ ! , (       d  f       U$ = f)NrU   rc   content_encodingrbT)	overwriterb    )
r7   rZ   rV   rW   r/   rl   r   r   rw   upload_blob)	rA   rm   rF   rW   
extra_argsrc   r   rb   r|   s	            rC   _upload_fileAzureBlobClient._upload_file  s     ""22 ** 3 
 
##/-1-E-Ec*o-V*L'-9>*+1A-.*8Z8*""4(DTTDTU )  )( s   B))
B8c                 v    U R                   R                  UR                  UR                  S9nUR                  $ )NrU   )r7   rZ   rV   rW   r<   )rA   rF   r   s      rC   _get_public_urlAzureBlobClient._get_public_url  s8    ))99 ** : 
 rE   expire_secondsc                 "   [        U R                  R                  UR                  UR                  U R                  R
                  R                  [        SS9[        R                  " 5       [        US9-   S9nU R                  U5       SU 3nU$ )NT)read)seconds)container_name	blob_namer;   
permissionexpiry?)r    r7   r:   rV   rW   r)   r;   r   r   r   r   r   )rA   rF   r   	sas_tokenr<   s        rC   _generate_presigned_url'AzureBlobClient._generate_presigned_url  s     &,,%// oo++66BB)t4??$y'HH
	 %%j12!I;?
rE   )r@   r,   r7   )F)T)FF)i  )(__name__
__module____qualname____firstlineno____doc__	mimetypes
guess_typer   rl   r   r   r   r5   PathLiker   r4   r   r^   rQ   rL   r	   ri   staticmethodr   rn   r}   r   r   r
   r   r   r   r   r   r   r   intr   __static_attributes____classcell__)rB   s   @rC   r&   r&   /   s    &*$(+/=A>B?C=A2;2F2FU1c]U1 SMU1 $C=	U1
 &&9:U1 ##:;U1 "%](:";<U1 "%R[[(8"9:U1 &h/U1 U1n!] !x~ !$-= -T -'	!14S>A	B4 / / /'5:3;K5L	6- HSM >C- CD C <A/'/48/	%t+,	-/d JN! !'4!BF!	!H RW'26JN	*N- NT NT N0R[[ 01?L	.- C  @G'9<	 rE   r&   c                 h    U R                  U5      nUR                  U5      nUR                  5         g)zStateless implementation so can be used in test suite cleanup as well.

If hierarchical namespace is enabled, delete the directory and all its contents.
(The non-HNS version is implemented in `_remove`, but will leave empty folders in HNS).
N)rd   r   delete_directory)r,   rV   	directoryr   r   s        rC   r   r     s2     *@@K)>>yI%%'rE   )9r   r   r   r5   httpr   pathlibr   typingr   r   r	   r
   r   r   r   	itertoolsr   r   ImportErrortyping_extensionsr   r   r   	cloudpathr   enumsr   
exceptionsr   
azblobpathr   azure.core.exceptionsr   r   azure.core.credentialsr   azure.storage.blobr   r   r   r   r   r    )azure.storage.blob._shared.authenticationr!   r9   azure.storage.filedatalaker"   r#   1azure.storage.filedatalake._shared.authenticationr>   ModuleNotFoundErrordependencies_loadedr&   r   r   r   rE   rC   <module>r     s    (  	   H H H ' 3 / ! 0 %AN>  Q wCf C  CL( !0 9 9 m  '&'@  A;@G$8As#   B: 2C :C	C	CC