o
    '                     @   s   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 deZdZeeejejB Zdd	 Zed
dd Zdd ZG dd dejZdddZdS )zCommon utility library.    )with_statementN)Errordecode_datetimeget_package_for_module
positionalTimeZoneOffsettotal_secondsc                   @   s   e Zd ZdZdS )r   z#Base class for protorpc exceptions.N)__name__
__module____qualname____doc__ r   r   H/tmp/google-cloud-sdk/lib/third_party/apitools/base/protorpclite/util.pyr   (   s    r   z
  # Examples:
  #   +01:00
  #   -05:30
  #   Z12:00
  ((?P<z>Z) | (?P<sign>[-+])
   (?P<hours>\d\d) :
   (?P<minutes>\d\d))$
c                    sX    fdd}t  tjr|S t ^}}}}}|du r tdtt|t|  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                    s   t   fdd}|S )z9Creates a function wraper to enforce number of arguments.c                     sD   t |  krd} dkrd}tdj |t | f | i |S )N    sz6%s() takes at most %d positional argument%s (%d given))len	TypeErrorr	   )argskwargsplural_s)max_positional_argswrappedr   r   positional_wrapper   s   zDpositional.<locals>.positional_decorator.<locals>.positional_wrapper)	functoolswraps)r   r   r   )r   r   positional_decorator   s   
z(positional.<locals>.positional_decoratorNzDFunctions with no keyword arguments must specify max_positional_args)
isinstancesixinteger_typesinspectgetfullargspec
ValueErrorr   r   )r   r   r   _defaultsr   r   r   r   8   s   Mr   r   c                 C   s   t | tjrztj|  } W n
 ty   Y dS w zt| jW S  tyf   | j	dkr^z| j
}W n	 ty9   Y n%w tj|}tj|}t|dkrSt| Y S d|dd  Y S t| j	 Y S 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_namer   r   r   r      s,   

r   c                 C   s.   | j d d d | j }|d | j }|d S )z4Backport of offset.total_seconds() from python 2.7+.   <   i@B g    .A)dayssecondsmicroseconds)offsetr=   r>   r   r   r   r      s   r   c                       s0   e Zd ZdZ fddZdd Zdd Z  ZS )r   z<Time zone information as encoded/decoded for DateTimeFields.c                    s0   t t|   t|tjrt|d }|| _dS )zInitialize a time zone offset.

        Args:
          offset: Integer or timedelta time zone offset, in minutes from UTC.
            This can be negative.
        r;   N)superr   __init__r   datetime	timedeltar   _TimeZoneOffset__offset)selfr?   	__class__r   r   rA      s   
zTimeZoneOffset.__init__c                 C   s   t j| jdS )zGet the a timedelta with the time zone's offset from UTC.

        Returns:
          The time zone offset from UTC, as a timedelta.
        )minutes)rB   rC   rD   rE   r$   r   r   r   	utcoffset   s   zTimeZoneOffset.utcoffsetc                 C   s
   t 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   )rB   rC   rI   r   r   r   dst   s   
zTimeZoneOffset.dst)r	   r
   r   r   rA   rJ   rK   __classcell__r   r   rF   r   r      s
    r   Fc                 C   sD  t | }|r| d|d  }n|  }d|v rd}nd}z	tj||}W n7 ty`   |r]d|v r]|d\}}t|dkr\d	||dd }tj||}t
d|| n  Y nw |se|S |d	rmd
}	n |d}
dd |ddD \}}|d | }	|
dkr|	d9 }	t|j|j|j|j|j|j|jt|	S )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   signc                 S   s   g | ]}t |qS r   )int).0valuer   r   r   
<listcomp>-  s    z#decode_datetime.<locals>.<listcomp>hoursrH   r;   -r(   )_TIME_ZONE_REsearchstartupperrB   strptimer#   splitr   formatloggingwarninggroup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_minutesrO   rT   rH   r   r   r   r      sd   




r   )F)r   
__future__r   rB   r   r!   r]   r1   rer*   r   __all__	Exceptionr   _TIME_ZONE_RE_STRINGcompile
IGNORECASEVERBOSErV   r   r   r   tzinfor   r   r   r   r   r   <module>   s(   
	g
&%