+
    BiӨ                     f   R t ^ RIt^ RIt^ RIt^ RIt^RIHt ^RIHt  ^ RI	H
t
  ^ RIt^tRR] R2/tRR lt ! R	 R
4      t ! R R4      t ! R R4      t ! R R4      tR tR t ! R R4      t ! R R]4      t ! R R]4      t ! R R]4      tR#   ] d    Rt
 Lzi ; i  ] d    Rt Li ; i)z1
The classes that actually handle the downloads.
N	parse_url)__version__)tqdmz
User-Agentpoochz! (https://www.fatiando.org/pooch)c           
         R\         R\        R\        R\        R\        /p\	        V 4      pVR,          V9  d+   \        RVR,           RV  R	VP                  4        R
24      hW#R,          ,          ! VR7      pV# )aK  
Choose the appropriate downloader for the given URL based on the protocol.

Parameters
----------
url : str
    A URL (including protocol).
progressbar : bool or an arbitrary progress bar object
    If True, will print a progress bar of the download to standard error
    (stderr). Requires `tqdm <https://github.com/tqdm/tqdm>`__ to be
    installed. Alternatively, an arbitrary progress bar object can be
    passed. See :ref:`custom-progressbar` for details.

Returns
-------
downloader
    A downloader class, like :class:`pooch.HTTPDownloader`,
    :class:`pooch.FTPDownloader`, or :class: `pooch.SFTPDownloader`.

Examples
--------

>>> downloader = choose_downloader("http://something.com")
>>> print(downloader.__class__.__name__)
HTTPDownloader
>>> downloader = choose_downloader("https://something.com")
>>> print(downloader.__class__.__name__)
HTTPDownloader
>>> downloader = choose_downloader("ftp://something.com")
>>> print(downloader.__class__.__name__)
FTPDownloader
>>> downloader = choose_downloader("doi:DOI/filename.csv")
>>> print(downloader.__class__.__name__)
DOIDownloader

ftphttpshttpsftpdoiprotocolzUnrecognized URL protocol 'z' in 'z'. Must be one of .)progressbar)FTPDownloaderHTTPDownloaderSFTPDownloaderDOIDownloaderr   
ValueErrorkeys)urlr   known_downloaders
parsed_url
downloaders   &&   O/var/www/html/photoedit/myenv/lib/python3.14/site-packages/pooch/downloaders.pychoose_downloaderr   -   s    L 	}} 3J*%66)*Z*@)Au M/4467q:
 	
 #j#9:{SJ    c                   8   a  ] tR t^dt o RtRR ltRR ltRtV tR# )r   a
  
Download manager for fetching files over HTTP/HTTPS.

When called, downloads the given file URL into the specified local file.
Uses the :mod:`requests` library to manage downloads.

Use with :meth:`pooch.Pooch.fetch` or :func:`pooch.retrieve` to customize
the download of files (for example, to use authentication or print a
progress bar).

Parameters
----------
progressbar : bool or an arbitrary progress bar object
    If True, will print a progress bar of the download to standard error
    (stderr). Requires `tqdm <https://github.com/tqdm/tqdm>`__ to be
    installed. Alternatively, an arbitrary progress bar object can be
    passed. See :ref:`custom-progressbar` for details.
chunk_size : int
    Files are streamed *chunk_size* bytes at a time instead of loading
    everything into memory at one. Usually doesn't need to be changed.
**kwargs
    All keyword arguments given when creating an instance of this class
    will be passed to :func:`requests.get`.

Examples
--------

Download one of the data files from the Pooch repository:

>>> import os
>>> from pooch import __version__, check_version
>>> url = "https://github.com/fatiando/pooch/raw/{}/data/tiny-data.txt"
>>> url = url.format(check_version(__version__, fallback="main"))
>>> downloader = HTTPDownloader()
>>> # Not using with Pooch.fetch so no need to pass an instance of Pooch
>>> downloader(url=url, output_file="tiny-data.txt", pooch=None)
>>> os.path.exists("tiny-data.txt")
True
>>> with open("tiny-data.txt") as f:
...     print(f.read().strip())
# A tiny data file for test purposes only
1  2  3  4  5  6
>>> os.remove("tiny-data.txt")

Authentication can be handled by passing a user name and password to
:func:`requests.get`. All arguments provided when creating an instance of
the class are forwarded to :func:`requests.get`. We'll use
``auth=(username, password)`` to use basic HTTPS authentication. The
https://httpbin.org website allows us to make a fake a login request using
whatever username and password we provide to it:

>>> user = "doggo"
>>> password = "goodboy"
>>> # httpbin will ask for the user and password we provide in the URL
>>> url = f"https://httpbin.org/basic-auth/{user}/{password}"
>>> # Trying without the login credentials causes an error
>>> downloader = HTTPDownloader()
>>> try:
...     downloader(url=url, output_file="tiny-data.txt", pooch=None)
... except Exception:
...     print("There was an error!")
There was an error!
>>> # Pass in the credentials to HTTPDownloader
>>> downloader = HTTPDownloader(auth=(user, password))
>>> downloader(url=url, output_file="tiny-data.txt", pooch=None)
>>> with open("tiny-data.txt") as f:
...     for line in f:
...         print(line.rstrip())
{
  "authenticated": true,
  "user": "doggo"
}
>>> os.remove("tiny-data.txt")

c                t    W0n         Wn        W n        V P                  R J d   \        f   \	        R4      hR# R# TN2Missing package 'tqdm' required for progress bars.)kwargsr   
chunk_sizer   r   )selfr   r"   r!   s   &&&,r   __init__HTTPDownloader.__init__   s8    &$t#QRR )5#r   c           	        ^ RI pV'       dN   V P                  P                  R\        4      pVP	                  WRR7      p\        VP                  ^8H  4      pV# V P                  P                  4       p	V	P                  R\        4      pV	P                  RR4       \        VR4      '       * p
V
'       d   \        VR4      p VP                  ! V3RV/V	B pVP                  4        VP                  V P                  R7      p\        VP                   P                  R	^ 4      4      pV P"                  RJ d/   \        \$        P&                  R
8H  4      p\)        V^OVRRRR7      pM$V P"                  '       d   V P"                  pWn        V F]  pV'       g   K  VP-                  V4       VP/                  4        V P"                  '       g   KB  XP1                  V P                  4       K_  	  V P"                  '       d2   XP3                  4        VP1                  V4       VP5                  4        V
'       d   VP5                  4        R#   T
'       d   TP5                  4        i i ; i)a  
Download the given URL over HTTP to the given output file.

Uses :func:`requests.get`.

Parameters
----------
url : str
    The URL to the file you want to download.
output_file : str or file-like object
    Path (and file name) to which the file will be downloaded.
pooch : :class:`~pooch.Pooch`
    The instance of :class:`~pooch.Pooch` that is calling this method.
check_only : bool
    If True, will only check if a file exists on the server and
    **without downloading the file**. Will return ``True`` if the file
    exists and ``False`` otherwise.

Returns
-------
availability : bool or None
    If ``check_only==True``, returns a boolean indicating if the file
    is available on the server. Otherwise, returns ``None``.

NtimeoutT)r'   allow_redirectsstreamwritew+b)r"   zcontent-lengthwin32Btotalncolsasciiunit
unit_scaleleave)requestsr!   getDEFAULT_TIMEOUTheadboolstatus_codecopypop
setdefaulthasattropenraise_for_statusiter_contentr"   intheadersr   sysplatformr   r/   r*   flushupdateresetclose)r#   r   output_filer   
check_onlyr5   r'   response	availabler!   ispathcontentr/   	use_asciiprogresschunks   &&&&&           r   __call__HTTPDownloader.__call__   s   : 	kkooiAG}}S4}PHX11S89I!!#**Y8(D)['22{E2K(	$||CCCFCH%%'++t+GG((,,-=qABE4' !!89	## !!!++!& 5%%e,%%'''' !8 !  & !!# !!# s%   B5I
 8I
 0I
 0I
 ?1I
 
I%)r"   r!   r   N)F   F	__name__
__module____qualname____firstlineno____doc__r$   rS   __static_attributes____classdictcell____classdict__s   @r   r   r   d   s     JXSV Vr   r   c                   8   a  ] tR tRt o RtRR ltRR ltRtV tR# )	r   i  a  
Download manager for fetching files over FTP.

When called, downloads the given file URL into the specified local file.
Uses the :mod:`ftplib` module to manage downloads.

Use with :meth:`pooch.Pooch.fetch` or :func:`pooch.retrieve` to customize
the download of files (for example, to use authentication or print a
progress bar).

Parameters
----------
port : int
    Port used for the FTP connection.
username : str
    User name used to login to the server. Only needed if the server
    requires authentication (i.e., no anonymous FTP).
password : str
    Password used to login to the server. Only needed if the server
    requires authentication (i.e., no anonymous FTP). Use the empty string
    to indicate no password is required.
account : str
    Some servers also require an "account" name for authentication.
timeout : int
    Timeout in seconds for ftp socket operations, use None to mean no
    timeout.
progressbar : bool
    If True, will print a progress bar of the download to standard error
    (stderr). Requires `tqdm <https://github.com/tqdm/tqdm>`__ to be
    installed. **Custom progress bars are not yet supported.**
chunk_size : int
    Files are streamed *chunk_size* bytes at a time instead of loading
    everything into memory at one. Usually doesn't need to be changed.

Nc                    Wn         W n        W0n        W@n        WPn        W`n        Wpn        V P
                  R J d   \        f   \        R4      hR# R# r   )	portusernamepasswordaccountr'   r   r"   r   r   )r#   rc   rd   re   rf   r'   r   r"   s   &&&&&&&&r   r$   FTPDownloader.__init__6  sN     	  &$t#QRR )5#r   c           	       aa \        V4      p\        P                  ! V P                  R7      pVP	                  VR,          V P
                  R7       V'       d   \        P                  P                  VR,          4      w  rx VP                  V P                  V P                  V P                  R7       WP                  V4      9   p	VP                  4        V	# \        SR4      '       * p
V
'       d   \!        SR4      o VP                  V P                  V P                  V P                  R7       RVR,           2pV P"                  '       d   VP%                  R	4       \'        \(        P*                  R
8H  4      p\-        \/        VP1                  VR,          4      4      ^OVRRRR7      oS;_uu_ 4        VV3R lpVP3                  WV P4                  R7       RRR4       M(VP3                  VSP6                  V P4                  R7       VP9                  4        V
'       d   SP                  4        R#   TP                  4        i ; i  + '       g   i     LO; i  TP9                  4        T
'       d   SP                  4        i i ; i)a  
Download the given URL over FTP to the given output file.

Parameters
----------
url : str
    The URL to the file you want to download.
output_file : str or file-like object
    Path (and file name) to which the file will be downloaded.
pooch : :class:`~pooch.Pooch`
    The instance of :class:`~pooch.Pooch` that is calling this method.
check_only : bool
    If True, will only check if a file exists on the server and
    **without downloading the file**. Will return ``True`` if the file
    exists and ``False`` otherwise.

Returns
-------
availability : bool or None
    If ``check_only==True``, returns a boolean indicating if the file
    is available on the server. Otherwise, returns ``None``.

)r'   netloc)hostrc   path)userpasswdacctr*   r+   zRETR zTYPE Ir,   r-   Tr.   c                ^   < SP                  \        V 4      4       SP                  V 4       R# z+Update the progress bar and write to outputN)rG   lenr*   )datarJ   rQ   s   &r   callback(FTPDownloader.__call__.<locals>.callback  s!     D	2#))$/r   )	blocksizeN)r   ftplibFTPr'   connectrc   osrk   splitloginrd   re   rf   nlstrI   r>   r?   r   voidcmdr9   rD   rE   r   rB   size
retrbinaryr"   r*   quit)r#   r   rJ   r   rK   r   r   	directory	file_namerM   rN   commandrP   rs   rQ   s   &&f&&         @r   rS   FTPDownloader.__call__J  s   0 s^
jj.H-DII>#%77==F1C#D I		t}}T]]	V%))<<			['22{E2K	$II4==T\\IRj012G H% !89	chhz&'9:;## X0
 NN7NP X w(9(9T__UHHJ!!#M 		0 X HHJ!!# s9   AH8 AI  A'I  8%I1I  8I
I	I   +J)rf   r"   re   rc   r   r'   rd   )   	anonymous r   NFrU   rV   rW   r_   s   @r   r   r     s     "HS(H Hr   r   c                   4   a  ] tR tRt o RtRR ltR tRtV tR# )r   i  a:  
Download manager for fetching files over SFTP.

When called, downloads the given file URL into the specified local file.
Requires `paramiko <https://github.com/paramiko/paramiko>`__ to be
installed.

Use with :meth:`pooch.Pooch.fetch` or :func:`pooch.retrieve` to customize
the download of files (for example, to use authentication or print a
progress bar).

Parameters
----------
port : int
    Port used for the SFTP connection.
username : str
    User name used to login to the server. Only needed if the server
    requires authentication (i.e., no anonymous SFTP).
password : str
    Password used to login to the server. Only needed if the server
    requires authentication (i.e., no anonymous SFTP). Use the empty
    string to indicate no password is required.
timeout : int
    Timeout in seconds for sftp socket operations, use None to mean no
    timeout.
progressbar : bool or an arbitrary progress bar object
    If True, will print a progress bar of the download to standard
    error (stderr). Requires `tqdm <https://github.com/tqdm/tqdm>`__ to
    be installed.

Nc                   Wn         W n        W0n        W@n        WPn        W`n        . pV P
                  '       d   \        f   VP                  R4       \        f   VP                  R4       V'       d   \        RP                  V4      4      hR # )Nr    z7Missing package 'paramiko' required for SFTP downloads. )rc   rd   re   rf   r'   r   r   appendparamikor   join)r#   rc   rd   re   rf   r'   r   errorss   &&&&&&& r   r$   SFTPDownloader.__init__  sv     	  & MMNOMMSTSXXf-.. r   c           	       a
 \        V4      p\        P                  ! VR,          V P                  3R7      pRp VP	                  V P
                  V P                  R7       \        P                  P                  V4      pV P                  VP                  4       n        V P                  '       dY   \        VP                  VR,          4      P                  4      p\!        \"        P$                  R8H  4      p\'        V^OVRRRR	7      o
V P                  '       d5   S
;_uu_ 4        V
3R
 lp	VP)                  VR,          W)R7       RRR4       MVP)                  VR,          V4       VP+                  4        Ve   VP+                  4        R# R#   + '       g   i     L8; i  TP+                  4        Te   TP+                  4        i i ; i)a  
Download the given URL over SFTP to the given output file.

The output file must be given as a string (file name/path) and not an
open file object! Otherwise, paramiko cannot save to that file.

Parameters
----------
url : str
    The URL to the file you want to download.
output_file : str
    Path (and file name) to which the file will be downloaded. **Cannot
    be a file object**.
pooch : :class:`~pooch.Pooch`
    The instance of :class:`~pooch.Pooch` that is calling this method.
ri   )sockN)rd   re   rk   r,   r-   Tr.   c                ~   < \        V4      Sn        SP                  \        V SP                  ,
          4      4       R# rp   )rB   r/   rG   n)currentr/   rQ   s   &&r   rs   )SFTPDownloader.__call__.<locals>.callback  s(    ),U Ghjj,@(ABr   )rs   )r   r   	Transportrc   rx   rd   re   
SFTPClientfrom_transportr'   get_channel
settimeoutr   rB   statst_sizer9   rD   rE   r   r6   rI   )r#   r   rJ   r   r   
connectionr   r~   rP   rs   rQ   s   &&&&      @r   rS   SFTPDownloader.__call__  sl   " s^
''j.BDII-NO
	N&&55jAD,0LLD)499Z%78@@A !89	## XC
 HHZ/HP X F+[9

   X 

  s1   A6F# 1A)F# 
F# %!F"F# F 	F# #'G
)rf   re   rc   r   r'   rd   )   r   r   r   NFrW   r_   s   @r   r   r     s     @/41 1r   r   c                   <   a  ] tR tRt o RtRRR]3R ltR tRtV t	R# )	r   i  a  
Download manager for fetching files from Digital Object Identifiers (DOIs).

Open-access data repositories often issue Digital Object Identifiers (DOIs)
for data which provide a stable link and citation point. The trick is
finding out the download URL for a file given the DOI.

When called, this downloader uses the repository's public API to find out
the download URL from the DOI and file name. It then uses
:class:`pooch.HTTPDownloader` to download the URL into the specified local
file. Allowing "URL"s  to be specified with the DOI instead of the actual
HTTP download link. Uses the :mod:`requests` library to manage downloads
and interact with the APIs.

The **format of the "URL"** is: ``doi:{DOI}/{file name}``.

Notice that there are no ``//`` like in HTTP/FTP and you must specify a
file name after the DOI (separated by a ``/``).

Use with :meth:`pooch.Pooch.fetch` or :func:`pooch.retrieve` to be able to
download files given the DOI instead of an HTTP link.

Supported repositories:

* `figshare <https://www.figshare.com>`__
* `Zenodo <https://www.zenodo.org>`__
* `Dataverse <https://dataverse.org/>`__ instances

.. attention::

    DOIs from other repositories **will not work** since we need to access
    their particular APIs to find the download links. We welcome
    suggestions and contributions adding new repositories.

Parameters
----------
progressbar : bool or an arbitrary progress bar object
    If True, will print a progress bar of the download to standard error
    (stderr). Requires `tqdm <https://github.com/tqdm/tqdm>`__ to be
    installed. Alternatively, an arbitrary progress bar object can be
    passed. See :ref:`custom-progressbar` for details.
chunk_size : int, optional
    Files are streamed *chunk_size* bytes at a time instead of loading
    everything into memory at one. Usually doesn't need to be changed.
headers : dict or None, optional
    Headers that will be passed to :func:`requests.get`.
    If None, default headers containing Pooch's user agent will be used.
    If no headers should be used, pass an empty dictionary.
**kwargs
    All keyword arguments given when creating an instance of this class
    will be passed to :func:`requests.get`.

Examples
--------

Download one of the data files from the figshare archive of Pooch test
data:

>>> import os
>>> downloader = DOIDownloader()
>>> url = "doi:10.6084/m9.figshare.14763051.v1/tiny-data.txt"
>>> # Not using with Pooch.fetch so no need to pass an instance of Pooch
>>> downloader(
...     url=url, output_file="tiny-data.txt", pooch=None
... ) # doctest: +SKIP
>>> os.path.exists("tiny-data.txt") # doctest: +SKIP
True
>>> with open("tiny-data.txt") as f: # doctest: +SKIP
...     print(f.read().strip())
# A tiny data file for test purposes only
1  2  3  4  5  6
>>> os.remove("tiny-data.txt") # doctest: +SKIP

Same thing but for our Zenodo archive:

>>> url = "doi:10.5281/zenodo.4924875/tiny-data.txt"
>>> downloader(
...     url=url, output_file="tiny-data.txt", pooch=None
... ) # doctest: +SKIP
>>> os.path.exists("tiny-data.txt") # doctest: +SKIP
True
>>> with open("tiny-data.txt") as f: # doctest: +SKIP
...     print(f.read().strip())
# A tiny data file for test purposes only
1  2  3  4  5  6
>>> os.remove("tiny-data.txt") # doctest: +SKIP

FrU   Nc                X    WPn         Ve   TM\        V n        W@n        Wn        W n        R # N)r!   REQUESTS_HEADERSrC   r'   r   r"   )r#   r   r"   rC   r'   r!   s   &&&&&,r   r$   DOIDownloader.__init__^  s(     ")"5w;K&$r   c                   \        V4      p\        VR,          3RV P                  RV P                  /V P                  B pVR,          pV^ ,          R8X  d
   VR,          pVP                  V4      p\        R
RV P                  RV P                  RV P                  RV P                  /V P                  B pV! WrV4       R	# )a  
Download the given DOI URL over HTTP to the given output file.

Uses the repository's API to determine the actual HTTP download URL
from the given DOI.

Uses :func:`requests.get`.

Parameters
----------
url : str
    The URL to the file you want to download.
output_file : str or file-like object
    Path (and file name) to which the file will be downloaded.
pooch : :class:`~pooch.Pooch`
    The instance of :class:`~pooch.Pooch` that is calling this method.

ri   rC   r'   rk   /   NNr   r"   N )	r   doi_to_repositoryrC   r'   r!   download_urlr   r   r"   )	r#   r   rJ   r   r   data_repositoryr   r   r   s	   &&&&     r   rS   DOIDownloader.__call__l  s    ( s^
+x 
LL
 LL
 kk	
 v&	Q<3!"I&33I> $ 
((

 LL
 LL	

 kk

 	<e4r   )r"   rC   r!   r   r'   )
rX   rY   rZ   r[   r\   r7   r$   rS   r]   r^   r_   s   @r   r   r     s)     Wv %,5 ,5r   r   c                    ^ RI pVP                  ! RV  23/ VB pVP                  pRVP                  u;8:  d   R8  d   M V# VP	                  4        V# )a  
Follow a DOI link to resolve the URL of the archive.

Parameters
----------
doi : str
    The DOI of the archive.
**kwargs
    All keyword arguments will be passed to :func:`requests.get`.

Returns
-------
url : str
    The URL of the archive in the data repository.

Nzhttps://doi.org/  X  )r5   r6   r   r:   r@   )r   r!   r5   rL   r   s   &,   r   
doi_to_urlr     s_    $  ||
3% 
H ,,C
h""(S(J 	!!#Jr   c                    V R,          R8X  d   V RR p \         \        \        .p\        V 3/ VB pRpV F  pVe   K	  VP                  ! R	RVRV /VB pK!  	  Vf"   \        V4      R,          p\        RV R24      hV# )
a  
Instantiate a data repository instance from a given DOI.

This function implements the chain of responsibility dispatch
to the correct data repository class.

Parameters
----------
doi : str
    The DOI of the archive.
**kwargs
    All keyword arguments will be passed also as ``**kwargs`` to the
    :meth:`DataRepository.initialize` method, that will ultimately get
    passed to :func:`requests.get`.

Returns
-------
data_repository : DataRepository
    The data repository object
r   Narchive_urlr   ri   zInvalid data repository 'zy'. To request or contribute support for this repository, please open an issue at https://github.com/fatiando/pooch/issuesr   )FigshareRepositoryZenodoRepositoryDataverseRepositoryr   
initializer   r   )r   r!   repositoriesr   r   repo
repositorys   &,     r   r   r     s    2 2w#~#2h 	L S+F+K O""oo ' O  {+H5
'
| 4O O
 	
 r   c                   <   a  ] tR tRt o ]R 4       tR tR tRtV t	R# )DataRepositoryi  c                    R# )a  
Initialize the data repository if the given URL points to a
corresponding repository.

Initializes a data repository object. This is done as part of
a chain of responsibility. If the class cannot handle the given
repository URL, it returns `None`. Otherwise a `DataRepository`
instance is returned.

Parameters
----------
doi : str
    The DOI that identifies the repository
archive_url : str
    The resolved URL for the DOI
Nr   )clsr   r   r!   s   &&&,r   r   DataRepository.initialize  s    & r   c                    \         h)  
Use the repository API to get the download URL for a file given
the archive URL.

Parameters
----------
file_name : str
    The name of the file in the archive that will be downloaded.

Returns
-------
download_url : str
    The HTTP URL that can be used to download the file.
NotImplementedError)r#   r   s   &&r   r   DataRepository.download_url
  s
      "!r   c                    \         h)
Populate the registry using the data repository's API

Parameters
----------
pooch : Pooch
    The pooch instance that the registry will be added to.
r   )r#   r   s   &&r   populate_registry DataRepository.populate_registry  s
     "!r   r   N)
rX   rY   rZ   r[   classmethodr   r   r   r]   r^   r_   s   @r   r   r     s&      ("$
" 
"r   r   c                   f   a  ] tR tRt o RtR t]R 4       t]R 4       t	]R 4       t
R tR tR	tV tR
# )r   i)  zhttps://zenodo.org/api/recordsc                F    W n         Wn        R V n        R V n        W0n        R # r   )r   r   _api_response_api_versionr!   r#   r   r   r!   s   &&&,r   r$   ZenodoRepository.__init__,  s"    &! r   c                J    \        V4      pVR,          R8w  d   R# V ! W3/ VB # )(  
Initialize the data repository if the given URL points to a
corresponding repository.

Initializes a data repository object. This is done as part of
a chain of responsibility. If the class cannot handle the given
repository URL, it returns `None`. Otherwise a `DataRepository`
instance is returned.

Parameters
----------
doi : str
    The DOI that identifies the repository
archive_url : str
    The resolved URL for the DOI
**kwargs
    All keyword arguments given when creating an instance of this class
    will be passed to :func:`requests.get`.
ri   z
zenodo.orgNr   r   r   r   r!   parsed_archive_urls   &&&, r   r   ZenodoRepository.initialize3  s/    . '{3h'<73.v..r   c                    V P                   ff   ^ RIpV P                  P                  R4      R,          pVP                  ! V P
                   RV 23/ V P                  B P                  4       V n         V P                   # )zCached API response from ZenodoNr   r   )r   r5   r   rz   r6   base_api_urlr!   json)r#   r5   
article_ids   &  r   api_responseZenodoRepository.api_responseP  sx     %))//4R8J!)$$%Qzl3"7;{{"df  !!!r   c                @   V P                   Ef   \        ;QJ d-    R V P                  R,           4       F  '       d   K   RM"	  RM! R V P                  R,           4       4      '       d   RV n         V P                   # \        ;QJ d-    R V P                  R,           4       F  '       d   K   RM"	  RM! R V P                  R,           4       4      '       d   RV n         V P                   # \        RV P                   R	V P
                   R
24      hV P                   # )a  
Version of the Zenodo API we are interacting with

The versions can either be :

- ``"legacy"``: corresponds to the Zenodo API that was supported until
  2023-10-12 (before the migration to InvenioRDM).
- ``"new"``: corresponds to the new API that went online on 2023-10-13
  after the migration to InvenioRDM.

The ``"new"`` API breaks backward compatibility with the ``"legacy"``
one and could probably be replaced by an updated version that restores
the behaviour of the ``"legacy"`` one.

Returns
-------
str
c              3   ,   "   T F
  pR V9   x  K  	  R# 5i)keyNr   .0files   & r   	<genexpr>/ZenodoRepository.api_version.<locals>.<genexpr>s  s     H-GT5D=-G   filesFTlegacyc              3   ,   "   T F
  pR V9   x  K  	  R# 5i)filenameNr   r   s   & r   r   r   u  s     O4NDZ4'4Nr   newz5Couldn't determine the version of the Zenodo API for  (doi:).)r   allr   r   r   r   r#   s   &r   api_versionZenodoRepository.api_version^  s    ( $sHT->->w-GHsssHT->->w-GHHH$,!     OD4E4Eg4NOOD4E4Eg4NOOO$)!    	 !K''(txxj<     r   c           	        V P                   R8X  d+   V P                  R,           Uu/ uF  q"R,          VbK  	  ppM(V P                  R,           Uu. uF  q"R,          NK  	  ppW9  d*   \        RV RV P                   RV P                   R24      hV P                   R8X  d   W1,          R	,          R
,          pV# V P                  R,          pRV RV R2pV# u upi u upi )az  
Use the repository API to get the download URL for a file given
the archive URL.

Parameters
----------
file_name : str
    The name of the file in the archive that will be downloaded.

Returns
-------
download_url : str
    The HTTP URL that can be used to download the file.

Notes
-----
After Zenodo migrated to InvenioRDM on Oct 2023, their API changed. The
link to the desired files that appears in the API response leads to 404
errors (by 2023-10-17). The files are available in the following url:
``https://zenodo.org/records/{article_id}/files/{file_name}?download=1``.

This method supports both the legacy and the new API.
r   r   r   r   File '' not found in data archive r   r   linksr#   idzhttps://zenodo.org/records/z/files/z?download=1)r   r   r   r   r   )r#   r   itemr   r   r   s   &&    r   r   ZenodoRepository.download_url~  s   2 x'373D3DW3MN3M4%[$&3MENE262C2CG2LM2L$*%%2LEM!#?##$F488*B8 
 x' +G4V<L 	 **40J-j\;W  # OMs   CCc                    V P                   R,           F;  pVR,          pV P                  R8X  d   RpMRpRV 2pW1P                  W$,          &   K=  	  R# )aj  
Populate the registry using the data repository's API

Parameters
----------
pooch : Pooch
    The pooch instance that the registry will be added to.

Notes
-----
After Zenodo migrated to InvenioRDM on Oct 2023, their API changed. The
checksums for each file listed in the API reference is now an md5 sum.

This method supports both the legacy and the new API.
r   checksumr   r   r   md5:N)r   r   registry)r#   r   filedatar   r   s   &&   r   r   "ZenodoRepository.populate_registry  sX      ))'22H
+H8+ !(,,4NN8=) 3r   )r   r   r   r   r!   N)rX   rY   rZ   r[   r   r$   r   r   propertyr   r   r   r   r]   r^   r_   s   @r   r   r   )  s[     3L / /8 " " ! !>+Z5 5r   r   c                   X   a  ] tR tRt o R t]R 4       tR t]R 4       t	R t
R tRtV tR	# )
r   i  c                8    W n         Wn        R V n        W0n        R # r   r   r   r   r!   r   s   &&&,r   r$   FigshareRepository.__init__      &!r   c                J    \        V4      pVR,          R8w  d   R# V ! W3/ VB # )r   ri   zfigshare.comNr   r   s   &&&, r   r   FigshareRepository.initialize  s/    . '{3h'>93.v..r   c                    V P                   P                  R4      w  rVP                  R4      R,          pV^ ,          R8w  d   R# \        VR,          4      pV# )zQ
Parse version from the doi

Return None if version is not available in the doi.
r   r   vNr   r   )r   rz   rB   )r#   _suffix	last_partversions   &    r   _parse_version_from_doi*FigshareRepository._parse_version_from_doi  sM     HHNN3'	LL%b)	Q<3im$r   c                   V P                   f   ^ RIpVP                  ! RV P                   23/ V P                  B P                  4       ^ ,          pVR,          pV P                  4       pVf0   \        P                  ! RV P                   R2\        4       RV 2pMRV RV 2pVP                  ! V3/ V P                  B pVP                  4        VP                  4       R,          V n         V P                   # )	z!Cached API response from FigshareNz)https://api.figshare.com/v2/articles?doi=r   zThe Figshare DOI 'zv' doesn't specify which version of the repository should be used. Figshare will point to the latest version available.z%https://api.figshare.com/v2/articles/z
/versions/r   )r   r5   r6   r   r!   r   r  warningswarnUserWarningr@   )r#   r5   articler   r
  api_urlrL   s   &      r   r   FigshareRepository.api_response  s    % ll;DHH:F++ dfQG !J224G  (
 3K K  	 B*N
 <!l*WI7 
  ||G;t{{;H%%'!)!9D!!!r   c           	         V P                    Uu/ uF  q"R,          VbK  	  ppW9  d*   \        RV RV P                   RV P                   R24      hW1,          R,          pV# u upi )r   namer   r   r   r   r   )r   r   r   r   )r#   r   r   r   r   s   &&   r   r   FigshareRepository.download_url$  s     150A0AB0Aft#0AB!#?@P@P?QQWX\X`X`Waacd  '7 Cs   A#c                l    V P                    F#  pRVR,           2VP                  VR,          &   K%  	  R# )r   r   computed_md5r  N)r   r   r#   r   r   s   && r   r   $FigshareRepository.populate_registry;  s4     ))H15h~6N5O/PENN8F+, *r   r   r   r   r!   N)rX   rY   rZ   r[   r$   r   r   r  r   r   r   r   r]   r^   r_   s   @r   r   r     sI      / /8  (" ("T.Q Qr   r   c                      a  ] tR tRt o R t]R 4       t]R 4       t]R 4       t	]	P                  R 4       t	R tR tR	tV tR
# )r   iI  c                8    W n         Wn        R V n        W0n        R # r   r   r   s   &&&,r   r$   DataverseRepository.__init__J  r  r   c                    V P                   ! W3/ VB pRVP                  u;8:  d
   R8  d    R#  V ! W3/ VB pWEn        V# )r   r   r   N)_get_api_responser:   r   )r   r   r   r!   rL   r   s   &&&,  r   r   DataverseRepository.initializeP  sS    , ((DVD (&&,, - 4V4
"*r   c                v    ^ RI p\        V4      pVP                  ! VR,           RVR,           RV 23/ VB pV# )z
Perform the actual API request

This has been separated into a separate ``classmethod``, as it can be
used prior and after the initialization.
Nr   ://ri   z-/api/datasets/:persistentId?persistentId=doi:)r5   r   r6   )r   r   r   r!   r5   parsedrL   s   &&&,   r   r   %DataverseRepository._get_api_responseq  sV     	;'<<j!"#fX&6%7 8..1U4
 

 r   c                    V P                   f8   V P                  ! V P                  V P                  3/ V P                  B V n         V P                   # )z-Cached API response from a DataVerse instance)r   r   r   r   r!   r   s   &r   r    DataverseRepository.api_response  sL     %!%!7!7$**".2kk"D !!!r   c                    Wn         R# )zUpdate the cached API responseN)r   )r#   rL   s   &&r   r   r'    s
     &r   c           	        \        V P                  4      pV P                  P                  4       pVR,          R,          R,           Uu/ uF  pVR,          R,          VR,          bK  	  ppW9  d*   \	        RV RV P                   RV P
                   R	24      hVR
,           RVR,           RWQ,          R,           2pV# u upi )r   rr   latestVersionr   dataFiler   r   r   r   r   r   r#  ri   z/api/access/datafile/r   )r   r   r   r   r   r   )r#   r   r$  rL   r   r   r   s   &&     r   r    DataverseRepository.download_url  s     4++,$$))+ !(9'B
B Z($z*::B 	 
 !#?##$F488*B8  j!"#fX&6%77L%&( 	 
s   	!Cc                    V P                   P                  4       R,          R,          R,           F1  pRVR,          R,           2VP                  VR,          R,          &   K3  	  R# )	r   rr   r*  r   r   r+  md5r   N)r   r   r   r  s   && r   r   %DataverseRepository.populate_registry  s]     ))..08I'RRHx
+E234 NN8J/
;< Sr   r  N)rX   rY   rZ   r[   r$   r   r   r   r   r   setterr   r   r]   r^   r_   s   @r   r   r   I  sq       @  $ " " & &
B r   r   rV   )r\   ry   rD   rv   r  utilsr   _versionr   	tqdm.autor   ImportErrorr   r7   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r5     s    
 
    !  E+&GH 
4nj jZA AHl l^T5 T5n>7t2" 2"jY5~ Y5xAQ AQHz. ze!  D
  Hs"   B B$ 	B! B!$	B0/B0