
    '                     $   d 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	Z	ddl
Z
g dZ G d de      ZdZ ej                  eej                   ej"                  z        Zd Z ed	      d
        Zd Z G d dej,                        ZddZy)zCommon utility library.    )with_statementN)Errordecode_datetimeget_package_for_module
positionalTimeZoneOffsettotal_secondsc                       e Zd ZdZy)r   z#Base class for protorpc exceptions.N)__name__
__module____qualname____doc__     2lib/third_party/apitools/base/protorpclite/util.pyr   r   (   s    -r   r   z
  # Examples:
  #   +01:00
  #   -05:30
  #   Z12:00
  ((?P<z>Z) | (?P<sign>[-+])
   (?P<hours>\d\d) :
   (?P<minutes>\d\d))$
c                       fd}t         t        j                        r|S t        j                         ^}}}}}|t        d       t        t        |      t        |      z
               S )a	  A decorator that declares only the first N arguments may 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):
            ...

      One can omit the argument to 'positional' altogether, and then no
      arguments with default values may be passed positionally. This
      would be equivalent to placing a '*' before the first argument
      with a default value in Python 3. If there are no arguments with
      default values, and no argument is given to 'positional', an error
      is raised.

        @positional
        def fn(arg1, arg2, required_kw1=None, required_kw2=0):
          ...

        fn(1, 3, 5)  # Raises exception.
        fn(1, 3)  # Ok.
        fn(1, 3, required_kw1=5)  # Ok.

    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 keyword-only argument is provided as a positional
        parameter.
      ValueError if no maximum number of arguments is provided and the function
        has no arguments with default values.
    c                 F     t        j                          fd       }|S )z9Creates a function wraper to enforce number of arguments.c            	          t        |       kD  r.d}dk7  rd}t        dj                  |t        |       fz         | i |S )N    sz6%s() takes at most %d positional argument%s (%d given))len	TypeErrorr   )argskwargsplural_smax_positional_argswrappeds      r   positional_wrapperzDpositional.<locals>.positional_decorator.<locals>.positional_wrapper   si    4y..&!+"H !-070@0@0C08#d)0E!E F F D+F++r   )	functoolswraps)r   r   r   s   ` r   positional_decoratorz(positional.<locals>.positional_decorator   s&    		!		, 
"		, "!r   zDFunctions with no keyword arguments must specify max_positional_args)
isinstancesixinteger_typesinspectgetfullargspec
ValueErrorr   r   )r   r"   r   _defaultss   `    r   r   r   8   sx    Z" %s'8'89###*#9#9:M#N aHq&' ' 5z#d)c(m345HIIr   r   c                 `   t        | t        j                        r	 t        j                  |    } 	 t        j                  | j                        S # t
        $ r Y yw xY w# t        $ r | j                  dk(  r	 | j                  }t        j                  j                  |      }t        j                  j                  |      }t        |      dk(  rt        j                  |      cY S dj!                  |dd       cY S # t        $ r Y nw xY wt        j                  | j                        cY S w xY w)a  Get package name for a module.

    Helper calculates the package name of a module.

    Args:
      module: Module to get name for.  If module is a string, try to find
        module in sys.modules.

    Returns:
      If module contains 'package' attribute, uses that as package name.
      Else, if module is not the '__main__' module, the module __name__.
      Else, the base name of the module file name.  Else None.
    N__main__r   .)r#   r$   string_typessysmodulesKeyError	text_typepackageAttributeErrorr   __file__ospathbasenamesplitextr   join)module	file_name	base_name
split_names       r   r   r      s     &#**+	[[(F.}}V^^,,	  		
  .??j(	2"OO	 GG,,Y7	WW--i8
z?a'==33yyCR11 "  }}V__--.sM   A A 	AAD-7C<A!D-&D-<	DD-D"D-,D-c                 t    | j                   dz  dz  dz  | j                  z   }|dz  | j                  z   }|dz  S )z4Backport of offset.total_seconds() from python 2.7+.   <   i@B g    .A)dayssecondsmicroseconds)offsetrD   rE   s      r   r	   r	      sB    kkB#b(6>>9GU?V%8%88L;''r   c                   .     e Zd ZdZ fdZd Zd Z xZS )r   z<Time zone information as encoded/decoded for DateTimeFields.c                     t         t        |           t        |t        j
                        rt        |      dz  }|| _        y)zInitialize a time zone offset.

        Args:
          offset: Integer or timedelta time zone offset, in minutes from UTC.
            This can be negative.
        rB   N)superr   __init__r#   datetime	timedeltar	   _TimeZoneOffset__offset)selfrF   	__class__s     r   rJ   zTimeZoneOffset.__init__   s8     	nd,.fh001"6*R/Fr   c                 B    t        j                  | j                        S )zGet the a timedelta with the time zone's offset from UTC.

        Returns:
          The time zone offset from UTC, as a timedelta.
        )minutes)rK   rL   rM   rN   r)   s     r   	utcoffsetzTimeZoneOffset.utcoffset   s     !!$--88r   c                 ,    t        j                  d      S )a   Get the daylight savings time offset.

        The formats that ProtoRPC uses to encode/decode time zone
        information don't contain any information about daylight
        savings time. So this always returns a timedelta of 0.

        Returns:
          A timedelta of 0.

        r   )rK   rL   rR   s     r   dstzTimeZoneOffset.dst   s     !!!$$r   )r   r   r   r   rJ   rS   rU   __classcell__)rO   s   @r   r   r      s    F
9%r   r   c                    t         j                  |       }|r#| d|j                  d       j                         }n| j                         }d|v rd}nd}	 t        j                  j                  ||      }|s|S |j                  d	      rd
}	nO|j                  d      }
|j                  dd      D cg c]  }t        |       c}\  }}|dz  |z   }	|
dk(  r|	dz  }	t	        j                  |j                  |j                  |j                   |j"                  |j$                  |j&                  |j(                  t+        |	            S # t        $ r{ |rtd|v rp|j                  d      \  }}t        |      dkD  rMdj                  ||dd       }t        j                  j                  ||      }t        j                  d||       n  Y Uw xY wc c}w )a  Decode a DateTimeField parameter from a string to a python datetime.

    Args:
      encoded_datetime: A string in RFC 3339 format.
      truncate_time: If true, truncate time string with precision higher than
          microsecs.

    Returns:
      A datetime object with the date and time specified in encoded_datetime.

    Raises:
      ValueError: If the string is not in a recognized format.
    Nr   r-   z%Y-%m-%dT%H:%M:%S.%fz%Y-%m-%dT%H:%M:%S   z{}.{}z,Truncating the datetime string from %s to %szr   signhoursrQ   rB   -r.   )_TIME_ZONE_REsearchstartupperrK   strptimer(   splitr   formatloggingwarninggroupintyearmonthdayhourminutesecondmicrosecondr   )encoded_datetimetruncate_timetime_zone_matchtime_stringformat_stringdecoded_datetimedatetime_stringdecimal_secstruncated_time_stringoffset_minutesrZ   valuer[   rQ   s                 r   r   r      s   " $**+;<O&'@(=(=a(@AGGI&,,.
k.+#,,55k6CE( 
 S!$$V,)//CEC */#e*CEwg-3;b N-22-33-11-22-44-44-99+N;= =E  SK/,7,=,=c,B)O\< 1$(/#\"1%5)7%#+#4#4#=#=)!$#  B!68 88Es    E 2GB G
G)F)r   
__future__r   rK   r    r&   rd   r7   rer0   r$   __all__	Exceptionr   _TIME_ZONE_RE_STRINGcompile
IGNORECASEVERBOSEr]   r   r   r	   tzinfor   r   r   r   r   <module>r      s   "  %     	 	 
 
.I .  

/1KLdJN A#. #.L("%X__ "%JH=r   