
    ^                        d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddlZddl	Z	ddl
ZddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlZdZdZdZdZ dZ!dZ"dZ#dZ$d Z%d Z& G d de'      Z( G d de	jR                        Z* G d de*      Z+ G d dejX                        Z-d!d Z.y)"z9A module that converts API exceptions to core exceptions.    )absolute_import)division)unicode_literalsN)
exceptions)resource)log)
properties)resource_lex)resource_printer)resource_property)encoding~CELRzgoogle.rpc.ErrorInfozgoogle.rpc.LocalizedMessagezgoogle.rpc.Helpc                    g }d}| D ]  }|t         k(  r$|j                  t         t        z   t         z          0|dk(  r$|j                  t         t        z   t         z          Y|dk(  r@|dkD  r$|j                  t         t        z   t         z          n|j                  d       |dz  }|dk(  r@|dz  }|dkD  r$|j                  t         t
        z   t         z          |j                  d       |j                  |        dj                  |      S )z0Return s with format special characters escaped.r   :{   } )_ESCAPEappend_ESCAPED_ESCAPE_ESCAPED_COLON_ESCAPED_LEFT_CURLY_ESCAPED_RIGHT_CURLYjoin)srncs       -lib/googlecloudsdk/api_lib/util/exceptions.py_Escaper%   7   s    !!aG|hhw(723	
chhw''12	
c	
Q	..89	1fa	
c1fa	
Q	//'9:	hhqk% & 
    c                    g }d}d}|t        |       k  r:| |   }|dz  }|t        k(  r|dz   t        |       k  r| |dz      t        k(  r| |   }|dz  }|t        k(  r9|dkD  r|j                  t        t        z          n|j                  d       |dz  }n|t        k(  r9|dz  }|dkD  r|j                  t        t        z          nz|j                  d       nh|dkD  r|j                  | |dz
  |        nK|t
        k(  r|j                  d       n0|t        k(  r'|j                  t               n|j                  |       |t        |       k  r:dj                  |      S )	z9Return s with escaped format special characters expanded.r   r      r   r      r   r   )lenr   r   r   r   r   r   r   )r    r!   r"   ir#   s        r$   _Expandr,   Q   s<   !!!	CF
	!AFAG|AA1QU8w+>
A$a1fa	
!	!q5
((700
1
((3-	Q$$	Qq5
((711
2
((3-q5	1q5		hhqk3 	
CF
4 
r&   c                       e Zd ZdZd Zy)_JsonSortedDictz0A dict with a sorted JSON string representation.c                 0    t        j                  | d      S )NT)	sort_keys)jsondumpsselfs    r$   __str__z_JsonSortedDict.__str__v   s    ::dd++r&   N)__name__
__module____qualname____doc__r5    r&   r$   r.   r.   s   s
    8,r&   r.   c                   :     e Zd ZdZ fdZd Zd Zd Zd Z xZ	S )FormattableErrorPayloada>  Generic payload for an HTTP error that supports format strings.

  Attributes:
    content: The dumped JSON content.
    message: The human readable error message.
    status_code: The HTTP status code number.
    status_description: The status_code description.
    status_message: Context specific status message.
  c                     t         t        |           d| _        i | _        d| _        d| _        d| _        t        |t        j                        r|| _        y| j                         | _        y)zInitialize a FormattableErrorPayload instance.

    Args:
      http_error: An Exception that subclasses can use to populate class
        attributes, or a string to use as the error message.
    z{?}r   r   N)superr<   __init___valuecontentstatus_codestatus_descriptionstatus_message
isinstancesixstring_typesmessage_MakeGenericMessager4   
http_error	__class__s     r$   r?   z FormattableErrorPayload.__init__   s`     

!413DKDLD DD*c../dl--/dlr&   c                 <   t        |      }|dk(  r| j                  |fS |j                  dd      }|j                  d      j                  dd      }|j                  d      }|j	                  d      rt        |      dkD  s|dk(  r|dd }|r|j                  d      nd}|r|j                  d      nd}| j                  |      \  }}	|	st        |	t        t        f      sd|fS |s@t        |	t        j                  t        j                  t        ft        j                  z         sOt        j                         }
t!        j"                  |	|xs d|
d	
       |
j%                         j'                         }	|r!|	| _        | j)                  t        |            }	|	|fS )a  Returns the value of field_name for string.Formatter.format().

    Args:
      field_name: The format string field name to get in the form
        name - the value of name in the payload, '' if undefined
        name?FORMAT - if name is non-empty then re-formats with FORMAT, where
          {?} is the value of name. For example, if name=NAME then
          {name?\nname is "{?}".} expands to '\nname is "NAME".'.
        .a.b.c - the value of a.b.c in the JSON decoded payload contents.
          For example, '{.errors.reason?[{?}]}' expands to [REASON] if
          .errors.reason is defined.
      unused_args: Ignored.
      unused_kwargs: Ignored.

    Returns:
      The value of field_name for string.Formatter.format().
    ?r   r   r   z0.Nr   defaultT)outsingle)r,   r@   splitpop
startswithr*   	_GetFieldrE   intfloatrF   	text_typebinary_typeinteger_typesioStringIOr   Printgetvaluestripformat)r4   
field_nameunused_argsunused_kwargspartssubpartsnameprinter_formatrecursive_formatvaluebufs              r$   	get_fieldz!FormattableErrorPayload.get_field   sc   $ $JS[[*$$S!$Eyy|!!#q)H<<?D 	#d)a-DDL!"Xd(0X\\!_dN',uyy|$..&KD%EC<8XoZs69J9JJLKKMc
,9#dDlln""$edkkk'"234e$;r&   c                 |   d|v r|j                  d      rd}|dd }nd}t        j                  |      j                         }| j                  }|r*|r(| j
                  j                  |d   d      }|r|d   |i}t        j                  ||d      }||fS |r | j
                  j                  |d      }||fS d}||fS )a8  Gets the value corresponding to name in self.content or class attributes.

    If `name` starts with a period, treat it as a key in self.content and get
    the corresponding value. Otherwise get the value of the class attribute
    named `name` first and fall back to checking keys in self.content.

    Args:
      name (str): The name of the attribute to return the value of.

    Returns:
      A tuple where the first value is `name` with any leading periods dropped,
      and the second value is the value of a class attribute or key in
      self.content.
    .Fr   NTr   )	rT   r
   LexerKeyrA   __dict__getr   Get)r4   rf   check_payload_attributeskeyrA   ri   s         r$   rU   z!FormattableErrorPayload._GetField   s     d{		#( ABx $( t$((*cg	!c!!#a&$/VUO'##GS$7e ; 
mmd+e ; e;r&   c                 v    | j                         }| j                  rdj                  || j                        S |S )z:Makes a generic human readable message from the HttpError.z{0}: {1})_MakeDescriptionrD   r`   r4   descriptions     r$   rI   z+FormattableErrorPayload._MakeGenericMessage   s8    '')K{D,?,?@@r&   c                     | j                   }|r|j                  d      r|dd }|S dj                  | j                        S )CMakes description for error by checking which fields are filled in.rm   NzHTTPError {0})rC   endswithr`   rB   rw   s     r$   rv   z(FormattableErrorPayload._MakeDescription   sG    ))K			c	"!#2&!!$"2"233r&   )
r6   r7   r8   r9   r?   rk   rU   rI   rv   __classcell__rL   s   @r$   r<   r<   z   s#    0$*X#J4r&   r<   c                   r     e Zd ZdZ fdZ fdZd Zd Zd Zd Z	d Z
d	 Zd
 Zd Z fdZd Zd Z xZS )HttpErrorPayloada  Converts apitools HttpError payload to an object.

  Attributes:
    api_name: The url api name.
    api_version: The url version.
    content: The dumped JSON content.
    details: A list of {'@type': TYPE, 'detail': STRING} typed details.
    domain_details: ErrorInfo metadata Indexed by domain.
    violations: map of subject to error message for that subject.
    field_violations: map of field name to error message for that field.
    error_info: content['error'].
    instance_name: The url instance name.
    message: The human readable error message.
    resource_item: The resource type.
    resource_name: The url resource name.
    resource_version: The resource version.
    status_code: The HTTP status code number.
    status_description: The status_code description.
    status_message: Context specific status message.
    unparsed_details: The unparsed details.
    type_details: ErrorDetails Indexed by type.
    url: The HTTP url. .<a>.<b>...: The <a>.<b>... attribute in the JSON content
      (synthesized in get_field()).

  Grammar:
    Format strings inherit from python's string.formatter. where we pass tokens
    obtained by the resource projection framework format strings.

  Examples:
    error_format values and resulting output:

    'Error: [{status_code}] {status_message}{url?\n{?}}{.debugInfo?\n{?}}'

      Error: [404] Not found
      http://dotcom/foo/bar
      <content.debugInfo in yaml print format>

    'Error: {status_code} {details?\n\ndetails:\n{?}}'

      Error: 404

      details:
      - foo
      - bar

     'Error [{status_code}] {status_message}\n'
     '{.:value(details.detail.list(separator="\n"))}'

       Error [400] Invalid request.
       foo
       bar
  c                 x   t         t        |   |       d| _        d| _        g | _        i | _        i | _        d | _        d| _	        d| _
        d| _        d| _        d| _        d | _        t        |t         j"                        s8| j%                  |       | j'                  |       | j)                         | _        y y Nr   )r>   r   r?   api_nameapi_versiondetails
violationsfield_violations
error_infoinstance_nameresource_itemresource_nameresource_versionurl
_cred_inforE   rF   rG   _ExtractResponseAndJsonContent#_ExtractUrlResourceAndInstanceNamesrI   rH   rJ   s     r$   r?   zHttpErrorPayload.__init__0  s    	
D*:6DMDDLDODDODDDDDHDOj#"2"23
))*5
..z:--/dl 4r&   c                 L   |j                  d      r4|j                  dd      \  }}| j                  j                  |      }||fS |j                  d      r4|j                  dd      \  }}| j                  j                  |      }||fS t
        t        |   |      \  }}||fS )Nzfield_violations.rm   r   zviolations.)rT   rR   r   rq   r   r>   r   rU   )r4   rf   _fieldri   subjectrL   s         r$   rU   zHttpErrorPayload._GetFieldC  s    *+C#ha##''.e ; 
	'::c1%jaoo!!'*e ; *D;DAkdE;r&   c                 \    d|v r|j                  dd      S d|v r|j                  dd      S y)zGenerates mTLS endpoint override for a given endpoint override.

    Args:
      endpoint_override: The endpoint to generate the mTLS endpoint override
        for.

    Returns:
      The mTLS endpoint override, if one exists. Otherwise, None.
    zsandbox.googleapis.comzmtls.sandbox.googleapis.comzgoogleapis.comzmtls.googleapis.comN)replace)r4   endpoint_overrides     r$   _GetMTLSEndpointOverridez)HttpErrorPayload._GetMTLSEndpointOverrideN  sI      #44&&
"$A  
.	.&&'79NOOr&   c                     t         j                  j                  j                         xrH t         j                  j                  j
                  j                         xr t        j                         S )zfReturns whether mTLS is enabled and an endpoint override is present for the current gcloud invocation.)r	   VALUESapi_endpoint_overrides	AllValuescontext_awareuse_client_certificateGetBoolIsInternalUserCheckr3   s    r$   ,_IsMTLSEnabledAndApiEndpointOverridesPresentz=HttpErrorPayload._IsMTLSEnabledAndApiEndpointOverridesPresenta  sU     	00::< 	-++BBJJL	-**,r&   c                     t         j                  j                  |      }|j                  }|sy|j	                  d      d   }|j                  d      S )zEReturns whether the existing endpoint override is using mTLS already.Nrm   r   mtls)urllibparseurlparsenetlocrR   rT   )r4   r   	urlparseddomain_partsdomains        r$   _IsExistingOverrideMTLSz(HttpErrorPayload._IsExistingOverrideMTLSi  sN    %%&78I##L$Q'FV$$r&   c                    t        |dd      }|rJt        |j                  dd            | _        t	        j
                  |j                  dd            | _        t	        j
                  |j                        }	 t        t        j                  |            | _        t        | j                  d         | _        | j                  s*t        | j                  j                  dd            | _        | j                  d	v r| j                  j                  d
d      rddlm} |j                  j                         | _        | j                   r| j                   j#                         }| j                  d   d
   }|d   dk7  r|dz   |dd z   | j                  d   d
<   n|dz   |z   | j                  d   d
<   | j                  d   d
   | j                  d
<   | j                  s!| j                  j                  dd      | _        | j%                         rt&        j(                  j*                  j-                         }|j/                         D ]  \  }}	| j1                  |	      }
| j3                  |	      r)|j4                  j7                  |	      sE|
sHdj9                  ||	g|
      | j                  d
<   dd|	|
ddg| j                  d<    n | j                  j                  d
d      | _        | j                  j                  dg       | _        | j?                  | j<                        | _         | jC                  | j<                        | _"        | jG                  | j<                        | _$        | jK                  | j<                        | _&        t&        j(                  jN                  jP                  jS                         r!| jU                  | j<                        | _+        yy# tX        tZ        t\        f$ r
 || _        Y yt^        $ r Y yw xY w)z:Extracts the response and JSON content from the HttpError.responseNstatusr   reasonr   errorcode)i      rH   )storer{   rm   z.  zCertificate-based access is enabled, but the endpoint override for the following API is not using mTLS: {}. Please update the endpoint override to use mTLS endpoint: {} z(type.googleapis.com/google.rpc.ErrorInfoACCESS_DENIED)r   mtls_endpoint_override)@typer   metadatar   )0getattrrV   rq   rB   r   DecoderC   rA   r.   r1   loadsr   googlecloudsdk.core.credentialsr   CredentialInfoGetCredentialInfor   GetInfoStringr   r	   r   r   r   itemsr   r   r   rT   r`   rD   r   _ExtractViolationsr   _ExtractFieldViolationsr   _IndexErrorDetailsByTypetype_details_IndexErrorInfoByDomaindomain_detailscoreparse_error_detailsr   RedactParsedTypesunparsed_detailsKeyError	TypeError
ValueErrorAttributeError)r4   rK   r   rA   c_storecred_info_messageexisting_messageendpoint_overridesr   r   mtls_endpoints              r$   r   z/HttpErrorPayload._ExtractResponseAndJsonContentr  s   z:t4HX\\(A67d (Xr0J Kdooj001GI$TZZ%89dl'W(=>dot2261=>			_	,1D1D
R2 	E "00BBD??"oo;;=
!\\'29=

 b!S( !4'*;CR*@@ LL!),
 !3&):: LL!), (,||G'<Y'G$//)
$$$"&//"5"5h"C		:	:	<44>>@ 	 ,>+C+C+E'H'778IJ-../@A..++,=>CCI601=D OOI& D)):.;+ *DOOI& - ,F. !OO//	2>d__((B7dl//=do"::4<<Hd77Ed 88Fd						3	3	;	;	= $ 6 6t|| D 
>i, $#d 
s,   :G5O  0O  O  EO   P=PPc                     g }|D ]H  }|j                  dd      }|j                  d      d   }|t        t        fvs8|j	                  |       J |S )z/Redacts the parsed types from the details list.r   N/r{   )rq   rR   LOCALIZED_MESSAGE_SUFFIXHELP_SUFFIXr   )r4   r   r   item
error_typeerror_suffixs         r$   r   z"HttpErrorPayload.RedactParsedTypes  s[    88GT*j%%c*2.l	6D	D%	 
 r&   c                     t        j                  t              }|D ]?  }|j                  dd      }|s|j	                  d      d   }||   j                  |       A |S )z>Extracts and indexes error details list by the type attribute.r   Nrm   r{   )collectionsdefaultdictlistrq   rR   r   )r4   r   type_mapr   r   error_type_suffixs         r$   r   z)HttpErrorPayload._IndexErrorDetailsByType  s`    &&t,H88GT*j	&,,S1"5"#**40	 
 Or&   c                     t        j                  t              }|D ]S  }|j                  dd      }|j	                  t
              s+|j                  dd      }|s@||   j                  |       U |S )z=Extracts and indexes error info list by the domain attribute.r   Nr   )r   r   r   rq   r|   ERROR_INFO_SUFFIXr   )r4   r   
domain_mapr   r   r   s         r$   r   z(HttpErrorPayload._IndexErrorInfoByDomain  si    ((.J88GT*j			.	/(D)
V

#
#D
)  r&   c                    |j                   | _         | j                   sy	 t        j                  | j                         \  }}}|r|| _        |r|| _        |j                  d      }dt        |      cxk  rdk  sy y|d   | _        |d   }|j                  d      d   | _	        dj                  | j                        | _        y# t        j                  $ r Y yw xY w)zEExtracts the url resource type and instance names from the HttpError.Nr   r      r   rN   z{} instance)r   resource_utilSplitEndpointUrlInvalidEndpointExceptionr   r   rR   r*   r   r   r`   r   )r4   rK   rf   versionresource_pathresource_partsr   s          r$   r   z4HttpErrorPayload._ExtractUrlResourceAndInstanceNames  s    ~~DH88%2%C%C
((&"dG]
 dm d #((-Ns>"&Q& ''*D"1%M&,,S1!4D&--d.@.@AD# 11 s   #C CCc                    | j                   rm| j                  r`| j                  rS| j                   dk(  r| j                  r/| j                  j                  xs | j                  j
                  }n2t        j                  j                  j
                  j                         }dj                  || j                  | j                        S | j                   dk(  r4dj                  | j                  j                         | j                        S | j                   dk(  r^| j                  dk(  rdj                  | j                        S dj                  | j                  j                         | j                        S t        t        | ?         S )	rz   r   zH[{0}] does not have permission to access {1} [{2}] (or it may not exist)r   z{0} [{1}] not foundi  projectsz7Resource in projects [{0}] is the subject of a conflictz&{0} [{1}] is the subject of a conflict)rB   r   r   r   impersonated_accountaccountr	   r   r   rr   r`   
capitalizer   r>   r   rv   )r4   r   rL   s     r$   rv   z!HttpErrorPayload._MakeDescription  sS   D..43E3E			S	 ??oo22Mdoo6M6M  %%**22668' 
&$,,d.@.@
A	B 
		S	 $++))+T-?-?A 	A			S	 +128&9K9K2LM :@@  ++-t/A/AC C !49;;r&   c                 @   t        j                         }|D ]o  }d|vr|d   }t        |t              s|j	                  d      }|D ]<  }	 |j	                  d      }|xs |}|r ||v r||xx   d|d   z   z  cc<   n|d   ||<   > q |S # t
        t        f$ r Y Tw xY w)a&  Extracts a map of violations from the given error's details.

    Args:
      details: JSON-parsed details field from parsed json of error.

    Returns:
      Map[str, str] sub -> error description. The iterator of it is ordered by
      the order the subjects first appear in the errror.
    r   r   
rx   r   OrderedDictrE   r   rq   r   r   )	r4   r   resultsdetailr   sub	violation	local_subr   s	            r$   r   z#HttpErrorPayload._ExtractViolations  s     %%'G	V	#,'j
D)JJy!c!)
	mmI.)$9''!g$=)A"AA!*=!9gg " & N )$ 	
	   9BBBc                 @   t        j                         }|D ]o  }d|vr|d   }t        |t              s|j	                  d      }|D ]<  }	 |j	                  d      }|xs |}|r ||v r||xx   d|d   z   z  cc<   n|d   ||<   > q |S # t
        t        f$ r Y Tw xY w)aD  Extracts a map of field violations from the given error's details.

    Args:
      details: JSON-parsed details field from parsed json of error.

    Returns:
      Map[str, str] field (in dotted format) -> error description.
      The iterator of it is ordered by the order the fields first
      appear in the error.
    fieldViolationsr   r   rx   r   )	r4   r   r   deetr   fviollocal_fr   s	            r$   r   z(HttpErrorPayload._ExtractFieldViolations:  s     %%'G	$	&)*j
D)
((7
a$
	HHW%',w%entM': ::n#M2gen  & N )$ 	
	r   )r6   r7   r8   r9   r?   rU   r   r   r   r   r   r   r   r   rv   r   r   r}   r~   s   @r$   r   r      sN    3j0&	&%Pd	B8<6@r&   r   c                   J     e Zd ZdZdef fd	Zd Zed        Zd Z	d Z
 xZS )HttpExceptionzTransforms apitools HttpError to api_lib HttpException.

  Attributes:
    error: The original HttpError.
    error_format: An HttpErrorPayload format string.
    payload: The HttpErrorPayload object.
  Nc                 b    t         t        |   d       || _        || _         ||      | _        y r   )r>   r  r?   r   error_formatpayload)r4   r   r  payload_classrL   s       r$   r?   zHttpException.__init__e  s-    	-'+DJ$D 'DLr&   c                 b   | j                   }|ud}t        j                  j                  j                  j                         rd}d}d}||z   |z   |z   }n|dz   }t        j                         t        j                  k  r|dz  }t        | j                  j                  t        |                  S )Nz
{message?}zG{type_details.LocalizedMessage:value(message.list(separator="
"))?
{?}}zJ{type_details.Help:value(links.flatten(show="values",separator="
"))?
{?}}z{unparsed_details?
{?}}z{details?
{?}}z{.debugInfo?
{?}})r  r	   r   r   r   r   r   GetVerbosityloggingDEBUGr,   r  r`   r%   )r4   r  error_prefixparsed_localized_messagesparsed_help_messagesr   s         r$   r5   zHttpException.__str__k  s    $$L!l						3	3	;	;	=: 	"
I 	 6'("#  	 $&77				w}}	,,,4<<&&w|'<=>>r&   c                 ,    t        j                  |       S N)rF   rX   r3   s    r$   rH   zHttpException.message  s    ==r&   c                 ,    t        | j                        S r  )hashrH   r3   s    r$   __hash__zHttpException.__hash__  s    r&   c                 V    t        |t              r| j                  |j                  k(  S y)NF)rE   r  rH   )r4   others     r$   __eq__zHttpException.__eq__  s"    %'\\U]]**r&   )r6   r7   r8   r9   r   r?   r5   propertyrH   r  r  r}   r~   s   @r$   r  r  \  s8     *.=M (?4  r&   r  c                       fd}|S )a*  Decorator that catches an HttpError and returns a custom error message.

  It catches the raw Http Error and runs it through the given format string to
  get the desired message.

  Args:
    format_str: An HttpErrorPayload format string. Note that any properties that
    are accessed here are on the HTTPErrorPayload object, and not the raw
    object returned from the server.

  Returns:
    A custom error message.

  Example:
    @CatchHTTPErrorRaiseHTTPException('Error [{status_code}]')
    def some_func_that_might_throw_an_error():
      ...
  c                       fd}|S )Nc                      	  | i |S # t         j                  $ r+}t        |      }t        j                  |       Y d }~y d }~ww xY wr  )apitools_exceptions	HttpErrorr  core_exceptionsreraise)argskwargsr   exc
format_strrun_funcs       r$   WrapperzdCatchHTTPErrorRaiseHTTPException.<locals>.CatchHTTPErrorRaiseHTTPExceptionDecorator.<locals>.Wrapper  sK    %((( ** %E:.$$%s    A	!AA	r:   )r#  r$  r"  s   ` r$   )CatchHTTPErrorRaiseHTTPExceptionDecoratorzSCatchHTTPErrorRaiseHTTPException.<locals>.CatchHTTPErrorRaiseHTTPExceptionDecorator  s    % Nr&   r:   )r"  r%  s   ` r$    CatchHTTPErrorRaiseHTTPExceptionr&    s    (	 
32r&   r  )/r9   
__future__r   r   r   r   r[   r1   r
  stringurllib.parser   apitools.base.pyr   r  googlecloudsdk.api_lib.utilr   r   googlecloudsdk.corer  r   r	   googlecloudsdk.core.resourcer
   r   r   googlecloudsdk.core.utilr   rF   r   r   r   r   r   r   r   r   r%   r,   dictr.   	Formatterr<   r   Errorr  r&  r:   r&   r$   <module>r2     s     @ &  '  	     > A = # * 5 9 : - 

    + 8 4D,d ,}4f.. }4@_. _D3O)) 3l3r&   