o
    !                     @   s  d Z ddlZddlZddlZddlmZ ddlm  m  m	Z
 ddlm  m  mZ ddlm  m  mZ ddlmZ ddlmZ ddlmZ ejrTddlmZ nddlmZ dd	gZd
Zdd Zdd	 Zdd ZdddZ dddZ!dddZ"dd Z#dd Z$dd Z%dS )z4Assorted utilities shared between parts of apitools.    N)http_client)messages)encoding_helper)
exceptions)Iterable	DetectGae	DetectGcez:/?#[]@!$&'()*+,;=c                  C   s"   t jdd} | dp| dS )zDetermine whether or not we're running on GAE.

    This is based on:
      https://developers.google.com/appengine/docs/python/#The_Environment

    Returns:
      True iff we're running on GAE.
    SERVER_SOFTWARE zDevelopment/zGoogle App Engine/)osenvironget
startswith)server_software r   >/tmp/google-cloud-sdk/lib/third_party/apitools/base/py/util.pyr   -   s   	
c                  C   sr   d tjdd} ztti tj| ddid}W n t	j
y)   Y dS w | tjko8|jddkS )	zDetermine whether or not we're running on GCE.

    This is based on:
      https://cloud.google.com/compute/docs/metadata#runninggce

    Returns:
      True iff we're running on a GCE instance.
    z	http://{}GCE_METADATA_ROOTzmetadata.google.internalzMetadata-FlavorGoogle)headersFzmetadata-flavor)formatr   r   r   urllib_requestbuild_openerProxyHandleropenRequesturllib_errorURLErrorgetcoder   OKr   )metadata_urlor   r   r   r   ;   s   	c                 C   sX   t | tjrt| } t| dS t | tr"dd | D } t| S tdt	| f )z)Normalize scope_spec to a set of strings. c                 S   s   g | ]}t |qS r   )six
ensure_str).0xr   r   r   
<listcomp>V   s    z#NormalizeScopes.<locals>.<listcomp>z5NormalizeScopes expected string or iterable, found %s)

isinstancer"   string_typesr#   setsplitr   r   TypecheckErrortype)
scope_specr   r   r   NormalizeScopesP   s   

r.   c                 C   sL   t | |s$|d u rt |trdt| |f }ndt| |f }t|| S )Nz"Type of arg is "%s", not one of %rzType of arg is "%s", not "%s")r'   tupler,   r   r+   )argarg_typemsgr   r   r   	Typecheck]   s   


r3   c           
      C   s   |p| j pd}| jD ]r}d| }d}d| }||v r"t}|||}||vr-td| z|| }W n tyA   td| w |du rMtd| zt|tj	sXt
|}||t|d|}W q
 ty| }	 z
td|||	f d}	~	ww |S )	z(Determine the relative path for request.r
   z{%s}z{+%s}zMissing path parameter %sz%Request missing required parameter %sNutf_8z3Error setting required parameter %s to value %s: %s)relative_pathpath_params_RESERVED_URI_CHARSreplacer   InvalidUserInputErrorKeyErrorr'   r"   r(   strurllib_parsequoteencode	TypeError)
method_configparamsr5   pathparamparam_templatereserved_charsreserved_templatevalueer   r   r   ExpandRelativePathi   sP   
rI   <   c                 C   s2   d|  }|d }|t | |7 }tdt||S )a  Calculates amount of time to wait before a retry attempt.

    Wait time grows exponentially with the number of attempts. A
    random amount of jitter is added to spread out retry attempts from
    different clients.

    Args:
      retry_attempt: Retry attempt counter.
      max_wait: Upper bound for wait time [seconds].

    Returns:
      Number of seconds to wait before retrying request.

       g      @   )randomuniformmaxmin)retry_attemptmax_wait	wait_time
max_jitterr   r   r   CalculateWaitForRetry   s   rU   c                    s\   dvrt d dd | D }|rt dd| dd  t fd	d
| D S )a  Return True iff mime_type is acceptable for one of accept_patterns.

    Note that this function assumes that all patterns in accept_patterns
    will be simple types of the form "type/subtype", where one or both
    of these can be "*". We do not support parameters (i.e. "; q=") in
    patterns.

    Args:
      accept_patterns: list of acceptable MIME types.
      mime_type: the mime type we would like to match.

    Returns:
      Whether or not mime_type matches (at least) one of these patterns.
    /zInvalid MIME type: "%s"c                 S   s   g | ]}d |v r|qS );r   r$   pr   r   r   r&      s    z&AcceptableMimeType.<locals>.<listcomp>z.MIME patterns with parameter unsupported: "%s"z, c                 S   s0   | dkrd} t dd t| d|dD S )z4Return True iff mime_type is acceptable for pattern.*z*/*c                 s   s     | ]\}}|d |fv V  qdS )rZ   Nr   )r$   acceptprovidedr   r   r   	<genexpr>   s    z>AcceptableMimeType.<locals>.MimeTypeMatches.<locals>.<genexpr>rV   )allzipr*   )pattern	mime_typer   r   r   MimeTypeMatches   s
   z+AcceptableMimeType.<locals>.MimeTypeMatchesc                 3   s    | ]} |V  qd S Nr   )r$   r`   rb   ra   r   r   r]      s    z%AcceptableMimeType.<locals>.<genexpr>)r   r9   GeneratedClientErrorjoinany)accept_patternsra   unsupported_patternsr   rd   r   AcceptableMimeType   s   rj   c                    s    fdd| D S )z2Reverse parameter remappings for URL construction.c                    s   g | ]}t j |d p|qS ))	json_name)encodingGetCustomJsonFieldMappingrX   request_typer   r   r&      s    z!MapParamNames.<locals>.<listcomp>r   )rA   ro   r   rn   r   MapParamNames   s   
rp   c                 C   st   t | }|  D ]/\}}tj||d}|dur ||||< |}t|tjr7tjt	|t
|dp4t
|||< q|S )a  Perform any renames/remappings needed for URL construction.

    Currently, we have several ways to customize JSON encoding, in
    particular of field names and enums. This works fine for JSON
    bodies, but also needs to be applied for path and query parameters
    in the URL.

    This function takes a dictionary from param names to values, and
    performs any registered mappings. We also need the request type (to
    look up the mappings).

    Args:
      params: (dict) Map from param names to values
      request_type: (protorpc.messages.Message) request type for this API call

    Returns:
      A new dict of the same size, with all registered mappings applied.
    )python_nameN)dictitemsrl   rm   popr'   r   EnumGetCustomJsonEnumMappingr,   r;   )rA   ro   
new_params
param_namerG   field_remappingr   r   r   MapRequestParams   s    rz   rc   )rJ   )&__doc__r   rM   r"   	six.movesr   six.moves.urllib.errormovesurlliberrorr   six.moves.urllib.parseparser<   six.moves.urllib.requestrequestr   apitools.base.protorpcliter   apitools.base.pyr   rl   r   PY3collections.abcr   collections__all__r7   r   r   r.   r3   rI   rU   rj   rp   rz   r   r   r   r   <module>   s6   


'$