o
                         @  s  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZddlmZ ddl	Z	ddl
mZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dZdZdZdZd\Z Z!d\Z"Z#Z$Z%d\Z&Z'Z(dZ)		dUddZ*G dd de+Z,G dd de,Z-G dd  d e.Z/d!d" Z0d#Z1e2d$Z3d%d& Z4e5e6e6e7e8ej9d'Z:d(d) Z;d*d+ Z<G d,d- d-e.Z=G d.d/ d/ej>d0Z?G d1d2 d2e?ej@ZAe	jBd3d4G d5d6 d6ZCG d7d8 d8ej>d0ZDG d9d: d:ejEej>d0ZFG d;d< d<eFeDZGd=d> ZHG d?d@ d@eFeDZIG dAdB dBeFeDZJG dCdD dDeFeDZKdEdF ZLG dGdH dHejMZNdIdJ ZOG dKdL dLe?ejPZQG dMdN dNe?ejPZRe	jBd3d4G dOdP dPZSG dQdR dRejEZTG dSdT dTe?ejUZVdS )Vz0Data objects to support the yaml command schema.    )absolute_import)annotations)division)unicode_literalsN)Callable)Any)messages)actions)arg_parsers)arg_parsers_usage_text)	arg_utils)labels_util)module_util)http_encoding__name____resource_id____relative_name____resource_type__keyvalue)
arg_objectarg_dictarg_listarg_json)specparamsgroup	file_typec                 C  s   |r|  }|p| |t< | |t< | |t< nt|i}||t< z	| jdi |W S  tyM } z|j	rGtd|j	d d
| |d}~ww )aT  Formats a string with all the attributes of the given resource ref.

  Args:
    format_string: str, The format string.
    resource_ref: resources.Resource, The resource reference to extract
      attributes from.
    display_name: the display name for the resource.
    display_resource_type:

  Returns:
    str, The formatted string.
  zKKey [{}] does not exist. Must specify one of the following keys instead: {}r   z, N )AsDictNameNAME_FORMAT_KEYRESOURCE_ID_FORMAT_KEYRelativeNameREL_NAME_FORMAT_KEYRESOURCE_TYPE_FORMAT_KEYformatKeyErrorargsjoinkeys)format_stringresource_refdisplay_namedisplay_resource_typederrr   r   Z/tmp/google-cloud-sdk/lib/googlecloudsdk/command_lib/util/apis/yaml_command_schema_util.pyFormatResourceAttrStr2   s(   
r3   c                   @     e Zd ZdZdS )ErrorzBase class for module errors.Nr   
__module____qualname____doc__r   r   r   r2   r5   U       r5   c                   @  r4   )InvalidSchemaErrorz+Error for when a yaml command is malformed.Nr6   r   r   r   r2   r;   Z   r:   r;   c                   @  s:   e Zd ZdZedd Zedd ZdddZd	d
 ZdS )Hooka  Represents a Python code hook declared in the yaml spec.

  A code hook points to some python element with a module path, and attribute
  path like: package.module:class.attribute.

  If arguments are provided, first the function is called with the arguments
  and the return value of that is the hook that is used. For example:

  googlecloudsdk.calliope.arg_parsers:Duration:lower_bound=1s,upper_bound=1m
  c                 C  s   | |}|r| |S dS )zGets the hook from the spec data.

    Args:
      data: The yaml spec
      key: The key to extract the hook path from.

    Returns:
      The Python element to call.
    N)getFromPath)clsdatar   pathr   r   r2   FromDatak   s   

zHook.FromDatac                 C  s   t | S )zGets the hook from the function path.

    Args:
      path: str, The module path to the hook function.

    Returns:
      The Python element to call.
    )ImportPythonHookGetHook)r?   rA   r   r   r2   r>   {   s   
zHook.FromPathNc                 C  s   || _ || _d S N)	attributekwargs)selfrF   rG   r   r   r2   __init__   s   
zHook.__init__c                 C  s"   | j dur| jdi | j S | jS )zaGets the Python element that corresponds to this hook.

    Returns:
      A Python element.
    Nr   )rG   rF   rH   r   r   r2   rD      s   
zHook.GetHookrE   )	r   r7   r8   r9   classmethodrB   r>   rI   rD   r   r   r   r2   r<   _   s    


r<   c              
   C  s   |  d}t|dkrt|dkrtd| zt|d d |d  }W n tjy< } ztd| |d}~ww d}t|dkrri }|d  d	D ]#}|sSqN| d
}t|dkretd| |d  ||d  < qNt||S )au  Imports the given python hook.

  Depending on what it is used for, a hook is a reference to a class, function,
  or attribute in Python code.

  Args:
    path: str, The path of the hook to import. It must be in the form of:
      package.module:attribute.attribute where the module path is separated from
      the class name and sub attributes by a ':'. Additionally, ":arg=value,..."
      can be appended to call the function with the given args and use the
      return value as the hook.

  Raises:
    InvalidSchemaError: If the given module or attribute cannot be loaded.

  Returns:
    Hook, the hook configuration.
  :      zzInvalid Python hook: [{}]. Hooks must be in the format: package(.module)+:attribute(.attribute)*(:arg=value(,arg=value)*)?r      z&Could not import Python hook: [{}]. {}N,=zKInvalid Python hook: [{}]. Args must be in the form arg=value,arg=value,...)	splitlenr;   r'   r   ImportModuleImportModuleErrorstripr<   )rA   partsattrerG   arg	arg_partsr   r   r2   rC      s8   



rC   store_true_false)store
store_trueappendc                 C  sf   | sdS t | tr| tkrtjS | tv r| S t| S | d}|r+t	j
|fi |S tdt|  )aa  Parse the action out of the argument spec.

  Args:
    action: The argument action spec data.
    flag_name: str, The effective flag name.

  Raises:
    ValueError: If the spec is invalid.

  Returns:
    The action to use as argparse accepts it. It will either be a class that
    implements action, or it will be a str of a builtin argparse type.
  N
deprecatedzUnknown value for action: )
isinstancestrTRUE_FALSE_ACTIONr
   StoreTrueFalseActionSTATIC_ACTIONSr<   r>   r=   r	   DeprecationAction
ValueError)action	flag_namedeprecationr   r   r2   ParseAction   s   


rk   )rb   intlongfloatboolbytesc                 C  sf   | t kr	t|S | tkrtdS | tkrt|S | tkr$t	|S t
| d }r.|S t| S )zParses type from string.

  Args:
    arg_type: str, string representation of type
    data: dict, raw argument data

  Returns:
    The type to use as argparse accepts it.
  z,googlecloudsdk.calliope.arg_parsers:ArgList:N)
ARG_OBJECT	ArgObjectrB   ARG_LISTr<   r>   ARG_JSONArgJSON	FILE_TYPEFileContentsBUILTIN_TYPESr=   )arg_typer@   builtin_typer   r   r2   _ParseTypeFromStr   s   





r{   c                   s   t  fddtttfD } d }r|}n|rt}nd}|r5|tkr5 d}td| d| d|s;|s;dS t|trIt	|v rIt
 S t|trSt| S td	t| )
a	  Parse the action out of the argument spec.

  Args:
    data: dict, raw arugment data

  Raises:
    ValueError: If the spec is invalid.
    InvalidSchemaError: If spec and non arg_object type are provided.

  Returns:
    The type to use as argparse accepts it.
  c                 3  s    | ]}| v V  qd S rE   r   ).0r   r@   r   r2   	<genexpr>  s    zParseType.<locals>.<genexpr>typeNarg_namezEOnly flags with type arg_object may contain a spec declaration. Flag z
 has type z1. Update the type or remove the spec declaration.zUnknown value for type: )anySPECPARAMSGROUPr=   rq   r;   ra   dictARG_DICTArgDictrB   rb   r{   rg   )r@   contains_specspecified_typery   r   r   r}   r2   	ParseType  s,   



r   c                   @  s$   e Zd ZdZdd Zedd ZdS )Choicez3Holds information about a single enum choice value.c                 C  s`   |d | _ t| j tr| j  | _ d|v r|d | _nt| j | _|d| _|d| _	d S )N	arg_value
enum_value	help_texthidden)
r   ra   rb   lowerr   r   ChoiceToEnumNamer=   r   r   )rH   r@   r   r   r2   rI   4  s   
zChoice.__init__c                 C  s   |si S dd |D S )a-  Converts a list of choices into a map for easy value lookup.

    Args:
      choices: [Choice], The choices.

    Returns:
      {arg_value: enum_value}, A mapping of user input to the value that should
      be used. All arg_values have already been converted to lowercase for
      comparison.
    c                 S     i | ]}|j |jqS r   )r   r   )r|   cr   r   r2   
<dictcomp>N      z&Choice.ToChoiceMap.<locals>.<dictcomp>r   )r?   choicesr   r   r2   ToChoiceMap@  s   zChoice.ToChoiceMapN)r   r7   r8   r9   rI   rK   r   r   r   r   r2   r   1  s
    r   c                   @     e Zd ZdZejdd ZdS )TypeGeneratorz-Interface for generating a type from a field.c                 C     dS )zGenerates a type from a field.Nr   rH   fieldr   r   r2   GenerateTypeT      zTypeGenerator.GenerateTypeN)r   r7   r8   r9   abcabstractmethodr   r   r   r   r2   r   Q  s    r   )	metaclassc                   @  $   e Zd ZdZedd Zdd ZdS )rw   z0Holds information about a file content argument.c                 C     ~|  S )z&Creates a FileContents from yaml data.r   r?   r@   r   r   r2   rB   \  s   zFileContents.FromDatac                 C  sJ   |r	|j tjjkrtjddS |j tjjkrtjddS td|j d)NF)binaryTzConflicting types for field: zB. Only string and bytes fields are supported when using file_type.)	variantapitools_messagesVariantSTRINGr
   rw   BYTESr;   namer   r   r   r2   r   d  s   zFileContents.GenerateTypeNr   r7   r8   r9   rK   rB   r   r   r   r   r2   rw   Y  s
    
rw   T)frozenc                   @  s\   e Zd ZU dZe		dddZded< ded	< ded
< ded< ded< ded< ded< dS )
_FieldSpeczCHolds information about a field and type that is generated from it.NFc           
   	   C  s~   |p|j }t|}||j krtd| d|j  t|tr%||}	n|}	| |||p-||	|j|dur9||dS |j|dS )a  Creates a _FieldSpec from user input.

    If value is not provided in yaml schema by user, the value is defaulted
    to a value derived from the apitools field.

    Args:
      field: apitools field instance
      api_field: The name of the field under the repeated message that the value
        should be put.
      field_type: The type of the field if specified by user.
      arg_name: The name of the key in the dict.
      required: True if the key is required.
      hidden: True if the help text should be hidden.

    Returns:
      _FieldSpec instance

    Raises:
      ValueError: if the field contradicts the values provided by the user
    zExpected to receive field z	 but got N)r   	api_fieldr   
field_typerepeatedrequiredr   )	r   r   GetChildFieldNamerg   ra   r   r   r   r   )
r?   r   r   r   r   r   r   
field_namechild_field_namegenerated_field_typer   r   r2   FromUserDatat  s.   




z_FieldSpec.FromUserDatazapitools_messages.Fieldr   rb   r   r   Callable[[str], Any] | Noner   ro   r   r   zbool | Noner   )NNNNF)r   r7   r8   r9   rK   r   __annotations__r   r   r   r2   r   p  s   
 /r   c                   @  r   )EquitableTypeaj  Wrapper that deteremines if two message fields of same type are equal.

  This is needed because the old message may contain ouptut only fields the
  user is not able to specify. For example, a message field may contain output
  only field `uid` that the user is not able to specify. Message(foo=bar)
  should still "match" existing Message(foo=bar, uid=baz).
  c                 C  r   )DChecks if new value matches existing value based on what user input.Nr   rH   existing_value	new_valuer   r   r2   Matches  r   zEquitableType.MatchesN)r   r7   r8   r9   r   r   r   r   r   r   r2   r     s    r   c                      s6   e Zd ZdZ fddZdd Zejdd Z  Z	S )_FieldSpecTypea  Wrapper that holds the arg type and information about the type.

  Interface allows users to parse string into arg_type and then parse value
  into correct apitools field.

  Attributes:
    field: apitools field instance
    api_field: str, name of the field where value should be mapped in message.
    arg_name: str, name of key in dict.
    repeated: bool, whether the field is repeated.
    required: bool, whether the field value is required.
  c                   s>   t t| j|d |j| _|j| _|j| _|j| _|j| _d S N)ry   )superr   rI   r   r   r   r   r   rH   ry   
field_spec	__class__r   r2   rI     s   z_FieldSpecType.__init__c                 C  s,   |du r
| j r
g }n|}t|| j| dS )zSets field in a message after value is parsed into correct type.

    Args:
      message_instance: apitools message instance we are parsing value into
      value: value we are parsing into apitools message
    N)r   r   SetFieldInMessager   )rH   message_instancer   field_valuer   r   r2   ParseIntoMessage  s   z_FieldSpecType.ParseIntoMessagec                 C  r   )zBParses arg_value into apitools message using field specs provided.Nr   )rH   r   r   r   r2   __call__  r   z_FieldSpecType.__call__)
r   r7   r8   r9   rI   r   r   r   r   __classcell__r   r   r   r2   r     s    r   c                      s2   e Zd ZdZd	 fdd	Zdd Zdd Z  ZS )

_FieldTypez~Type that converts string into apitools field instance.

  Attributes:
    choices: list[Choice], list of valid user inputs
  Nc                       t t| jdi | || _d S Nr   )r   r   rI   r   )rH   r   rG   r   r   r2   rI        
z_FieldType.__init__c                 C  s"   |  |}tj| j|| j| jdS )z*Converts string into apitools field value.)r   r   )ry   r   ConvertValuer   r   r   rH   r   parsed_arg_valuer   r   r2   r     s
   

z_FieldType.__call__c                 C  sx   ||krdS |du s|du rdS t |tr|n|g}t |tr!|n|g}t|t|kr.dS |D ]	}||vr9 dS q0dS r   TNF)ra   listrS   )rH   r   r   new_val_listexisting_val_listvalr   r   r2   r     s   z_FieldType.MatchesrE   r   r7   r8   r9   rI   r   r   r   r   r   r   r2   r     s
    r   c                 C  s(   t | |j}t ||j}|||S )r   )r   GetFieldValueFromMessager   r   )r   r   r   existing_field	new_fieldr   r   r2   _SubFieldMatches	  s   r   c                      s@   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Z  Z	S )_MessageFieldTypezType that converts string input into apitools message.

  Attributes:
    field_specs: list[_FieldSpecType], list of message's fields
  c                   r   r   )r   r   rI   field_specs)rH   r   rG   r   r   r2   rI     r   z_MessageFieldType.__init__c                 C  s2   | j  }| jD ]}||j}||| q|S )z<Iterates through fields and adds fields to message instance.)r   r   r   r=   r   r   )rH   r   r   ry   r   r   r   r2   _ParseFieldsIntoMessage  s
   

z)_MessageFieldType._ParseFieldsIntoMessagec                   s0     |}t|tr fdd|D S  |S )z&Converts string into apitools message.c                      g | ]}  |qS r   )r   )r|   rrJ   r   r2   
<listcomp>)  r   z._MessageFieldType.__call__.<locals>.<listcomp>)ry   ra   r   r   r   r   rJ   r2   r   %  s   


z_MessageFieldType.__call__c                   s2   |D ]t  fdd| jD }|r dS qdS )r   c                 3  s    | ]	}t  |V  qd S rE   )r   )r|   r   new_valr   r   r2   r~   0  s    z1_MessageFieldType._ContainsVal.<locals>.<genexpr>TF)allr   )rH   r   
all_valuesmatchesr   r   r2   _ContainsVal-  s   z_MessageFieldType._ContainsValc                 C  s|   ||krdS |du s|du rdS t |tr|n|g}t |tr!|n|g}t|t|kr.dS |D ]}| ||s; dS q0dS r   )ra   r   rS   r   )rH   r   r   r   r   r   r   r   r2   r   7  s"   z_MessageFieldType.Matches)
r   r7   r8   r9   rI   r   r   r   r   r   r   r   r   r2   r     s    
r   c                      0   e Zd ZdZ fddZdd Zdd Z  ZS )_AdditionalPropsTypea  Type converts string into list of apitools message instances for map field.

  Type function returns a list of apitools messages with key, value fields ie
  [Message(key=key1, value=value1), Message(key=key2, value=value2), etc].
  The list of messages is how apitools specifies map fields.

  Attributes:
    key_spec: _FieldSpecType, specifes expected type of key field
    value_spec: _FieldSpecType, specifies expected type of value field
  c                   s&   t t| jdi | || _|| _d S r   )r   r   rI   key_spec
value_spec)rH   r   r   rG   r   r   r2   rI   X  s   
z_AdditionalPropsType.__init__c                 C  sX   |  |}g }t| D ]\}}| j }| j|| | j|| || q|S rE   )	ry   sorteditemsr   r   r   r   r   r_   )rH   r   r   r   kvr   r   r   r2   r   ]  s   

z_AdditionalPropsType.__call__c                 C  s|   ||krdS |d u s|d u rdS t |t |krdS dd |D }|D ]}|j|vr- dS | j||j |js; dS q#dS )NTFc                 S  r   r   r   )r|   r   r   r   r2   r   r  s    
z0_AdditionalPropsType.Matches.<locals>.<dictcomp>)rS   r   r   r   r   )rH   r   r   sub_field_mapr   r   r   r2   r   j  s    
z_AdditionalPropsType.Matchesr   r   r   r   r2   r   L  s
    r   c                   @      e Zd ZdZdd Zdd ZdS )_MapFieldTypezCType converts string into apitools additional props field instance.c                 C  s&   |  |}| j }| j || |S )zBParses arg_value into additional props field of apitools messages.)ry   r   r   r   )rH   r   additional_props_fieldparent_messager   r   r2   r     s   

z_MapFieldType.__call__c                 C  s.   ||krdS |du s|du rdS t ||| jS r   )r   ry   r   r   r   r2   r     s
   z_MapFieldType.MatchesN)r   r7   r8   r9   r   r   r   r   r   r2   r   }  s    r   c                 C  s$   t j| j}|std| j |S )zReturns the input type for the apitools field.

  Args:
    field: apitools field instance

  Returns:
    Type function for apitools field input.

  Raises:
    InvalidSchemaError: if the field type is not listed in arg_utils.TYPES
  zUnknown type for field: )r   TYPESr=   r   r;   r   )r   ry   r   r   r2   _GetFieldValueType  s   r   c                   @  s   e Zd ZdZedd Zedd ZedddZedd
dZ				dddZ	dd Z
dd Zd ddZd!ddZd!ddZd ddZd"ddZdS )#rr   z>A wrapper to bind an ArgObject argument to a message or field.c                 C  s"   | d }r|tkrt|S dS )!Creates ArgObject from yaml data.r   N)r=   rq   r   )r?   r@   	data_typer   r   r2   _FieldTypeFromData  s   zArgObject._FieldTypeFromDatac                 C  sH   g }|D ]}t j||p|d}|js|jr||j q|| q|S )z,Creates ArgObject types from yaml spec data.)parent_field)rr   rB   r   r   extendr_   )r?   params_datar   r   r   
field_datar   r   r   r2   _SpecFromData  s   zArgObject._SpecFromDataNc                 C  s4   |r|s|S | d}| |r|t|d S |S )r   .N)
startswithrS   )r?   r   r   prefixr   r   r2   _RelativeApiField  s   

zArgObject._RelativeApiFieldFc              	   C  s   | t }r
|}n|}| d}| tp| t }dur'| |||}nd}| d}	| dsG|sG| dp;|	}
td|
 d|
 d| | |||	| d	| d
| |||dS )r   r   N	json_namemutexr   zapi_field is required for z: Add api_field to z to generate a valid ArgObject.r   r   r   r  r   r   r   r   disable_key_description)r=   r   r   r   r   r;   r  r   )r?   r@   r  r   r   
group_datar   r   r   r  r   r   r   r2   rB     s0   


zArgObject.FromDatac                 C  s.   || _ || _|| _|| _|| _|| _|| _d S rE   r  )rH   r   r  r   r   r   r   r  r   r   r2   rI     s   
zArgObject.__init__c                 C  s   |j rt S dS )zReturns the correct argument action.

    Args:
      field: apitools field instance

    Returns:
      str, argument action string.
    r]   )r   r
   FlattenActionr   r   r   r2   Action  s   	zArgObject.Actionc                   s.   t | jd}| jp
g }t fdd|D |S )z4Returns first spec field that matches the api_field.)r  c                 3  s    | ]
}|j  kr|V  qd S rE   r   r|   fr  r   r2   r~     s    z2ArgObject._GetFieldTypeFromSpec.<locals>.<genexpr>)rr   r  r   next)rH   r   default_typer   r   r  r2   _GetFieldTypeFromSpec
  s
   
zArgObject._GetFieldTypeFromSpecc                 C  s&   t ||}| |}|j||ddS )ac  Retrieves the the type of the field from messsage.

    Args:
      message: Apitools message class
      api_field: str, field path of message
      is_label_field: bool, whether field is part of labels map field

    Returns:
      _FieldSpecType, Type function that returns apitools message
        instance or list of instances from string value.
    F)is_label_fieldis_root)r   GetFieldFromMessager  r   )rH   messager   r  r  arg_objr   r   r2   _GenerateSubFieldType  s
   
zArgObject._GenerateSubFieldTypeTc              	   C  s   |j  }rtd| d| j dzt|jjtj}W n tjy/   tdj	|jtjdw |j
dk}tj|| jd}| j|jt|d}| j|jt|d}tj||| j|j|| jd	d
}	t|	|||d}
t|
|dS )a6  Returns function that parses apitools map fields from string.

    Map fields are proto fields with type `map<...>` that generate
    apitools message with an additionalProperties field

    Args:
      field_spec: _FieldSpec, information about the field
      is_root: whether the type function is for the root level of the message

    Returns:
      type function that takes string like 'foo=bar' or '{"foo": "bar"}' and
        creates an apitools message additionalProperties field
    Raises:
      InvalidSchemaError: if type is specified for a map field
    Field type z  is not supported for map field (. Remove the type declaration from spec.zV{name} message does not contain field "{props}". Remove "{props}" from api field name.)r   propslabelsr   )r  T)key_type
value_typer   r   
root_levelr  allow_key_onlyry   r   r   r   ry   r   )r   r;   r   r   r  r   r   ADDITIONAL_PROPSUnknownFieldErrorr'   r   r   r   r  r  KEYVALUEr
   rr   r   r   r  r   r   )rH   r   r  r   r   r  props_field_specr  r  r  additional_prop_spec_typer   r   r2   _GenerateMapType"  s`   


	zArgObject._GenerateMapTypec              
     s    j  }rtd| dj djdurdd jD }nddhfd	d jj D } fd
d|D }dd |D }tjdd |D j	| j
 j|jdd}t| |dS )a  Returns function that parses apitools message fields from string.

    Args:
      field_spec: _FieldSpec, information about the field
      is_root: whether the _MessageFieldType is for the root level of
        the message

    Returns:
      _MessageFieldType that takes string like 'foo=bar' or '{"foo": "bar"}' and
      creates an apitools message like Message(foo=bar) or [Message(foo=bar)]

    Raises:
      InvalidSchemaError: if type is specified for a message field
    r  z$ is not supported for message field r  Nc                 S  s   g | ]}|j qS r   r  r  r   r   r2   r   v  s    z2ArgObject._GenerateMessageType.<locals>.<listcomp>
createTime
updateTimec                   s   g | ]
}|j  vr|j qS r   )r   r  )output_only_fieldsr   r2   r   y  s
    
c                   s   g | ]
}  jj|qS r   )r  r   r   )r|   r   )r   rH   r   r2   r   }  s    c                 S     g | ]}|j r|jqS r   r   r   r  r   r   r2   r         c                 S     i | ]}|j |qS r   r  r  r   r   r2   r         z2ArgObject._GenerateMessageType.<locals>.<dictcomp>T)r   r   required_keysr   r   r  r  r   ry   r   r   )r   r;   r   r   r   r   
all_fieldsr
   rr   r   r   r   r  r   )rH   r   r  r   field_namesr   r   r  r   )r   r,  rH   r2   _GenerateMessageType`  s>   




zArgObject._GenerateMessageTypec              	   C  s   |r|j tkrtj}tj}n|r|j tkrtj}tj}n
|jp#t	|j
}d}tj|| jp-||j|jdt|tj | jd}t||ddS )a  Returns _FieldType that parses apitools field from string.

    Args:
      field_spec: _FieldSpec, information about the field
      is_label_field: bool, whether or not the field is for a labels map field.
        If true, supplies default validation and help text.

    Returns:
      _FieldType that takes string like '1' or ['1'] and parses it
      into 1 or [1] depending on the apitools field type
    NF)r  r   r   r   r  enable_file_uploadr  ry   r   r   )r   r%  r   KEY_FORMAT_VALIDATORKEY_FORMAT_HELPr&  VALUE_FORMAT_VALIDATORVALUE_FORMAT_HELPr   r   r   r
   rr   r   r   r   ra   rw   r  r   )rH   r   r  r  default_help_textr  r   r   r2   _GenerateFieldType  s,   
zArgObject._GenerateFieldTypec                 C  sb   t j|| j| j| j| jd}t|}|tjj	kr| 
||S |tjjkr+| ||S | ||S )a  Generates a _FieldSpecType to parse the argument.

    Args:
      field: apitools field instance we are generating ArgObject for
      is_root: bool, whether this is the first level of the ArgObject
        we are generating for.
      is_label_field: bool, whether the field is for labels map field

    Returns:
      _FieldSpecType, Type function that returns apitools message
      instance or list of instances from string value.
    )r   r   r   r   )r   r   r  r   r   r   r   GetFieldType	FieldTypeMAPr)  MESSAGEr6  r>  )rH   r   r  r  r   field_variationr   r   r2   r     s   

zArgObject.GenerateTyperE   )FN)NNNNNNF)F)T)TF)r   r7   r8   r9   rK   r   r   r  rB   rI   r  r  r  r)  r6  r>  r   r   r   r   r2   rr     s*    

#



>
2%rr   c                 C  sF   t | |j}|jpt|}tj||j|j|jd}t	|||
 dS )zRetrieves the the type of the field from message.

  Args:
    message: Apitools message class
    user_field_spec: ArgDictFieldSpec, specifies the api field

  Returns:
    _FieldType, type function that returns apitools field class
  )r   r   r   r8  )r   r  r   r   r   r   r   r   r   r   	ChoiceMap)r  user_field_specr   ry   r   r   r   r2   _GetArgDictFieldType  s   
rF  c                   @  s4   e Zd ZdZedd Zdd Zdd Zdd	 Zd
S )r   a  A wrapper to bind an ArgDict argument to a message.

  The non-flat mode has one dict per message. When the field is repeated, you
  can repeat the message by repeating the flag. For example, given a message
  with fields foo and bar, it looks like:

  --arg foo=1,bar=2 --arg foo=3,bar=4

  The Action method below is used later during argument generation to tell
  argparse to allow repeats of the dictionary and to append them.
  c                 C  sr   |d }| d}|d t }dd |d D }| dr3t|dkr'td	t|||d
 |d dS | |||S )Nr   r   r   c                 S  s   g | ]}t |qS r   )ArgDictFieldSpecrB   r|   r0   r   r   r2   r     r   z$ArgDict.FromData.<locals>.<listcomp>r   flattenrM   z;Flattened ArgDicts must have exactly two items in the spec.r   rO   r   r   r   r   )r=   r   rS   r;   FlattenedArgDict)r?   r@   r   r   ry   fieldsr   r   r2   rB     s   

zArgDict.FromDatac                 C  s   || _ || _|| _d S rE   )r   r   rL  )rH   r   r   rL  r   r   r2   rI     s   
zArgDict.__init__c                 C  r   )Nr_   r   rJ   r   r   r2   r    s   zArgDict.Actionc                   s\   t j | j| jd} fdd| jD }dd |D }tjdd |D |d}t|||dS )	a  Generates an argparse type function to use to parse the argument.

    The return of the type function will be an instance of the given message
    with the fields filled in.

    Args:
      field: apitools field instance we are generating ArgObject for

    Raises:
      InvalidSchemaError: If a type for a field could not be determined.

    Returns:
      _MessageFieldType, The type function that parses the ArgDict and returns
      a message instance.
    r   r   c                   s   g | ]}t  j|qS r   )rF  r   r  r   r   r2   r      r/  z(ArgDict.GenerateType.<locals>.<listcomp>c                 S  r-  r   r.  r  r   r   r2   r   !  r/  c                 S  r0  r   r  r  r   r   r2   r   $  r1  z(ArgDict.GenerateType.<locals>.<dictcomp>)r   r2  r3  )r   r   r   r   rL  r
   r   r   )rH   r   r   r   r   r   r   rN  r2   r     s   
zArgDict.GenerateTypeN)	r   r7   r8   r9   rK   rB   rI   r  r   r   r   r   r2   r     s    
r   c                   @  r   )rK  aB  A wrapper to bind an ArgDict argument to a message with a key/value pair.

  The flat mode has one dict corresponding to a repeated field. For example,
  given a message with fields key and value, it looks like:

  --arg a=b,c=d

  Which would generate 2 instances of the message:
  [{key=a, value=b}, {key=c, value=d}]
  c                 C  s   || _ || _|| _|| _d S rE   rJ  )rH   r   r   r   r   r   r   r2   rI   8  s   
zFlattenedArgDict.__init__c                 C  sN   t j|| j| jd}t|j| j}t|j| j}tj	||d}t
||||dS )a  Generates an argparse type function to use to parse the argument.

    The return of the type function will be a list of instances of the given
    message with the fields filled in.

    Args:
      field: apitools field instance we are generating ArgObject for

    Raises:
      InvalidSchemaError: If a type for a field could not be determined.

    Returns:
      _AdditionalPropsType, The type function that parses the ArgDict
        and returns a list of message instances.
    rM  )r  r  r!  )r   r   r   r   rF  r   r   r   r
   r   r   )rH   r   r   r  r  r   r   r   r2   r   ?  s   
zFlattenedArgDict.GenerateTypeN)r   r7   r8   r9   rI   r   r   r   r   r2   rK  ,  s    rK  c                   @  sN   e Zd ZU dZedd Zded< ded< ded< d	ed
< ded< dd ZdS )rG  a  Attributes about the fields that make up an ArgDict spec.

  Attributes:
    api_field: The name of the field under the repeated message that the value
      should be put.
    arg_name: The name of the key in the dict.
    field_type: The argparse type of the value of this field.
    required: True if the key is required.
    choices: A static map of choice to value the user types.
  c                 C  sH   | d}|rdd |D nd }| |d | dt|| dd|dS )	Nr   c                 S  s   g | ]}t |qS r   )r   rH  r   r   r2   r   l  r1  z-ArgDictFieldSpec.FromData.<locals>.<listcomp>r   r   r   T)r   r   r   r   r   )r=   r   )r?   r@   data_choicesr   r   r   r2   rB   i  s   

zArgDictFieldSpec.FromDataz
str | Noner   r   r   r   ro   r   zlist[Choice] | Noner   c                 C  s   t | jS rE   )r   r   r   rJ   r   r   r2   rD  {  s   zArgDictFieldSpec.ChoiceMapN)r   r7   r8   r9   rK   rB   r   rD  r   r   r   r2   rG  \  s   
 
rG  c                      r   )_ArgJSONTypez>Parse json into apitools type but preserve arg_json help text.c                   s4   t t| j|d |j| _|j| _t|j| _d S r   )r   rP  rI   r   r   r   r?  r   r   r   r   r2   rI     s   z_ArgJSONType.__init__c                   sT   t |tr jr fdd|D S  jtjjkr"t |ts"t	dt
 jj|S )Nc                   r   r   )_EncodeInput)r|   r   rJ   r   r2   r     r   z-_ArgJSONType._EncodeInput.<locals>.<listcomp>z(Expecting map format i.e. {"foo": "bar"})ra   r   r   r   r   r@  JSONr   r
   ArgumentTypeErrorEncodeToMessager   r   )rH   r   r   rJ   r2   rQ    s   z_ArgJSONType._EncodeInputc              
   C  sH   |  |}z| |W S  tjy# } ztd| d| d }~ww )NzBad value [z]: )ry   rQ  r
   rS  )rH   r   r   rY   r   r   r2   r     s   
z_ArgJSONType.__call__)r   r7   r8   r9   rI   rQ  r   r   r   r   r   r2   rP    s
    rP  c                   @  r   )ru   z3A wrapper to bind an ArgJSON argument to a message.c                 C  r   )zCreates ArgJSON from yaml data.r   r   r   r   r2   rB     s   zArgJSON.FromDatac                 C  sD   t |}|t jjkr|t jjkrtdt|}tt	
 |dS )NzbInvalid type: arg_json cannot be used for non-struct field types.Recommend changing to arg_object.r"  )r   r?  r@  rR  
JSON_VALUEr;   r   r   rP  r
   ru   )rH   r   r   r   r   r   r2   r     s   

zArgJSON.GenerateTypeNr   r   r   r   r2   ru     s
    
ru   )NN)Wr9   
__future__r   r   r   r   r   collections.abcr   dataclassestypingr   apitools.base.protorpcliter   r   googlecloudsdk.callioper	   r
   r   
usage_text$googlecloudsdk.command_lib.util.apisr   $googlecloudsdk.command_lib.util.argsr   googlecloudsdk.corer   googlecloudsdk.core.utilr   r"   r#   r%   r&   r%  r&  rq   r   rs   rt   r   r   r   rv   r3   	Exceptionr5   r;   objectr<   rC   rc   	frozensetre   rk   rb   rl   rn   ro   Encoderx   r{   r   r   ABCMetar   FileTyperw   	dataclassr   r   DefaultArgTypeWrapperr   r   r   r   r   r   r   ArgObjectTyperr   rF  RepeatedMessageBindableTyper   rK  rG  rP  ArgJSONTyperu   r   r   r   r2   <module>   s   

#7/!
& 
<)%	:1  0C
0"