
    i.                        S 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  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  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  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  SSK J!r!  SSK"J#r#  Sr$ " S S\5      r% " S S\5      r& " S S\5      r'S\(S \)\(\4   4S! jr* " S" S#\5      r+ " S$ S%\5      r,g&)'zDefines an auth handler to inject an Authorization header into each request.

Tokens are assumed to be installed onto a user's system via a separate CLI command.

    )fnmatch)	lru_cache)Any)
NamedTuple)Optional)Protocol)ParseResult)urlparse)
CondaError)Context)ChannelAuthBase)	BaseModel)Field)ValidationError)PreparedRequest)Response)repo_config)TOKEN_DOMAIN_MAP)CredentialType)AnacondaAuthConfig)TokenNotFoundError)	TokenInfoz/repo/c                   *    \ rS rSrS\S\S\4S jrSrg)ResponseHook#   response_returnc                     g N )selfr   r   s      Alib/python3.13/site-packages/anaconda_auth/_conda/auth_handler.py__call__ResponseHook.__call__%   s    #    r!   N)__name__
__module____qualname____firstlineno__r   r   r$   __static_attributes__r!   r&   r#   r   r   #   s    EEEEr&   r   c                   4    \ rS rSr% Sr\\   \S'   \\S'   Sr	g)AccessCredential(   zNRepresents a typed string containing an access credential (of CredentialType).valuetyper!   N)
r'   r(   r)   r*   __doc__r   str__annotations__r   r+   r!   r&   r#   r-   r-   (   s    X C=
r&   r-   c                       \ rS rSrSrSrg)AnacondaAuthError0   zr
A generic error to raise that is a subclass of CondaError so we don't trigger the unhandled exception traceback.
r!   N)r'   r(   r)   r*   r1   r+   r!   r&   r#   r5   r5   0   s    r&   r5   channel_namer   c                    U nUR                  S5      (       d  US-  n[        U5      nUR                  (       a  UR                  (       d  0 $ 0 n[	        5       nUR
                   H  nUR                  SS5      nX`:X  a  UnM  [        U5      nUR                  UR                  :w  a  ME  UR                  UR                  -   nUR                  UR                  -   n	[        X5      (       d  M  UnM     U$ )z=Find the correct channel settings from conda's configuration./channel )	endswithr
   schemenetlocr   channel_settingsgetpathr   )
r7   url
parsed_urlr?   contextsettingsr:   parsed_settingurl_without_schemapatterns
             r#   _load_channel_settingsrI   6   s     C<<s
#JJ$5$5	 iG,,,,y"-"'!'*   J$5$55'..@ ''.*=*==%//'# -& r&   c                   n    \ rS rSr% \" SSS9r\\   \S'   \" SSS9r	\\
   \S'   \S\S	S 4S
 j5       rSrg) AnacondaAuthHandlerExtraSettingsc   Nauth_domain)defaultaliasoverride_auth_domaincredential_typeoverride_credential_typer7   r   c                 j    [        U5      n U " S0 UD6$ ! [         a  n[        SU 35      eSnAff = f)z3Load extra settings for a channel, with validation.zIError when loading anaconda-auth extra configuration from your condarc.

Nr!   )rI   r   r5   )clsr7   rE   es       r#   from_channel_name2AnacondaAuthHandlerExtraSettings.from_channel_namei   sH     *,7	??" 	#_`a_be 	s    
2-2r!   )r'   r(   r)   r*   r   rP   r   r2   r3   rR   r   classmethodrV   r+   r!   r&   r#   rK   rK   c   sX    */M*R(3-R9>-:h~6  S 5W  r&   rK   c            	         ^  \ rS rSrS\S\S\4U 4S jjrS\S\\\	4   4S jr
S	\S
\	S\S\\   4S jr\S\S\\   4S j5       r\S\S\4S j5       r\S\S\\\   \	4   4S j5       rS
\	S\4S jrS\S\4S jrSrU =r$ )AnacondaAuthHandleru   r7   argskwargsc                 b   > [         TU ]  " U/UQ70 UD6  [        R                  U5      U l        g r    )super__init__rK   rV   _extras)r"   r7   r\   r]   	__class__s       r#   r`   AnacondaAuthHandler.__init__v   s,    7777II,Wr&   rC   r   c                    UR                   R                  5       nUn[        R                  nU[        ;   a  [        U   u  p4n[        US9nUR                  (       a  [        R                  nU R                  R                  (       a  U R                  R                  nU R                  R                  (       a  U R                  R                  nX44$ )zSelect the appropriate domain for token lookup based on a parsed URL.

We also determine whether to use API key or legacy repo token. This method
handles a default set of rules, as well as user overrides via conda
channel_settings.

)domain)
r>   lowerr   API_KEYr   r   use_unified_repo_api_keyra   rP   rR   )r"   rC   channel_domaintoken_domainrQ   r   configs          r#   _load_token_domain&AnacondaAuthHandler._load_token_domainz   s     $**002 &(00 --/?/O,L1 $<8**,44O<<,,<<<<L<<00"llCCO,,r&   rj   rQ   c                 t    [         R                  " U5      nUR                  (       a8  U[        R
                  :X  a$  [        UR                  [        R
                  5      $ UR                  nUR                  [        5      (       a  U[        [        5      S nUR                  S5      u  n  n [        UR                  U5      [        R                  5      $ ! [         a     gf = f! [         a     Of = f [        UR                  S   R                  [        R                  5      $ ! [          a     gf = f)a  Attempt to load an appropriate token from the keyring.

We parse the requested URL, extract what may be an organization ID, and first
attempt to load the token for that specific organization. If that fails, we
then simply return the first token in the keyring (since this is in all likelihood
one of the default channels ('main', 'r', etc.).

If no token can be found in the keyring, we return None, which means that
the token will attempt to be read from via conda-token instead.

Nr9   r   )r   loadr   api_keyr   rg   r-   rA   
startswith
URI_PREFIXlen	partitionget_repo_token
REPO_TOKENrepo_tokenstoken
IndexError)r"   rj   rQ   rC   
token_inforA   	maybe_orgr   s           r#   _load_token_from_keyring,AnacondaAuthHandler._load_token_from_keyring   s   "	"5J /^5K5K"K#J$6$68N8NOO ??:&&J)*D..-	1a	#)))4n6O6O # " 		( " 			#&&q)//1J1J   		s5   C /(C( 
C%$C%(
C54C590D* *
D76D7c                 6   U R                   R                  5       n[        bx  [        R                  " 5       nUR	                  5        HO  u  p4[        U5      R                   nUR                  5       U:X  d  M0  Uc  M5  [        U[        R                  5      s  $    g r    )	r>   rf   r   
token_listitemsr
   r-   r   rv   )rC   re   tokens	token_urlrx   token_netlocs         r#   _load_token_via_conda_token/AnacondaAuthHandler._load_token_via_conda_token   s}     ""((*" ++-F$*LLN 	'	299%%'61e6G+E>3L3LMM %3 r&   rB   c                     [        U5      nU R                  U5      u  p4U R                  X4U5      =n(       a  U$ U R                  U5      =n(       a  U$ [	        SU5      $ )a)  Load the appropriate token based on URL matching.

First, attempts to load from the keyring. If that fails, we attempt
to load the legacy repo token via conda-token.

Cached for performance.

Args:
    url: The URL for the request.

Returns:
     The token, if it can be loaded. None, otherwise.

N)r
   rl   r|   r   r-   )r"   rB   rC   rj   rQ   rx   s         r#   _load_tokenAnacondaAuthHandler._load_token   sp      c]
(,(?(?
(K% 11:
 
5 
 L66zBBUBLo66r&   c                 @    U R                  U5      nUR                  c  SUR                  4$ UR                  [        R                  :X  a  SUR                   3UR                  4$ SUR                   3UR                  4$ ! [
         a    SWR                  4s $ f = f)zBuild the Authorization header based on the request URL.

The result can vary in terms of "token" vs. "Bearer" as well as whether the
credential is a legacy repo token or an API key.

Nztoken zBearer )r   r/   r0   r   rv   	Exception)r"   rB   rx   s      r#   _build_header!AnacondaAuthHandler._build_header   s    	$$$S)E{{"UZZ''zz^666}-uzz99U[[M*EJJ66 	$##	$s   +B 8B 'B BBc                 p   ^ ^ U[         R                  :X  a  SOSmS[        S[        S[        4UU 4S jjnU$ )Nzanaconda token installzanaconda loginr   r   r   c                    > U R                   S;   ae  U R                  R                  R                  S5      b!  SU R                    STR                   ST S3nOSTR                   ST S3n[        U5      eU $ )	zBRaise a nice error message if the authentication token is missing.>       AuthorizationzReceived authentication error (z) when accessing z?. If your token is invalid or expired, please re-install with `z`.zToken not found for z. Please install token with `)status_coderequestheadersr@   r7   r5   )r   r   messageinstructionr"   s      r#   handler<AnacondaAuthHandler._build_response_handler.<locals>.handler  s    ##z1##++//@L9(:N:N9OO`aearar`s tXXcWddfh  /t/@/@.A B66A]"F  (00Or&   )r   rv   r   r   )r"   rQ   r   r   s   `  @r#   _build_response_handler+AnacondaAuthHandler._build_response_handler  sF     .";";; %! 		h 	S 	X 	 	  r&   r   c                     UR                   c  U$ U R                  UR                   5      u  p#UR                  SU R                  U5      5        U(       a  X!R                  S'   U$ )z<Inject the token as an Authorization header on each request.r   r   )rB   r   register_hookr   r   )r"   r   headerrQ   s       r#   r$   AnacondaAuthHandler.__call__(  sc     ;;N #'"4"4W[["A 	((9	

 /5OOO,r&   )ra   )r'   r(   r)   r*   r2   r   r`   r	   tupler   rl   r   r-   r|   staticmethodr   r   r   r   r   r   r   r$   r+   __classcell__)rb   s   @r#   rZ   rZ   u   s   XS X X X-[ -U3CV=W ->22 (2  	2
 
"	#2h 	"	#  7s 7'7 7 76 $ $x}n/L)M $ $(' 
8 O  r&   rZ   N)-r1   r   	functoolsr   typingr   r   r   r   urllib.parser	   r
   condar   conda.base.contextr   conda.plugins.typesr   pydanticr   r   r   requestsr   r   anaconda_auth._condar   anaconda_auth._conda.configr   r   anaconda_auth.configr   anaconda_auth.exceptionsr   anaconda_auth.tokenr   rr   r   r-   r5   r2   dictrI   rK   rZ   r!   r&   r#   <module>r      s          $ !  & /   $ $  , 8 6 3 7 )
F8 F
z 
 * *c3h *Zy $G/ Gr&   