
    5pja              
         % S r SSKJr  SSKrSSKJrJrJr  SSKJ	r	J
r
  SSKrSSKJrJr  SSKJrJrJrJrJrJrJrJr  SS	KJrJrJrJrJr  SS
KJr  \" S5      r \RB                  S\RD                  S\RF                  S\RH                  S\RJ                  S0r&S\'S'   \RB                  S\RD                  S\RF                  S\RH                  S\RJ                  S0r(S\'S'   SS jr) " S S5      r*g)u"  Internal client for ``/api/v1/`` endpoints not covered by the OpenAPI spec.

This module is **private** — external callers should interact through the
public :class:`~modelscope_hub.api.HubApi` facade.

Auth strategy
-------------
The legacy API authenticates via a session cookie (``m_session_id``) rather
than the ``Authorization: Bearer`` header used by the OpenAPI surface. On
first use the client sets ``m_session_id = <access_token>`` on the
``requests.Session`` cookie jar — no round-trip to ``/api/v1/login`` is
needed for API calls.
    )annotationsN)IOAnyBinaryIO)
quote_plusurlparse)HTTPAdapterRetry   )API_CONNECT_TIMEOUTAPI_MAX_RETRIESAPI_TIMEOUTLEGACY_API_PREFIXUPLOAD_BLOB_CONNECT_TIMEOUTUPLOAD_BLOB_READ_TIMEOUTUPLOAD_RETRY_ALLOWED_METHODSRepoType)InvalidParameterNetworkErrorRequestTimeoutErrorServerErrorraise_for_status)
get_logger
legacy_apimodelsdatasetsstudiosskillsmcpsdict[str, str]_REPO_TYPE_SEGMENT_REPOS_SEGMENTc                2    [         R                  X  S35      $ )z4Return the URL path segment for the given repo_type.s)r!   get)	repo_types    V/var/www/html/pdf-tiff/venv/lib/python3.13/site-packages/modelscope_hub/_legacy_api.py_resolve_segmentr(   <   s    !!){!_==    c                     \ rS rSrSr\\S4           S)S jjr\S*S j5       r	\S+S j5       r
\
R                  S,S j5       r
S-S jrS.S/S	 jjrS0S
 jrSSSSSSSS.                   S1S jjrS2S jrS3S jrS4S jrS5S jrSSSS.       S6S jjrS7S jr   S8           S9S jjr   S:         S;S jjrS<S jrSS.       S=S jjr          S>S jr S?         S@S jjr S?           SAS jjr        SBS jrSSS .           SCS! jjr S?         SDS" jjrS#SSS$.         SES% jjr   SF         SGS& jjr!  SF           SHS' jjr"S(r#g)ILegacyClientA   zInternal client for /api/v1/ endpoints not covered by OpenAPI.

All network IO goes through :meth:`_request`, which handles auth headers,
retries, and structured error raising.
Nc                |   Xl         UR                  S5      U l        [        U4U l        SU l        [        R                  " 5       U l        U(       a  XPR                  R                  S'   [        US/ SQ[        S9n[        US9nU R                  R                  SU5        U R                  R                  S	U5        g )
N/Fz
User-Agentg      ?)i    i  i  i  )totalbackoff_factorstatus_forcelistallowed_methods)max_retrieszhttps://zhttp://)_tokenrstrip	_endpointr   _timeout_session_authenticatedrequestsSession_sessionheadersr
   r   r	   mount)selftokenendpointtimeoutr4   
user_agentretryadapters           r'   __init__LegacyClient.__init__H   s     !-0CW/M&+# ((*2<MM!!,/68	
 %0J0Iw/r)   c                    U R                   $ N)r7   r?   s    r'   rA   LegacyClient.endpointe   s    ~~r)   c                    U R                   $ rI   )r5   rJ   s    r'   r@   LegacyClient.tokeni   s    {{r)   c                f    Xl         SU l        U R                  R                  R	                  5         g )NF)r5   r9   r<   cookiesclear)r?   values     r'   r@   rM   m   s%    &+###%r)   c                N    U R                    [         SUR                  S5       3$ )zAConstruct full URL from a path relative to the legacy API prefix.r.   )r7   r   lstrip)r?   paths     r'   
_build_urlLegacyClient._build_urlv   s(    ..!"3!4Adkk#6F5GHHr)   c                    S[         R                  " 5       R                  S.nU R                  (       a  SU R                   3US'   U(       a  UR	                  U5        U$ )Nzapplication/json)Content-TypeX-Request-IDBearer Authorization)uuiduuid4hexr5   update)r?   extrar=   s      r'   _headersLegacyClient._headersz   sM    . JJL,,#
 ;;)0'>GO$NN5!r)   c                4   U R                   (       d  U R                  (       d  g[        U R                  5      R                  =(       d    SnU R
                  R                  R                  SU R                  USS9  SU l         [        R                  SU5        g)a  Set the ``m_session_id`` cookie on the session for legacy API auth.

Both cookie and Bearer header are sent: older endpoints rely on
the ``m_session_id`` cookie, while newer endpoints accept the
``Authorization: Bearer`` header. Sending both is harmless and
maximises compatibility.
N m_session_idr.   )domainrT   Tz'Legacy session cookie set for domain=%s)
r9   r5   r   r7   hostnamer<   rO   setloggerdebug)r?   rf   s     r'   _ensure_session_auth!LegacyClient._ensure_session_auth   sl     &&dkk$..)228b!!.$++fSV!W&*#>Gr)   F)params	json_bodydatafilesr=   rB   streamc               8   U R                  5         U R                  U5      n
U R                  U5      nUc  Ub  Uc  UR                  SS5        [        R                  SX5         U R                  R                  UU
UUUUUU=(       d    U R                  U	S9	n[        R                  SXUR"                  5        UR"                  S	:  aD  [        R                  S
UU
UUR"                  UR$                  (       a  UR$                  SS OS5        ['        U5        U$ ! [        R                  R                   a  n[        SU 35      UeSnAf[        R                   a  n[        SU 35      UeSnAf[        R                   a  n[!        SU 35      UeSnAff = f)z@Unified request dispatcher with auth, retry, and error handling.NrX   z%s %s)	methodurlrm   jsonro   rp   r=   rB   rq   zMax retries exceeded: zConnection failed: zRequest timed out: z%s %s -> %si  z1Request failed: %s %s params=%s status=%s body=%sr/   rd   )rk   rU   ra   popri   rj   r<   requestr8   r:   
exceptions
RetryErrorr   ConnectionErrorr   Timeoutr   status_codetextr   )r?   rs   rT   rm   rn   ro   rp   r=   rB   rq   rt   merged_headersrespexcs                 r'   _requestLegacyClient._request   s    	!!#ood#w/  1y7H~t4Wf*	L==((&04== ) 
D$ 	]F1A1ABs"LLC  #'99		$3" 	% ""-- 	G 6se<=3F'' 	E!4SE:;D 	L%(;C5&ABK	Ls0   %4D F9EFE..FFFc                F    UR                  5       nUR                  SU5      $ )zBExtract the 'Data' field from a standard legacy API JSON response.Data)ru   r%   )r?   r   bodys      r'   
_json_dataLegacyClient._json_data   s    yy{xx%%r)   c                    Xl         SU l        U R                  R                  R	                  5         U R                  5         U R                  SSSU0S9nU R                  U5      UR                  4$ )u  Authenticate via access token and return (user_data, cookies).

POST /api/v1/login

Performs a full login round-trip that returns a git token and
server-issued session cookies. For routine API access, the
``m_session_id`` cookie set by :meth:`_ensure_session_auth` is
sufficient — this method is only needed when the caller wants the
git token or the full cookie set from the server.
FPOSTloginAccessTokenrn   )r5   r9   r<   rO   rP   rk   r   r   )r?   access_tokenr   s      r'   r   LegacyClient.login   sd     #&+###%!!#}}VW8U}Vt$dll22r)   c           	        [        U5      nU[        R                  S4;   aF  UR                  5        VVs0 s H  u  pEUc  M
  US[	        U5      4_M     nnnU R                  SX6S9nOU R                  SX2S9nU R                  U5      $ s  snnf )u   POST /api/v1/{type}s — create a new repository.

``body`` is the fully-constructed request payload (PascalCase keys).

The dataset endpoint requires multipart form data (matching the
upstream server implementation), while model uses JSON.
datasetNr   )rp   r   )r(   r   DATASETitemsstrr   r   )r?   r&   r   segmentkvrp   r   s           r'   create_repoLegacyClient.create_repo   s     #9-))95537::<Q<411&Qs1v&<EQ===>D===ADt$$	 Rs   	B	B	c                h    [        U5      nU R                  SU SU 35      nU R                  U5      $ )u   GET /api/v1/{type}s/{repo_id} — fetch repository metadata.

Uses cookie-based session auth which supports private repositories
(unlike the OpenAPI Bearer-only endpoint).
GETr.   r(   r   r   )r?   repo_idr&   r   r   s        r'   get_repo_infoLegacyClient.get_repo_info   s8     #9-}}Uwiq	$:;t$$r)   r   2   )ownerpage_number	page_sizec                  UUS.nU(       a  XS'    U R                  SSUS9nUR                  5       nUR	                  S5      =(       d    / UR	                  S5      =(       d    SUR	                  S5      =(       d    UUR	                  S5      =(       d    US	.$ ! [         a0  nS[        U5      ;   a  S[        U5      ;   a  / SUUS	.s S
nA$ e S
nAff = f)u   GET /api/v1/datasets — list datasets with full private visibility.

The legacy endpoint returns ALL datasets for the authenticated user
(including private ones that the OpenAPI search index may miss).
)
PageNumberPageSizer   r   r   rm   	fromIndextoIndexr   )r   total_countr   r   Nr   
TotalCountr   r   )r   r   r   ru   r%   )r?   r   r   r   rm   r   r   r   s           r'   list_datasetsLegacyClient.list_datasets  s     &!"
 #7O
	==
6=BD yy{XXf%+88L16Q88L1@[*-:	
 	
   	c#h&9C+@#$#.!*	  	s#   B 
C$$CCCCc                H    [        U5      nU R                  SU SU 35        g)z`Delete a repository.

DELETE /api/v1/models/{owner}/{name}
DELETE /api/v1/datasets/{dataset_id}
DELETEr.   Nr(   r   )r?   r   r&   r   s       r'   delete_repoLegacyClient.delete_repo'  s'     #9-h7)1WI 67r)   c                   [        U5      nU[        U5      S.nU(       a  XWS'   U[        R                  SS4;   a  SOSnU R	                  SU SU SU 3US	9n	U R                  U	5      n
[        U
[        5      (       a  U
$ [        U
[        5      (       a2  U
R                  S
5      =(       d    U
R                  S5      =(       d    / $ / $ )zList files in a repository.

Models/studios/etc: GET /api/v1/{type}s/{repo_id}/repo/files
Datasets: GET /api/v1/datasets/{repo_id}/repo/tree
)Revision	RecursiveRootr   r   z	repo/treez
repo/filesr   r.   r   Filesrp   )
r(   r   r   r   r   r   
isinstancelistdictr%   )r?   r   r&   revision	recursiverootr   rm   suffixr   ro   s              r'   list_repo_filesLegacyClient.list_repo_files3  s     #9- Y"
 !6N )h.>.>	:-V V\h}}Uwiq	6($CF}St$dD!!KdD!!88G$?(9?R?	r)   c                   / nSn USUUS.nU(       a
  US:w  a  XGS'   U R                  SSU S3US	9nU R                  U5      n	[        U	[        5      (       a  U	n
OJ[        U	[        5      (       a3  U	R                  S
5      =(       d    U	R                  S5      =(       d    / n
O/ n
UR                  U
5        [        U
5      U:  a   U$ US-  nM  )zList files in a dataset repo using pagination.

Datasets can have millions of files, so this method pages through
``GET /api/v1/datasets/{repo_id}/repo/tree`` with
``PageNumber``/``PageSize`` params.
r   True)r   r   r   r   r.   r   r   z	datasets/z
/repo/treer   r   rp   )r   r   r   r   r   r%   extendlen)r?   r   r   r   	root_path	all_filesr   rm   r   ro   rp   s              r'   list_dataset_files_paginated)LegacyClient.list_dataset_files_paginatedR  s     !#	$#)%	&F Y#-!*v==G9J/ ! D
 ??4(D$%%D$'')DTXXg->D"U#5zI% 1K3 r)   c                j   [        U5      nU R                  SU SU S35      nU R                  U5      n[        U[        5      (       aR  UR                  S5      =(       d    0 nUR                  S5      =(       d    / nUR                  S5      =(       d    / nXx-   $ [        U[        5      (       a  U$ / $ )zQList branches and tags of a repository.

GET /api/v1/{type}s/{repo_id}/revisions
r   r.   
/revisionsRevisionMapTagsBranches)r(   r   r   r   r   r%   r   )	r?   r   r&   r   r   ro   revision_maptagsbranchess	            r'   list_revisionsLegacyClient.list_revisions  s    
 #9-}}Uwiq	$DEt$dD!!88M28bL##F+1rD#''
39rH?"!$--t525r)   )end_timec               Z   [        U5      n0 nUb  X5S'   U R                  SU SU S3U=(       d    SS9nU R                  U5      n[        U[        5      (       aN  UR                  S5      =(       d    0 nUR                  S5      =(       d    / UR                  S	5      =(       d    / 4$ / / 4$ )
zList branches and tags as separate lists.

GET /api/v1/{type}s/{repo_id}/revisions[?EndTime=...]

Returns ``(branches, tags)`` where each element is a list of dicts
with at least ``Revision`` and ``CreatedAt`` keys.
NEndTimer   r.   r   r   r   r   r   r(   r   r   r   r   r%   )	r?   r   r&   r   r   rm   r   ro   r   s	            r'   list_revisions_detail"LegacyClient.list_revisions_detail  s     #9-!# (9}}iq	,>T  

 t$dD!!88M28bL  ,2  (.B  2vr)   c                p    [        U5      nX4S.nU R                  SU SU S3US9nU R                  U5      $ )zGCreate a tag on a repository.

POST /api/v1/{type}s/{repo_id}/repo/tag
)TagNameRefr   r.   z	/repo/tagr   r   )r?   r   r&   tagr   r   r   r   s           r'   
create_tagLegacyClient.create_tag  sG     #9-0}}Vy')%DPT}Ut$$r)   c                    [        U5      nU[        R                  :X  a  U R                  SU SU S3SU0S9nOU R                  SU SU S3X4S.S9nU R	                  U5      $ )zDelete a single file from the repository.

DELETE /api/v1/{type}s/{owner}/{name}/file?FilePath=...&Revision=...
(for models)
DELETE /api/v1/datasets/{owner}/{name}/repo?FilePath=...
(for datasets)
r   r.   /repoFilePathr   z/file)r   r   )r(   r   r   r   r   )r?   r   r&   	file_pathr   r   r   s          r'   delete_fileLegacyClient.delete_file  s     #9-(((==)1WIU+"I. ! D ==)1WIU+$-D ! D
 t$$r)   c           	     x    [        U5      nUUS.nU R                  SSU SU SU 3US9nU R                  U5      $ )a  Create a Git commit with file operations.

POST /api/v1/repos/{type}s/{repo_id}/commit/{revision}

Each operation should be a dict with keys:
- action: "create" | "update" | "delete"
- path: path in repo
- type: "normal" | "lfs"
- size: file size in bytes
- sha256: hex digest (empty string for normal files)
- content: base64 content (for normal files)
- encoding: "base64" (for normal files)
)commit_messageactionsr   repos/r.   z/commit/r   r   )	r?   r   r&   
operationsr   r   r   payloadr   s	            r'   create_commitLegacyClient.create_commit  s]    * #9-,!
 }}WIQwixz:  

 t$$r)   c                v   [        U5      nSUS.nU R                  SSU SU S3US9nU R                  U5      n0 n[        U[        5      (       a  UR                  S/ 5      O/ n	U	 HN  n
U
R                  S	S
5      nU
R                  S0 5      nUR                  S0 5      nUR                  S5      nXU'   MP     U$ )u   Check which blobs need uploading via the LFS batch API.

POST /api/v1/repos/{type}s/{repo_id}/info/lfs/objects/batch

Returns mapping: sha256 → upload_url (if needs upload) or None (exists).
upload)	operationobjectsr   r   r.   z/info/lfs/objects/batchr   r   oidrd   r   hrefr   )r?   r   r&   r   r   r   r   ro   resultresp_objectsobjr   r   upload_actionr   s                  r'   validate_blobsLegacyClient.validate_blobs  s     #9- (W=}}WIQwi'>?  

 t$(*2<T42H2Htxx	2.bC''%$Cggi,G#KK"5M $$V,D3K   r)   )r=   rB   c               n   [        U5      [        R                  " 5       R                  S.nU R                  (       a$  SU R                   3US'   SU R                   3US'   U(       a  UR                  U5         U R                  R                  UUUU=(       d    [        [        4S9n[        U5         UR!                  5       n	['        U	[(        5      (       ar  U	R+                  S
5      S;  a]  SSKJn
  U
" U	R+                  S5      =(       d-    U	R+                  S5      =(       d    SU	R+                  S
5       S3UR0                  U	USS9eU	$ ! [        R                   a  n[        SU 35      UeSnAf[        R                   a  n[        S	U 35      UeSnAff = f! ["        [$        4 a    0 s $ f = f)a+  Upload a blob to the presigned URL returned by :meth:`validate_blobs`.

PUT {upload_url}

Sends both ``Authorization: Bearer`` and ``Cookie: m_session_id``
headers to authenticate against the LFS domain (which may differ
from the main API domain).

Returns the parsed JSON response body on success.
)zContent-LengthrY   rZ   r[   zm_session_id=Cookie)ro   r=   rB   zBlob upload connection failed: NzBlob upload timed out: Code)   200Nr   )APIErrorMessagemessagezBlob upload failed (Code=)PUT)r|   response_bodyrt   rs   )r   r\   r]   r^   r5   r_   r<   putr   r   r:   rz   r   r{   r   r   ru   
ValueErrorRuntimeErrorr   r   r%   errorsr   r|   )r?   
upload_urlro   sizer=   rB   upload_headersr   r   r   r   s              r'   upload_blobLegacyClient.upload_blob%  s   ( "$i JJL,,*
 ;;07}.EN?+)6t{{m'DN8$!!'*
	P==$$&Z$?AY#Z	 % D 		99;D dD!!dhhv&6>P&P(#mtxx	':m@YZ^ZbZbciZjYkkl>m ,,"  - '' 	Q!@FGSP 	P%(?u&EFCO	P L) 	I	s6   :/E 5F F"E11FFFF43F4c                |    [        U5      nU R                   [         SU SU S[        U5       S[        U5       3
$ )zConstruct the file download URL (no request is made).

URL pattern: {endpoint}/api/v1/{type}s/{repo_id}/repo?Revision={rev}&FilePath={path}
r.   z/repo?Revision=z
&FilePath=)r(   r7   r   r   )r?   r   r&   r   r   r   s         r'   get_download_urlLegacyClient.get_download_urld  sR     #9-~~017)1WI F#H-.jI9N8OQ	
r)   skill)element_typer   r   c               T    UUUUS.nU R                  SSUS9nU R                  U5      $ )zZGet collection details and its elements.

GET /api/v1/collections?Fid=...&ElementType=...
)FidElementTyper   r   r   collectionsr   )r   r   )r?   collection_idr  r   r   rm   r   s          r'   get_collectionLegacyClient.get_collectionx  s<     !'%!	
 }}UM&}At$$r)   c                L    [        U5      nU R                  SU SU SU 3USS9$ )zDownload the entire repo as a zip archive.

GET /api/v1/{type}s/{repo_id}/archive/zip/{revision}

Skills (and potentially other repo types) do not support per-file
download via ``/repo?FilePath=...``.  This method streams the
archive endpoint instead.
r   r.   z/archive/zip/T)r=   rq   r   )r?   r   r&   r   r=   r   s         r'   download_archiveLegacyClient.download_archive  sA     #9-}}iq	xj9	  
 	
r)   c                R    [        U5      nXCS.nU R                  SU SU S3UUSS9$ )z`Start a streaming download of a file.

Returns a Response with stream=True for chunked reading.
)r   r   r   r.   r   T)rm   r=   rq   r   )r?   r   r&   r   r   r=   r   rm   s           r'   download_streamLegacyClient.download_stream  sH     #9-&>}}iq	'  
 	
r)   )r7   r<   r9   r8   r5   )r@   
str | NonerA   r   rB   intr4   r  rC   r  returnNone)r   r   )r   r  )rQ   r  r   r!  )rT   r   r   r   rI   )r`   dict[str, str] | Noner   r    )r   r!  )rs   r   rT   r   rm   dict[str, Any] | Nonern   
Any | Nonero   r$  rp   r#  r=   r"  rB   
int | Nonerq   boolr   requests.Response)r   r'  r   r   )r   r   r   z/tuple[dict, requests.cookies.RequestsCookieJar])r&   r   r   zdict[str, Any]r   r   )r   r   r&   r   r   r   )r   r  r   r  r   r  r   r   )r   r   r&   r   r   r!  )masterTN)r   r   r&   r   r   r   r   r&  r   r  r   
list[dict])r(  r   r.   )
r   r   r   r   r   r  r   r   r   r)  )r   r   r&   r   r   r)  )r   r   r&   r   r   r%  r   ztuple[list[dict], list[dict]])
r   r   r&   r   r   r   r   r   r   r   )r(  )
r   r   r&   r   r   r   r   r   r   r   )r   r   r&   r   r   r)  r   r   r   r   r   r   )r   r   r&   r   r   zlist[dict[str, Any]]r   zdict[str, str | None])r  r   ro   z(str | bytes | BinaryIO | IO[bytes] | Anyr  r  r=   r"  rB   r%  r   r   )
r   r   r&   r   r   r   r   r   r   r   )
r  r   r  r   r   r  r   r  r   r   )r(  N)
r   r   r&   r   r   r   r=   r"  r   r'  )r   r   r&   r   r   r   r   r   r=   r"  r   r'  )$__name__
__module____qualname____firstlineno____doc__r   r   rF   propertyrA   r@   setterrU   ra   rk   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
  r  r  r  r  __static_attributes__ r)   r'   r+   r+   A   sa    #*!%00 0 	0
 0 0 
0:     \\& &I	H( )- $'+)-"55 5
 &5 5 5 %5 '5 5 5 
5n&3*% % !#
 #
 	#

 #
 
#
J8  !  	
   
D !)) ) 	)
 ) 
)\6(  $ 
  
'@%% % 	%
 % 
%0 !%% % 	%
 % 
%L !%% % 	%
 % % 
%H  &	
 
J *.":: 7: 	: ': : 
:H !

 
 	

 
 

0 $%% 	%
 % % 
%8 !)-

 
 	

 '
 

> !)-

 
 	

 
 '
 

 
r)   r+   )r&   r   r   r   )+r.  
__future__r   r\   typingr   r   r   urllib.parser   r   r:   requests.adaptersr	   r
   	constantsr   r   r   r   r   r   r   r   r  r   r   r   r   r   utils.loggerr   ri   MODELr   STUDIOSKILLMCPr!   __annotations__r"   r(   r+   r2  r)   r'   <module>r>     s    #  $ $ -  0	 	 	 g f $	L	! NNHjOOYNNHLL&& N  NNHjOOYNNHLL&" >
}	
 }	
r)   