o
    9                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddlm	Z	 e
dZdd	 Zd#ddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zd$ddZdd Zdd  Zd!d" ZdS )%zResource property Get.    )absolute_import)division)unicode_literalsN)rangez9((?<=[a-z0-9])[A-Z]+(?=[A-Z][a-z]|$)|(?!^)[A-Z](?=[a-z]))c                 C   sF   z| D ]}| ||kr|  W S qW dS  ttttfy"   Y dS w )az  Gets the dict in items that contains key==value.

  A metadict object is a list of dicts of the form:
    [
      {key: value-1, ...},
      {key: value-2, ...},
      ...
    ]

  Args:
    items: A list of dicts.
    key: The dict key name.
    value: The dict key value.

  Returns:
    The dict in items that contains key==value or None if no match or not a
    metadict.
  N)getAttributeError
IndexError	TypeError
ValueError)itemskeyvalueitem r   K/tmp/google-cloud-sdk/lib/googlecloudsdk/core/resource/resource_property.py_GetMetaDict!   s   
r   Fc              	   C   sR   t | d|}|du rdS |dd}|r'zt|W S  ttfy&   Y |S w |S )aY  Gets the metadata value for the item in items with key == name.

  A metadata object is a list of dicts of the form:
    [
      {'key': key-name-1, 'value': field-1-value-string},
      {'key': key-name-2, 'value': field-2-value-string},
      ...
    ]

  Examples:
    x.metadata[windows-keys].email
      Deserializes the 'windows-keys' metadata value and gets the email value.
    x.metadata[windows-keys]
      Gets the 'windows-key' metadata string value.
    x.metadata[windows-keys][]
      Gets the deserialized 'windows-key' metadata value.

  Args:
    items: The metadata items list.
    name: The metadata name (which must match one of the 'key' values).
    deserialize: If True then attempt to deserialize a compact JSON string.

  Returns:
    The metadata value for name or None if not found or if items is not a
    metadata dict list.
  r   Nr   )r   r   jsonloadsr	   r
   )r   namedeserializer   r   r   r   r   _GetMetaDataValue=   s   r   c                 C   s.   |  d}|d ddd |dd D  S )z&Converts snake_case name to camelCase._r    c                 s   s    | ]}|  V  qd S N)title).0xr   r   r   	<genexpr>g   s    z%ConvertToCamelCase.<locals>.<genexpr>   N)splitjoin)r   partr   r   r   ConvertToCamelCased   s   
$r"   c                 C      t d|  S )z&Converts camelCase name to snake_case._\1)	_SNAKE_REsublowerr   r   r   r   ConvertToSnakeCasej      r)   c                 C   r#   )z,Converts camelCase name to ANGRY_SNAKE_CASE.r$   )r%   r&   upperr(   r   r   r   ConvertToAngrySnakeCaseo   r*   r,   c                 C   sF   || r| S t | tjsdS ttfD ]}|| }||r |  S qdS )z6Returns index converted to a case that satisfies func.N
isinstancesixstring_typesr"   r)   )indexfuncconvertr   r   r   r   GetMatchingIndext   s   r4   c                 C   sJ   || }|r|S t | tjsdS ttfD ]}||| }|r"|  S qdS )z?Returns the first non-None func value for case-converted index.Nr-   )r1   r2   r   r3   r   r   r   GetMatchingIndexValue   s   r5   c                 C   s   g }| D ]8}t |tjsqdd ttfD ]}||}z||j}W n ttfy-   Y qw  ntd	||
| q|tjkrDt}||fS )a  Returns the messages module type for key in message and the actual key.

  Handles camelCase/snake_case key name variants for OnePlatform compatibility.
  Indices and slices in resource_key are ignored -- they are not needed for
  repeated field queries.

  Args:
    resource_key: Ordered list of key names/indices, applied left to right. Each
      element in the list may be one of:
        str - A resource property name. This could be a class attribute name or
          a dict index.
        int - A list index. Selects one member is the list. Negative indices
          count from the end of the list, starting with -1 for the last element
          in the list. An out of bounds index is not an error; it produces the
          value None.
        None - A list slice. Selects all members of a list or dict like object.
          A slice of an empty dict or list is an empty dict or list.
    message: The known proto message type if not None.

  Raises:
    KeyError: If key is not in message.

  Returns:
    (type, actual_key), the messages module type for key in message and the
      actual key (names in the proper case, indices omitted).
  c                 S      | S r   r   r   r   r   r   <lambda>       z%GetMessageFieldType.<locals>.<lambda>zField {} not in message.)r.   r/   r0   r"   r)   field_by_nametyper   KeyErrorformatappendinteger_typesint)resource_keymessage
actual_keyr   r3   actual_namer   r   r   GetMessageFieldType   s"   
rE   c                    sN   dd t tfD ]  fdd| D }ddd |D }||v r$|  S qdS )al  Returns the actual_key match of resource_key in fields.

  Handles camelCase/snake_case key name variants for OnePlatform compatibility.
  Indices and slices in resource_key are ignored to normalize the lookup. This
  means that the lookup can determine the existence of an attribute name, but
  not a specific value among all repeated values.

  Args:
    resource_key: Ordered list of key names/indices, applied left to right. Each
      element in the list may be one of:
        str - A resource property name. This could be a class attribute name or
          a dict index.
        int - A list index. Selects one member is the list. Negative indices
          count from the end of the list, starting with -1 for the last element
          in the list. An out of bounds index is not an error; it produces the
          value None.
        None - A list slice. Selects all members of a list or dict like object.
          A slice of an empty dict or list is an empty dict or list.
    fields: The set of dotted field names to match against.

  Returns:
    The actual_key match of resource_key in fields or None if no match.
  c                 S   r6   r   r   r7   r   r   r   r8      r9   zLookupField.<locals>.<lambda>c                    s$   g | ]}t |tjr |n|qS r   r.   r/   r0   r   r   r3   r   r   
<listcomp>   s    zLookupField.<locals>.<listcomp>.c                 S   s   g | ]
}t |tjr|qS r   rF   rG   r   r   r   rI      s    

N)r"   r)   r    )rA   fieldsrC   
lookup_keyr   rH   r   LookupField   s   
rM   c                    s>  t || rdttrtdu r S tdrXdu r5r3 fddD S S tfdd}|rE| qdv rVfdd	}t|q S ttj	rvtfd
d}|rvt
| }t|sv|qtdsttj	rdu rr fddttD S S ttjsttj	rtt rtrtd trrtd }|dur|dqnt}|dur|S d v r fddttD S dd fddD D p S  S tt tv r q S ttrtS )a  Gets the value referenced by key in the object resource.

  Since it is common for resource instances to be sparse it is not an error if
  a key is not present in a particular resource instance, or if an index does
  not match the resource type.

  Args:
    resource_obj: The resource object possibly containing a value for key.
    resource_key: Ordered list of key names/indices, applied left to right. Each
      element in the list may be one of:
        str - A resource property name. This could be a class attribute name or
          a dict index.
        int - A list index. Selects one member is the list. Negative indices
          count from the end of the list, starting with -1 for the last element
          in the list. An out of bounds index is not an error; it produces the
          value None.
        None - A list slice. Selects all members of a list or dict like object.
          A slice of an empty dict or list is an empty dict or list.
    default: Get() returns this value if key is not in resource.

  Returns:
    The value, None if any of the given keys are not found. This is
      intentionally not an error. In this context a value can be any data
      object: dict, list, tuple, class, str, int, float, ...
  r   Nr   c                       g | ]}t |g  qS r   Getr   kdefaultr   resourcer   r   rI     s    zGet.<locals>.<listcomp>c                    s   |  v S r   r   r7   rU   r   r   r8     s    zGet.<locals>.<lambda>c                    s   t d | t dS )Nr   )r   )r   boolr1   )r   rU   r   r   	_GetValue$  s   zGet.<locals>._GetValuec                    s
   t  | S r   )hasattrr7   rV   r   r   r8   0  s   
 __iter__c                    rN   r   rO   rQ   rS   r   r   rI   <  s    c                    s    g | ]}t |g  qS r   rO   rQ   rT   r1   r   rU   r   r   rI   W  s    c                 S   s   g | ]}|r|qS r   r   )r   fr   r   r   rI   `  s    c                    s   g | ]}|  qS r   )r   )r   drX   r   r   rI   `  s    )listpopr.   setsortedrZ   r4   r5   r/   r0   getattrcallabler   lenr?   dictr   r   )resource_objrA   rT   r   rY   rr   r\   r   rP      s   







	rP   c                 C   s   t | |dduS )z*True if resource contains key, else False.NrO   )rU   r   r   r   r   ResourceContainsKeyt  r*   ri   c                 C   sD  | sdS t | tjrzt|| W S  ty   Y nw t | ttfr7z
t|t| W S  ty6   Y nw zt	| D ]\}}|
dsPt|||rP W dS q=W n' tyy   z| D ]}t|||ri W Y dS q\W Y dS  tyv   Y nw Y nw zt	| jD ]\}}|
dst|||r W dS qW dS  ty   Y dS w )ao  Returns True if any attribute value in resource matches the RE pattern.

  This function is called to evaluate a global restriction on a resource. For
  example, --filter="Foo.Bar" results in a call like this on each resource item:

    resource_property.EvaluateGlobalRestriction(
      resource,
      'Foo.Bar',
      re.compile(re.escape('Foo.Bar'), re.IGNORECASE),
    )

  Args:
    resource: The object to check.
    restriction: The global restriction string.
    pattern: The global restriction pattern for matcing resource values.

  Returns:
    True if any attribute value in resource matches the RE pattern.
  Fr   T)r.   r/   r0   rW   searchr	   floatr@   str	iteritems
startswithEvaluateGlobalRestrictionr   __dict__)rU   restrictionpatternr   r   r   r   r   ro   y  s^   
ro   c                 C   s(   t | tpt| dot| dpt| dS )zChecks if resource is a list-like iterable object.

  Args:
    resource: The object to check.

  Returns:
    True if resource is a list-like iterable object.
  r[   next__next__)r.   r_   rZ   rV   r   r   r   
IsListLike  s   
	
ru   )Fr   )__doc__
__future__r   r   r   r   rer/   	six.movesr   compiler%   r   r   r"   r)   r,   r4   r5   rE   rM   rP   ri   ro   ru   r   r   r   r   <module>   s2   
'2
" 7