
    z*                         S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
  \R                  " \5      rSrSrSr\" \\\/5      r\rSrSrS	rS
 rS rS rS rS rS rS rS rS rSS jr S r!S r"S r#g)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                    ^  U 4S jn[        T [        R                  5      (       a  U$ [        R                  " T 5      u  n  p4[        [        U5      [        U5      -
  5      " T 5      $ )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                 J   >^  [         R                  " T 5      UU 4S j5       nU$ )Nc                    > [        U 5      T:  ak  SnTS:w  a  SnSR                  TR                  T[        U 5      US9n[        [        :X  a  [        U5      e[        [        :X  a  [        R                  U5        T" U 0 UD6$ )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_wrapperDpositional.<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_decorator(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9##&112EFa#d)c(m345HIIr#   c                 f    [        U [        R                  5      (       a  U $ SR                  U 5      $ )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_stringr6      s+     &#**++xxr#   c                 x    U (       d  / $ [        U [        R                  5      (       a  U R                  S5      $ U $ )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.
r1   )r(   r)   r2   splitr4   s    r    string_to_scopesr9      s3     		FC,,	-	-||C  r#   c                     [         R                  R                  U 5      n0 n[        R                  " U5       H?  u  p4[        U5      S:w  a$  SU< SSR                  U5      < 3n[        U5      eUS   X#'   MA     U$ )zParses 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   r3   
ValueError)contenturlencoded_paramsparamskeyvaluemsgs         r    parse_unique_urlencodedrE      sp     --g6Fmm$56
u:?!$dii&68CS/!Ah 7 Mr#   c                 &   [         R                  R                  U 5      n[        UR                  5      nUR                  U5        [         R                  R                  U5      nUR                  US9n[         R                  R                  U5      $ )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   r;   urlparserE   rG   update	urlencode_replace
urlunparse)urirA   partsquery_params	new_query	new_partss         r    update_query_paramsrR      sm    " LL!!#&E*5;;7L&&|4IY/I<<""9--r#   c                 &    Uc  U $ [        XU05      $ )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.
)rR   )urlnamerC   s      r    _add_query_parameterrV      s     }
"3u66r#   c                    [         R                  R                  U 5      (       a  [        [        R                  U 5      5      e[         R                  R                  U 5      (       a  [        [        R                  U 5      5      e[         R                  R                  U 5      (       d*  [        R                  " [        R                  U 5      5        g g )N)ospathislinkIOError_SYM_LINK_MESSAGEr   isdir_IS_DIR_MESSAGEisfilewarningswarn_MISSING_FILE_MESSAGE)filenames    r    validate_filerd      s    	ww~~h'..x899	x	 	 o,,X677WW^^H%%+228<= &r#   c                 :    U R                  S5      nUS:w  a  XS $ g)aV  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_keyrj     s+     /F|W%% r#   c                 ,    [         R                  " U SS9$ )N),:)
separators)jsondumps)datas    r    _json_encoderr     s    ::dz22r#   c                     [        U [        R                  5      (       a  U R                  U5      OU n[        U[        R                  5      (       a  U$ [        SR                  U 5      5      e)a  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   )rC   encodingresults      r    	_to_bytesry     sX    , E3==11 ll8$7< &#//**@GGNOOr#   c                     [        U [        R                  5      (       a  U R                  S5      OU n[        U[        R                  5      (       a  U$ [        SR                  U 5      5      e)a%  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)   rv   decodert   r>   r   )rC   rx   s     r    _from_bytesr}   7  s^     E3??33 ll7#9> &#--((5<<UCE 	Er#   c                 `    [        U SS9n [        R                  " U 5      R                  S5      $ )Nr{   )rw      =)ry   base64urlsafe_b64encoderstrip)	raw_bytess    r    _urlsafe_b64encoder   M  s*    )g6I##I.55d;;r#   c                 r    [        U 5      n U SS[        U 5      S-  -
  -  -   n[        R                  " U5      $ )Nr      )ry   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+   ro   loggingrX   r`   r)   	six.movesr   	getLoggerr   r   r   r   POSITIONAL_IGNORE	frozensetPOSITIONAL_SETr   r\   r^   rb   r-   r6   r9   rE   rR   rV   rd   rj   rr   ry   r}   r   r    r#   r    <module>r      s     4      	  
  
		8	$ "  .0D-/ 0 %7 !4 'F `JF &(..27&>&&3P:E,<
,r#   