
    z*                         d 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ZddlZddl	m
Z
  ej                  e      ZdZdZdZ eeeeg      ZeZdZdZd	Zd
 Zd Zd Zd Zd Zd Zd Zd Zd ZddZ d Z!d Z"d Z#y)z-Helper functions for commonly used utilities.    N)urllibWARNING	EXCEPTIONIGNOREzFile: {0}: Is a symbolic link.z{0}: Is a directoryz,Cannot access {0}: No such file or directoryc                       fd}t         t        j                        r|S t        j                         \  }}}} t        t        |      t        |      z
               S )a  A decorator to declare that only the first N arguments my be positional.

    This decorator makes it easy to support Python 3 style keyword-only
    parameters. For example, in Python 3 it is possible to write::

        def fn(pos1, *, kwonly1=None, kwonly1=None):
            ...

    All named parameters after ``*`` must be a keyword::

        fn(10, 'kw1', 'kw2')  # Raises exception.
        fn(10, kwonly1='kw1')  # Ok.

    Example
    ^^^^^^^

    To define a function like above, do::

        @positional(1)
        def fn(pos1, kwonly1=None, kwonly2=None):
            ...

    If no default value is provided to a keyword argument, it becomes a
    required keyword argument::

        @positional(0)
        def fn(required_kw):
            ...

    This must be called with the keyword parameter::

        fn()  # Raises exception.
        fn(10)  # Raises exception.
        fn(required_kw=10)  # Ok.

    When defining instance or class methods always remember to account for
    ``self`` and ``cls``::

        class MyClass(object):

            @positional(2)
            def my_method(self, pos1, kwonly1=None):
                ...

            @classmethod
            @positional(2)
            def my_method(cls, pos1, kwonly1=None):
                ...

    The positional decorator behavior is controlled by
    ``_helpers.positional_parameters_enforcement``, which may be set to
    ``POSITIONAL_EXCEPTION``, ``POSITIONAL_WARNING`` or
    ``POSITIONAL_IGNORE`` to raise an exception, log a warning, or do
    nothing, respectively, if a declaration is violated.

    Args:
        max_positional_arguments: Maximum number of positional arguments. All
                                  parameters after the this index must be
                                  keyword only.

    Returns:
        A decorator that prevents using arguments after max_positional_args
        from being used as positional parameters.

    Raises:
        TypeError: if a key-word only argument is provided as a positional
                   parameter, but only if
                   _helpers.positional_parameters_enforcement is set to
                   POSITIONAL_EXCEPTION.
    c                 F     t        j                          fd       }|S )Nc                     t        |       kD  rkd}dk7  rd}dj                  j                  t        |       |      }t        t        k(  rt        |      t        t        k(  rt        j                  |        | i |S )N    szV{function}() takes at most {args_max} positional argument{plural} ({args_given} given))functionargs_max
args_givenplural)	lenformat__name__!positional_parameters_enforcementPOSITIONAL_EXCEPTION	TypeErrorPOSITIONAL_WARNINGloggerwarning)argskwargsplural_smessagemax_positional_argswrappeds       4platform/bq/third_party/oauth2client_4_0/_helpers.pypositional_wrapperzDpositional.<locals>.positional_decorator.<locals>.positional_wrapperv   s    4y..&!+"HCCI6(/(8(8(;*-d)&.	 DJ D0  58LL#G,,6:LLNN7+D+F++    )	functoolswraps)r   r!   r   s   ` r    positional_decoratorz(positional.<locals>.positional_decoratoru   s&    		!	, 
"	,  "!r"   )
isinstancesixinteger_typesinspect
getargspec
positionalr   )r   r%   r   _defaultss   `    r    r+   r+   -   s\    P"( %s'8'89##&112EFaH4z#d)c(m345HIIr"   c                 \    t        | t        j                        r| S dj                  |       S )a_  Converts scope value to a string.

    If scopes is a string then it is simply passed through. If scopes is an
    iterable then a string is returned that is all the individual scopes
    concatenated with spaces.

    Args:
        scopes: string or iterable of strings, the scopes.

    Returns:
        The scopes formatted as a single string.
     )r&   r'   string_typesjoinscopess    r    scopes_to_stringr4      s(     &#**+xxr"   c                 d    | sg S t        | t        j                        r| j                  d      S | S )a+  Converts stringifed scope value to a list.

    If scopes is a list then it is simply passed through. If scopes is an
    string then a list of each individual scope is returned.

    Args:
        scopes: a string or iterable of strings, the scopes.

    Returns:
        The scopes in a list.
    r/   )r&   r'   r0   splitr2   s    r    string_to_scopesr7      s0     		FC,,	-||C  r"   c                     t         j                  j                  |       }i }t        j                  |      D ]=  \  }}t        |      dk7  r"d|ddj                  |      }t        |      |d   ||<   ? |S )a  Parses unique key-value parameters from urlencoded content.

    Args:
        content: string, URL-encoded key-value pairs.

    Returns:
        dict, The key-value pairs from ``content``.

    Raises:
        ValueError: if one of the keys is repeated.
    r   z.URL-encoded content contains a repeated value:z -> z, r   )r   parseparse_qsr'   	iteritemsr   r1   
ValueError)contenturlencoded_paramsparamskeyvaluemsgs         r    parse_unique_urlencodedrC      st     --g6Fmm$56
Uu:?!$dii&68CS/!Ahs 7 Mr"   c                 ,   t         j                  j                  |       }t        |j                        }|j                  |       t         j                  j                  |      }|j                  |      }t         j                  j                  |      S )a  Updates a URI with new query parameters.

    If a given key from ``params`` is repeated in the ``uri``, then
    the URI will be considered invalid and an error will occur.

    If the URI is valid, then each value from ``params`` will
    replace the corresponding value in the query parameters (if
    it exists).

    Args:
        uri: string, A valid URI, with potential existing query parameters.
        params: dict, A dictionary of query parameters.

    Returns:
        The same URI but with the new query parameters added.
    )query)	r   r9   urlparserC   rE   update	urlencode_replace
urlunparse)urir?   partsquery_params	new_query	new_partss         r    update_query_paramsrP      sm    " LL!!#&E*5;;7L&&|4IY/I<<""9--r"   c                 &    || S t        | ||i      S )a\  Adds a query parameter to a url.

    Replaces the current value if it already exists in the URL.

    Args:
        url: string, url to add the query parameter to.
        name: string, query parameter name.
        value: string, query parameter value.

    Returns:
        Updated query parameter. Does not update the url if value is None.
    )rP   )urlnamerA   s      r    _add_query_parameterrT      s     }
"3u66r"   c                    t         j                  j                  |       rt        t        j                  |             t         j                  j                  |       rt        t        j                  |             t         j                  j                  |       s)t        j                  t        j                  |              y y )N)ospathislinkIOError_SYM_LINK_MESSAGEr   isdir_IS_DIR_MESSAGEisfilewarningswarn_MISSING_FILE_MESSAGE)filenames    r    validate_filerb      s|    	ww~~h'..x899	x	 o,,X677WW^^H%+228<= &r"   c                 :    | j                  d      }|dk7  r| |d S y)az  Identify and extract PEM keys.

    Determines whether the given key is in the format of PEM key, and extracts
    the relevant part of the key if it is.

    Args:
        raw_key_input: The contents of a private key file (either PEM or
                       PKCS12).

    Returns:
        string, The actual key if the contents are from a PEM file, or
        else None.
    s   -----BEGIN N)find)raw_key_inputoffsets     r    _parse_pem_keyrh     s-     /F|VW%% r"   c                 0    t        j                  | d      S )N),:)
separators)jsondumps)datas    r    _json_encoderp     s    ::dz22r"   c                     t        | t        j                        r| j                  |      n| }t        |t        j                        r|S t        dj                  |             )a4  Converts a string value to bytes, if necessary.

    Unfortunately, ``six.b`` is insufficient for this task since in
    Python2 it does not modify ``unicode`` objects.

    Args:
        value: The string/bytes value to be converted.
        encoding: The encoding to use to convert unicode to bytes. Defaults
                  to "ascii", which will not allow any characters from ordinals
                  larger than 127. Other useful values are "latin-1", which
                  which will only allows byte ordinals (up to 255) and "utf-8",
                  which will encode any unicode that needs to be.

    Returns:
        The original value converted to bytes (if unicode) or as passed in
        if it started out as bytes.

    Raises:
        ValueError if the value could not be converted to bytes.
    z%{0!r} could not be converted to bytes)r&   r'   	text_typeencodebinary_typer<   r   )rA   encodingresults      r    	_to_bytesrw     sR    , E3==1 ll8$7< &#//*@GGNOOr"   c                     t        | t        j                        r| j                  d      n| }t        |t        j                        r|S t        dj                  |             )aE  Converts bytes to a string value, if necessary.

    Args:
        value: The string/bytes value to be converted.

    Returns:
        The original value converted to unicode (if bytes) or as passed in
        if it started out as unicode.

    Raises:
        ValueError if the value could not be converted to unicode.
    utf-8z'{0!r} could not be converted to unicode)r&   r'   rt   decoderr   r<   r   )rA   rv   s     r    _from_bytesr{   7  sX     E3??3 ll7#9> &#--(5<<UCE 	Er"   c                 d    t        | d      } t        j                  |       j                  d      S )Nry   )ru      =)rw   base64urlsafe_b64encoderstrip)	raw_bytess    r    _urlsafe_b64encoder   M  s*    )g6I##I.55d;;r"   c                 p    t        |       } | ddt        |       dz  z
  z  z   }t        j                  |      S )Nr}      )rw   r   r~   urlsafe_b64decode)	b64stringpaddeds     r    _urlsafe_b64decoder   R  s:    )$IS^a%7!788F##F++r"   )ascii)$__doc__r~   r#   r)   rm   loggingrV   r^   r'   	six.movesr   	getLoggerr   r   r   r   POSITIONAL_IGNORE	frozensetPOSITIONAL_SETr   rZ   r\   r`   r+   r4   r7   rC   rP   rT   rb   rh   rp   rw   r{   r   r    r"   r    <module>r      s     4      	  
  
		8	$ "  .0D-/ 0 %7 !4 'F `JF &(..27&>&&3P:E,<
,r"   