o
    S                     @   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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dlZdZG dd dejZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG d d! d!eZ G d"d# d#eZ!d$d% Z"d&d' Z#d;d(d)Z$d*d+ Z%d,d- Z&d<d.d/Z'd;d0d1Z(		2d=d3d4Z)d5d6 Z*d7d8 Z+	2d=d9d:Z,dS )>z+Utilities for the gcloud meta apis surface.    )absolute_import)division)unicode_literals)messages)
exceptions)
list_pager)apis)apis_internal)resource)	arg_utils)log)apis_mapN.c                   @      e Zd ZdS )ErrorN__name__
__module____qualname__ r   r   J/tmp/google-cloud-sdk/lib/googlecloudsdk/command_lib/util/apis/registry.pyr   &       r   c                          e Zd Z fddZ  ZS )UnknownAPIErrorc                       t t| dj|d d S )Nz0API [{api}] does not exist or is not registered.api)superr   __init__formatselfapi_name	__class__r   r   r   ,   
   
zUnknownAPIError.__init__r   r   r   r   __classcell__r   r   r#   r   r   *       r   c                       r   )UnknownAPIVersionErrorc                    s   t t| dj||d d S )Nz3Version [{version}] does not exist for API [{api}].)versionr   )r   r)   r   r   )r!   r"   r*   r#   r   r   r   5   
   
zUnknownAPIVersionError.__init__r&   r   r   r#   r   r)   3   r(   r)   c                       r   )NoDefaultVersionErrorc                    r   )NzSAPI [{api}] does not have a default version. You must specify which version to use.r   )r   r,   r   r   r    r#   r   r   r   >   r%   zNoDefaultVersionError.__init__r&   r   r   r#   r   r,   <   r(   r,   c                       r   )UnknownCollectionErrorc                    s    t t| dj|||d d S )NzACollection [{collection}] does not exist for [{api}] [{version}].)
collectionr   r*   )r   r-   r   r   )r!   r"   api_versionr.   r#   r   r   r   G   s
   
zUnknownCollectionError.__init__r&   r   r   r#   r   r-   E   r(   r-   c                       r   )UnknownMethodErrorc                    s   t t| dj||d d S )Nz?Method [{method}] does not exist for collection [{collection}].)methodr.   )r   r0   r   r   )r!   r1   r.   r#   r   r   r   P   r+   zUnknownMethodError.__init__r&   r   r   r#   r   r0   N   r(   r0   c                   @   r   )APICallErrorNr   r   r   r   r   r2   W   r   r2   c                   @   s    e Zd ZdZdd Zdd ZdS )APIz1A data holder for returning API data for display.c                 C   s"   || _ || _|| _|| _|| _d S N)namer*   
is_default_clientbase_url)r!   r5   r*   r6   clientr8   r   r   r   r   ^   s
   
zAPI.__init__c                 C   s   | j jS r4   )r7   MESSAGES_MODULEr!   r   r   r   GetMessagesModulee   s   zAPI.GetMessagesModuleN)r   r   r   __doc__r   r<   r   r   r   r   r3   [   s    r3   c                   @   s   e Zd ZdZdd ZdS )APICollectionz4A data holder for collection information for an API.c                 C   sd   |j | _ |j| _|j| _|j| _|j| _|j| _|d| _|d| _	|j
| _
|j| _|j| _d S )N )r"   r/   r8   docs_urlr5   	full_nameGetPathdetailed_path	GetParamsdetailed_paramspathparamsenable_uri_parsing)r!   collection_infor   r   r   r   l   s   zAPICollection.__init__N)r   r   r   r=   r   r   r   r   r   r>   i   s    r>   c                   @   s   e Zd ZdZ	d(ddZedd Ze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 Zdd Zdd Zdd Z		d)d d!Z		d*d"d#Zd$d% Zd&d' ZdS )+	APIMethodz;A data holder for method information for an API collection.Fc                 C   s   || _ || _|| _|| _|j| _| jjt }| j|r&| jt	|d  | _t
| jj|j| _|j| _|jrGt
| jj|j| _t|j| _n| j| _| j| _|j| _|j| _|j| _|j| _|  | _|j| _d S r4   )_service_method_name_disable_paginationr.   	method_idr5   rA   NAME_SEPARATOR
startswithlen_RemoveVersionPrefixr/   relative_pathrF   ordered_paramsrG   	flat_pathrC   r
   GetParamsFromPathrE   http_methodrequest_fieldrequest_type_namerequest_typeresponse_type_nameresponse_type_RequestCollection_request_collectionquery_params)r!   servicer5   api_collectionmethod_configdisable_paginationdotted_pathr   r   r   r   }   s2   


zAPIMethod.__init__c                 C   s   |   r| jS | jS )a  Gets the collection that should be used to represent the resource.

    Most of the time this is the same as request_collection because all methods
    in a collection operate on the same resource and so the API method takes
    the same parameters that make up the resource.

    One exception is List methods where the API parameters are for the parent
    collection. Because people don't specify the resource directly for list
    commands this also returns the parent collection for parsing purposes.

    The other exception is Create methods. They reference the parent collection
    list Like, but the difference is that we *do* want to specify the actual
    resource on the command line, so the original resource collection is
    returned here instead of the one that matches the API methods. When
    generating the request, you must figure out how to generate the message
    correctly from the parsed resource (as you cannot simply pass the reference
    to the API).

    Returns:
      APICollection: The collection.
    )IsListr^   r.   r;   r   r   r   resource_argument_collection   s   z&APIMethod.resource_argument_collectionc                 C   s   | j S )zFGets the API collection that matches the parameters of the API method.)r^   r;   r   r   r   request_collection   s   zAPIMethod.request_collectionc                 C      | j | jS )z0Gets the apitools request class for this method.)rK   GetRequestTyperL   r;   r   r   r   ri         zAPIMethod.GetRequestTypec                 C   rh   )z1Gets the apitools response class for this method.)rK   GetResponseTyperL   r;   r   r   r   rk      rj   zAPIMethod.GetResponseTypec                 C   s.   |    }r|  rt|  |jS |  S )aG  Gets the effective apitools response class for this method.

    This will be different from GetResponseType for List methods if we are
    extracting the list of response items from the overall response. This will
    always match the type of response that Call() returns.

    Returns:
      The apitools Message object.
    )ListItemFieldHasTokenizedRequestr   GetFieldFromMessagerk   type)r!   
item_fieldr   r   r   GetEffectiveResponseType   s   
z"APIMethod.GetEffectiveResponseTypec                 C   s   | j jj}t||dS )ax  Gets a arbitrary apitools message class by name.

    This method can be used to get arbitrary apitools messages from the
    underlying service. Examples:

    policy_type = method.GetMessageByName('Policy')
    status_type = method.GetMessageByName('Status')

    Args:
      name: str, the name of the message to return.
    Returns:
      The apitools Message object.
    N)rK   r9   r:   getattr)r!   r5   msgsr   r   r   GetMessageByName   s   
zAPIMethod.GetMessageByNamec                 C   s
   | j dkS )z)Determines whether this is a List method.List)rL   r;   r   r   r   re      s   
zAPIMethod.IsListc                 C   s    | j  od|  v od|  v S )z9Determines whether this is a method that supports paging.	pageTokennextPageToken)rM   _RequestFieldNames_ResponseFieldNamesr;   r   r   r   rm      s
   

zAPIMethod.HasTokenizedRequestc                 C   s$   |   }d|v r
dS d|v rdS dS )zAGets the name of the page size field in the request if it exists.
maxResultspageSizeN)rx   )r!   request_fieldsr   r   r   BatchPageSizeField   s   zAPIMethod.BatchPageSizeFieldc                 C   s>   | j rdS |  }dd | D }t|dkr|d jS dS )a  Gets the name of the field that contains the items in paginated response.

    This will return None if the method is not a paginated or if a single
    repeated field of items could not be found in the response type.

    Returns:
      str, The name of the field or None.
    Nc                 S   s$   g | ]}|j tjjkr|jr|qS r   )variantr   VariantMESSAGErepeated.0fr   r   r   
<listcomp>  s    z+APIMethod.ListItemField.<locals>.<listcomp>   r   )rM   rk   
all_fieldsrQ   r5   )r!   responsefoundr   r   r   rl      s   	
zAPIMethod.ListItemFieldc                 C   sr   | j | jj kr
| jS t| jj| jj}|D ]}| j |j kr'|j| jv r'|  S q|D ]}| j |j kr6|  S q*dS )a#  Gets the collection that matches the API parameters of this method.

    Methods apply to elements of a collection. The resource argument is always
    of the type of that collection. List is an exception where you are listing
    items of that collection so the argument to be provided is that of the
    parent collection. This method returns the collection that should be used
    to parse the resource for this specific method.

    Returns:
      APICollection, The collection to use or None if no parent collection could
      be found.
    N)rE   r.   GetAPICollectionsr"   r/   rC   )r!   collectionscr   r   r   r]     s   zAPIMethod._RequestCollectionc                 C      dd |    D S )a  Gets the fields that are actually a part of the request message.

    For APIs that use atomic names, this will only be the single name parameter
    (and any other message fields) but not the detailed parameters.

    Returns:
      [str], The field names.
    c                 S      g | ]}|j qS r   r5   r   r   r   r   r   2      z0APIMethod._RequestFieldNames.<locals>.<listcomp>)ri   r   r;   r   r   r   rx   )  s   	zAPIMethod._RequestFieldNamesc                 C   r   )zrGets the fields that are actually a part of the response message.

    Returns:
      [str], The field names.
    c                 S   r   r   r   r   r   r   r   r   :  r   z1APIMethod._ResponseFieldNames.<locals>.<listcomp>)rk   r   r;   r   r   r   ry   4  s   zAPIMethod._ResponseFieldNamesNc           
   
   C   s   |du rt | jj| jj}t|| jj}| j|||||d}z||dW S  tj	y? }	 zt
jddd tt|	d}	~	ww )a  Executes this method with the given arguments.

    Args:
      request: The apitools request object to send.
      client: base_api.BaseApiClient, An API client to use for making requests.
      global_params: {str: str}, A dictionary of global parameters to send with
        the request.
      raw: bool, True to not do any processing of the response, False to maybe
        do processing for List results.
      limit: int, The max number of items to return if this is a List method.
      page_size: int, The max number of items to return in a page if this API
        supports paging.

    Returns:
      The response from the API.
    N)rawlimit	page_sizeglobal_paramsr?   T)exc_info)r   GetClientInstancer.   r"   r/   _GetServicer5   _GetRequestFuncapitools_excInvalidUserInputErrorr   debugr2   str)
r!   requestr9   r   r   r   r   r`   request_funcer   r   r   Call<  s   
zAPIMethod.Callc                    s   |sj rS    s  rtd S  s5 r/ S S d fdd	}|S )a  Gets a request function to call and process the results.

    If this is a method with paginated response, it may flatten the response
    depending on if the List Pager can be used.

    Args:
      service: The apitools service that will be making the request.
      request: The apitools request object to send.
      raw: bool, True to not do any processing of the response, False to maybe
        do processing for List results.
      limit: int, The max number of items to return if this is a List method.
      page_size: int, The max number of items to return in a page if this API
        supports paging.

    Returns:
      A function to make the request.
    z<Unable to flatten list response, raw results being returned.Nc                    s$   t jj | dd d
S )Nrv   rw   )r1   fieldr   r   current_token_attributenext_token_attributebatch_size_attribute
batch_size)r   YieldFromListrL   r}   r   rp   r   r   r   r!   r`   r   r   RequestFunc~  s   
z.APIMethod._GetRequestFunc.<locals>.RequestFuncr4   )rM   _NormalRequestrl   re   r   r   rm   _FlatNonPagedRequest)r!   r`   r   r   r   r   r   r   r   r   r   Z  s   
zAPIMethod._GetRequestFuncc                    s   d fdd	}|S )zGenerates a basic request function for the method.

    Args:
      service: The apitools service that will be making the request.
      request: The apitools request object to send.

    Returns:
      A function to make the request.
    Nc                    s   t j}| | dS Nr   )rr   rL   )r   r1   r   r!   r`   r   r   r     s   z-APIMethod._NormalRequest.<locals>.RequestFuncr4   r   )r!   r`   r   r   r   r   r   r     s   
zAPIMethod._NormalRequestc                    s   d fdd	}|S )a  Generates a request function for the method that extracts an item list.

    List responses usually have a single repeated field that represents the
    actual items being listed. This request function returns only those items
    not the entire response.

    Args:
      service: The apitools service that will be making the request.
      request: The apitools request object to send.
      item_field: str, The name of the field that the list of items can be found
       in.

    Returns:
      A function to make the request.
    Nc                    s    | d}t| S r   )r   rr   )r   r   rp   r   r!   r`   r   r   r     s   

z3APIMethod._FlatNonPagedRequest.<locals>.RequestFuncr4   r   )r!   r`   r   rp   r   r   r   r   r     s   zAPIMethod._FlatNonPagedRequest)F)NNFNN)FNN)r   r   r   r=   r   propertyrf   rg   ri   rk   rq   rt   re   rm   r}   rl   r]   rx   ry   r   r   r   r   r   r   r   r   rJ   z   s6    
!

	

.rJ   c                 C   s*   |sdS | | r|t| d d S |S )z@Trims the version number off the front of a URL path if present.Nr   )rP   rQ   )r/   rF   r   r   r   rR     s
   
rR   c                 C   sl   t | \} }tj| i }|st| |r!||vrt| ||S t|D ]\}}|j	r1|  S q&t
| )zCValidates the API exists and gets the default version if not given.)r	   _GetApiNameAndAliasr   MAPgetr   r)   six	iteritemsdefault_versionr,   )r"   r/   _api_versr*   api_defr   r   r   _ValidateAndGetDefaultVersion  s   
r   c                 C   s   t | |}t| |}|jrt|}nt| |}t|dr#|j}nz	t| |j}W n t	y;   d
| |}Y nw t| ||j||S )zGet a specific API definition.

  Args:
    api_name: str, The name of the API.
    api_version: str, The version string of the API.

  Returns:
    API, The API definition.
  BASE_URLzhttps://{}.googleapis.com/{})r   r	   	GetApiDefapitools_GetClientClassFromDef_GetGapicClientClasshasattrr   _GetResourceModuleImportErrorr   r3   r   )r"   r/   r   
api_clientr8   r   r   r   GetAPI  s&   


r   c                  C   sB   g } t tjD ]\}}t |D ]\}}| t|| qq| S )zNGets all registered APIs.

  Returns:
    [API], A list of API definitions.
  )r   r   r   r   appendr   )all_apisr"   versionsr/   r   r   r   r   
GetAllAPIs  s   r   c                 C   s   t | tdS )Nr   )tuplesplitrO   )r.   r   r   r   _SplitFullCollectionName  s   r   c                 C   s\   | r
| t | |i}ndd t D }g }t|D ]\}}|dd t||D  q|S )a(  Gets the registered collections for the given API version.

  Args:
    api_name: str, The name of the API or None for all apis.
    api_version: str, The version string of the API or None to use the default
      version.

  Returns:
    [APICollection], A list of the registered collections.
  c                 S   s   i | ]
}|j r|j|jqS r   )r6   r5   r*   )r   xr   r   r   
<dictcomp>	  s    z%GetAPICollections.<locals>.<dictcomp>c                 S   s   g | ]}t |qS r   )r>   )r   r   r   r   r   r     s    z%GetAPICollections.<locals>.<listcomp>)r   r   r   r   extendr	   _GetApiCollections)r"   r/   r   r   nvr   r   r   r     s   r   c                 C   sH   t | \}}t||}t||}|D ]}|j|kr|  S qt|||)a  Gets the given collection for the given API version.

  Args:
    full_collection_name: str, The collection to get including the api name.
    api_version: str, The version string of the API or None to use the default
      for this API.

  Returns:
    APICollection, The requested API collection.

  Raises:
    UnknownCollectionError: If the collection does not exist for the given API
    and version.
  )r   r   r   r5   r-   )full_collection_namer/   r"   r.   r   r   r   r   r   GetAPICollection  s   


r   Fc                 C   s4   t | ||d}|D ]}|j|kr|  S q	t|| )a  Gets the specification for the given API method.

  Args:
    full_collection_name: str, The collection including the api name.
    method: str, The name of the method.
    api_version: str, The version string of the API or None to use the default
      for this API.
    disable_pagination: bool, Boolean for whether pagination should be disabled

  Returns:
    APIMethod, The method specification.

  Raises:
    UnknownMethodError: If the method does not exist on the collection.
  )r/   rc   )
GetMethodsr5   r0   )r   r1   r/   rc   methodsmr   r   r   	GetMethod+  s   

r   c                 C   s   t | |tdd S )Nr   )rr   replacerO   )r9   collection_namer   r   r   r   E  s   r   c                 C   s6   t | |}|jrtj| |dd}|S t| |}|S )z+Gets the repesctive api client for the api.T)no_http)r	   r   r   r   r   GetGapicClientInstance)r"   r/   r   r9   r   r   r   _GetApiClientI  s   r   c                    s^   t | |d t j j}t| jsg S  }fdd|D } fdd|D S )at  Gets all the methods available on the given collection.

  Args:
    full_collection_name: str, The collection including the api name.
    api_version: str, The version string of the API or None to use the default
      for this API.
    disable_pagination: bool, Boolean for whether pagination should be disabled

  Returns:
    [APIMethod], The method specifications.
  )r/   c                    s   g | ]	}|  |fqS r   )GetMethodConfig)r   r5   )r`   r   r   r   j  s    zGetMethods.<locals>.<listcomp>c                    s    g | ]\}}t | |qS r   )rJ   )r   r5   configra   rc   r`   r   r   r   l  s    )r   r   r"   r/   r   r5   GetMethodsList)r   r/   rc   r9   method_namesmethod_configsr   r   r   r   S  s   
r   r4   )NN)NF)-r=   
__future__r   r   r   apitools.base.protorpcliter   apitools.base.pyr   r   r   googlecloudsdk.api_lib.utilr   r	   r
   $googlecloudsdk.command_lib.util.apisr   googlecloudsdk.corer   %googlecloudsdk.generated_clients.apisr   r   rO   r   r   r)   r,   r-   r0   r2   objectr3   r>   rJ   rR   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sT   					  6	
 


