o
    S                     @   sn  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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zddlmZ W n eyc   dZY nw ersdeejddv rseZneZdZd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eej G dd deZ!G dd dej"Z#d"d d!Z$dS )#ae	  The Cloud SDK resource cache.

A resource is an object maintained by a service. Each resource has a
corresponding URI. A URI is composed of one or more parameters. A
service-specific resource parser extracts the parameter tuple from a URI. A
corresponding resource formatter reconstructs the URI from the parameter tuple.

Each service has an API List request that returns the list of resource URIs
visible to the caller. Some APIs are aggregated and return the list of all URIs
for all parameter values. Other APIs are not aggregated and require one or more
of the parsed parameter tuple values to be specified in the list request. This
means that getting the list of all URIs for a non-aggregated resource requires
multiple List requests, ranging over the combination of all values for all
aggregate parameters.

A collection is list of resource URIs in a service visible to the caller. The
collection name uniqely identifies the collection and the service.

A resource cache is a persistent cache that stores parsed resource parameter
tuples for multiple collections. The data for a collection is in one or more
tables.

    +---------------------------+
    | resource cache            |
    | +-----------------------+ |
    | | collection            | |
    | | +-------------------+ | |
    | | | table             | | |
    | | | (key,...,col,...) | | |
    | | |       ...         | | |
    | | +-------------------+ | |
    | |         ...           | |
    | +-----------------------+ |
    |           ...             |
    +---------------------------+

A resource cache is implemented as a ResourceCache object that contains
Collection objects. A Collection is a virtual table that contains one or more
persistent cache tables. Each Collection is also an Updater that handles
resource parsing and updates. Updates are typically done by service List or
Query requests that populate the tables.

The Updater objects make this module resource agnostic. For example, there
could be updater objects that are not associated with a URI. The ResourceCache
doesn't care.

If the List request API for a collection aggregates then its parsed parameter
tuples are contained in one table. Otherwise the collection is stored in
multiple tables. The total number of tables is determined by the number of
aggregate parameters for the List API, and the number of values each aggregate
parameter can take on.
    )absolute_import)division)unicode_literalsN)config)log)module_util)
properties)
exceptions)
file_cache)encoding)files)sqlite_cachesqlCLOUDSDK_CACHE_IMPLEMENTATIONsqlitei  zgooglecloudsdk.resource-1.0c                   @   s4   e Zd ZdZdddZdddZdd	 Zd
d ZdS )ParameterInfoa  An object for accessing parameter values in the program state.

  "program state" is defined by this class.  It could include parsed command
  line arguments and properties.  The class also can also map between resource
  and program parameter names.

  Attributes:
    _additional_params: The list of parameter names not in the parsed resource.
    _updaters: A parameter_name => (Updater, aggregator) dict.
  Nc                 C   s   |pg | _ |pi | _d S N)_additional_params	_updaters)selfadditional_paramsupdaters r   E/tmp/google-cloud-sdk/lib/googlecloudsdk/core/cache/resource_cache.py__init__s   s   
zParameterInfo.__init__Tc                 C      ~~dS )zReturns the program state string value for parameter_name.

    Args:
      parameter_name: The Parameter name.
      check_properties: Check the property value if True.

    Returns:
      The parameter value from the program state.
    Nr   )r   parameter_namecheck_propertiesr   r   r   GetValuew   s   
zParameterInfo.GetValuec                 C   s   | j S )a  Return the list of parameter names not in the parsed resource.

    These names are associated with the resource but not a specific parameter
    in the resource.  For example a global resource might not have a global
    Boolean parameter in the parsed resource, but its command line specification
    might require a --global flag to completly qualify the resource.

    Returns:
      The list of parameter names not in the parsed resource.
    )r   r   r   r   r   GetAdditionalParams   s   z!ParameterInfo.GetAdditionalParamsc                 C   s   | j |dS )a1  Returns the updater and aggregator property for parameter_name.

    Args:
      parameter_name: The Parameter name.

    Returns:
      An (updater, aggregator) tuple where updater is the Updater class and
      aggregator is True if this updater must be used to aggregate all resource
      values.
    NN)r   get)r   r   r   r   r   
GetUpdater   s   zParameterInfo.GetUpdaterr!   )T)__name__
__module____qualname____doc__r   r   r    r#   r   r   r   r   r   g   s    

r   c                   @   s   e Zd ZdZdddZdS )	ParameterzA parsed resource tuple parameter descriptor.

  A parameter tuple has one or more columns. Each has a Parameter descriptor.

  Attributes:
    column: The parameter tuple column index.
    name: The parameter name.
  r   Nc                 C   s   || _ || _d S r   )columnname)r   r)   r*   r   r   r   r      s   
zParameter.__init__)r   N)r$   r%   r&   r'   r   r   r   r   r   r(      s    	r(   c                       s    e Zd ZdZ fddZ  ZS )_RuntimeParametera  A runtime Parameter.

  Attributes:
    aggregator: True if parameter is an aggregator (not aggregated by updater).
    generate: True if values must be generated for this parameter.
    updater_class: The updater class.
    value: A default value from the program state.
  c                    s4   t t| j|j|jd d| _|| _|| _|| _d S )N)r*   F)	superr+   r   r)   r*   generateupdater_classvalue
aggregator)r   	parameterr.   r/   r0   	__class__r   r   r      s   

z_RuntimeParameter.__init__)r$   r%   r&   r'   r   __classcell__r   r   r2   r   r+      s    	r+   c                   @   s   e Zd ZdZdS )BaseUpdaterz(A base object for thin updater wrappers.N)r$   r%   r&   r'   r   r   r   r   r5      s    r5   c                       s   e Zd ZdZdddddef fdd	ZdddZdd	 Zd
d ZdddZ	dddZ
dd Zdd Zdd ZdddZejdddZ  ZS )Updatera  A resource cache table updater.

  An updater returns a list of parsed parameter tuples that replaces the rows in
  one cache table. It can also adjust the table timeout.

  The parameters may have their own updaters. These objects are organized as a
  tree with one resource at the root.

  Attributes:
    cache: The persistent cache object.
    collection: The resource collection name.
    columns: The number of columns in the parsed resource parameter tuple.
    parameters: A list of Parameter objects.
    timeout: The resource table timeout in seconds, 0 for no timeout (0 is easy
      to represent in a persistent cache tuple which holds strings and numbers).
  Nr   c                    sF   t t|   || _|| _|r|nd| _|| _|pg | _|pd| _dS )a  Updater constructor.

    Args:
      cache: The persistent cache object.
      collection: The resource collection name that (1) uniquely names the
        table(s) for the parsed resource parameters (2) is the lookup name of
        the resource URI parser. Resource collection names are unique by
        definition. Non-resource collection names must not clash with resource
        collections names. Prepending a '.' to non-resource collections names
        will avoid the clash.
      columns: The number of columns in the parsed resource parameter tuple.
        Must be >= 1.
      column: If this is an updater for an aggregate parameter then the updater
        produces a table of aggregate_resource tuples. The parent collection
        copies aggregate_resource[column] to a column in its own resource
        parameter tuple.
      parameters: A list of Parameter objects.
      timeout: The resource table timeout in seconds, 0 for no timeout.
       r   N)	r,   r6   r   cache
collectioncolumnsr)   
parameterstimeout)r   r8   r9   r:   r)   r;   r<   r2   r   r   r      s   
zUpdater.__init__c                 C   s4   | j r| j g}nt| g}|r|| d|S )a  Returns the table name; the module path if no collection.

    Args:
      suffix_list: a list of values to attach to the end of the table name.
        Typically, these will be aggregator values, like project ID.
    Returns: a name to use for the table in the cache DB.
    .)r9   r   GetModulePathextendjoin)r   suffix_listr*   r   r   r   _GetTableName   s   


zUpdater._GetTableNamec                 C   sL   g }| j D ]}||j\}}|j|j|d}t||||}|| q|S )aR  Constructs and returns the _RuntimeParameter list.

    This method constructs a muable shadow of self.parameters with updater_class
    and table instantiations. Each runtime parameter can be:

    (1) A static value derived from parameter_info.
    (2) A parameter with it's own updater_class.  The updater is used to list
        all of the possible values for the parameter.
    (3) An unknown value (None).  The possible values are contained in the
        resource cache for self.

    The Select method combines the caller supplied row template and the runtime
    parameters to filter the list of parsed resources in the resource cache.

    Args:
      parameter_info: A ParamaterInfo object for accessing parameter values in
        the program state.

    Returns:
      The runtime parameters shadow of the immutable self.parameters.
    )r   )r;   r#   r*   r   r+   append)r   parameter_inforuntime_parametersr1   r.   r0   r/   runtime_parameterr   r   r   _GetRuntimeParameters
  s   
zUpdater._GetRuntimeParametersc                 C   s   t  S )z"Returns the parameter info object.)r   r   r   r   r   r   *  s   zUpdater.ParameterInfoc                 C   s   |sg }t d|jddd |D  z||W S  tjyB   | ||}|dur9|  |	| |
  |j|dd Y S w )a  Returns the list of rows matching row_template in table.

    Refreshes expired tables by calling the updater.

    Args:
      table: The persistent table object.
      row_template: A row template to match in Select().
      parameter_info: A ParamaterInfo object for accessing parameter values in
        the program state.
      aggregations: A list of aggregation Parameter objects.

    Returns:
      The list of rows matching row_template in table.
    z cache table=%s aggregations=[%s] c                 S   s   g | ]
}d  |j|jqS )z{}={})formatr*   r/   .0xr   r   r   
<listcomp>A      z'Updater.SelectTable.<locals>.<listcomp>NT)ignore_expiration)r   infor*   r@   Selectr	   CacheTableExpiredUpdate
DeleteRowsAddRowsValidate)r   tablerow_templaterD   aggregationsrowsr   r   r   SelectTable.  s    
zUpdater.SelectTablec                 C   s  t |}| jt|kr|dg| jt|  7 }tdddd |D  g g}g }| |}t|D ]\}}d|_|j	rn||j
 dv rn|j	||j
< td|j|j
|j	|j |jrm|| d	|_|D ]}	|	|j	 qdq3|jr|| d	|_td|j|j
|j	|j |j| jd
}
dg|
j }||j
 ||
j
< td|j|j
|j g }|
|d| |||D ]\}}|
||| q|}q3|sdd |D }d|v rg S | j|d}| jj|| j| j| jd}| ||||S g }| ||||D ]	\}}|| qtd|  |S )a%  Returns the list of rows matching row_template in the collection.

    All tables in the collection are in play. The row matching done by the
    cache layer conveniently prunes the number of tables accessed.

    Args:
      row_template: A row template tuple. The number of columns in the template
        must match the number of columns in the collection. A column with value
        None means match all values for the column. Each column may contain
        these wildcard characters:
          * - match any string of zero or more characters
          ? - match any character
        The matching is anchored on the left.
      parameter_info: A ParamaterInfo object for accessing parameter values in
        the program state.

    Returns:
      The list of rows that match the template row.
    Nzcache template=[%s]z, c                 S   s   g | ]}d  |qS )z'{}')rI   )rK   tr   r   r   rM   d      z"Updater.Select.<locals>.<listcomp>F)N*z2cache parameter=%s column=%s value=%s aggregate=%sT)r8   z)cache parameter=%s column=%s aggregate=%sc                 S   s   g | ]}|j qS r   )r/   rJ   r   r   r   rM     s    rA   r:   keysr<   zcache rows=%s)listr:   lenr   rP   r@   rG   	enumerater-   r/   r)   r*   r0   rC   r.   r8    YieldSelectTableFromPermutationsExtendValuesrB   Tabler<   r[   r?   )r   rX   rD   templatevaluesrY   r;   ir1   vupdatersub_template
new_valuespermselectedaggregation_values
table_namerW   rZ   _r   r   r   rQ   L  s|   


zUpdater.Selectc                 C   s,   |  |}|D ]}|j|kr|j  S qdS )z9Get this updater's column number for a certain parameter.N)rG   r*   r)   )r   rD   r   updater_parametersr1   r   r   r   _GetParameterColumn  s   


zUpdater._GetParameterColumnc                    sF   fdd|D }t dj|  fdd|D }|| dS )z?Add selected values to a template and extend the selected rows.c                    s   g | ]}| j  qS r   )r)   )rK   rowr   r   r   rM     r]   z(Updater.ExtendValues.<locals>.<listcomp>z$cache collection={} adding values={}c                    s   g | ]} |g qS r   r   rK   val)ro   r   r   rM     r]   N)r   rP   rI   r9   r?   )r   ri   ro   rp   valsrk   r   )ro   r   r   rf     s   zUpdater.ExtendValuesc                 c   s    |D ]Q}dd |D }| j j| j|d| j| j| jd}g }|D ]%}	|	jr>| ||	j}
|
du r2q!|d||
< ||
 |	_	|	j	rF|
|	 q!| ||||}||fV  qdS )a  Selects completions from tables using multiple permutations of values.

    For each vector in values, e.g. ['my-project', 'my-zone'], this method
    selects rows matching the template from a leaf table corresponding to the
    vector (e.g. 'my.collection.my-project.my-zone') and yields a 2-tuple
    containing that vector and the selected rows.

    Args:
      parameters: [Parameter], the list of parameters up through the
        current updater belonging to the parent. These will be used to iterate
        through each permutation contained in values.
      values: list(list()), a list of lists of valid values. Each item in values
        corresponds to a single permutation of values for which item[n] is a
        possible value for the nth generator in parent_parameters.
      template: list(str), the template to use to select new values.
      parameter_info: ParameterInfo, the object that is used to get runtime
        values.

    Yields:
      (perm, list(list)): a 2-tuple where the first value is the permutation
        currently being used to select values and the second value is the result
        of selecting to match the permutation.
    c                 S   s   g | ]}|qS r   r   rw   r   r   r   rM     s    z<Updater.YieldSelectTableFromPermutations.<locals>.<listcomp>r_   r`   Nr   )r8   rg   rB   r:   r<   r-   ru   r*   popr/   rC   r[   )r   r;   ri   rh   rD   ro   	temp_permrW   rY   r1   r)   rp   r   r   r   re     s.   


z(Updater.YieldSelectTableFromPermutationsTc                    s@   |  |} fdd|D }| jj| j|d| j| j| j|dS )a$  Returns the table for row.

    Args:
      row: The fully populated resource row.
      parameter_info: A ParamaterInfo object for accessing parameter values in
        the program state.
      create: Create the table if it doesn't exist if True.

    Returns:
      The table for row.
    c                    s   g | ]
}|j r |j qS r   )r0   r)   )rK   prv   r   r   rM     rN   z*Updater.GetTableForRow.<locals>.<listcomp>r_   )r:   ra   r<   create)rG   r8   rg   rB   r:   r<   )r   rv   rD   r~   r;   ri   r   r}   r   GetTableForRow  s   

zUpdater.GetTableForRowc                 C   r   )z;Returns the list of all current parsed resource parameters.Nr   )r   rD   rY   r   r   r   rS     s   zUpdater.Updater   NTr!   )r$   r%   r&   r'   DEFAULT_TIMEOUTr   rB   rG   r   r[   rQ   ru   rf   re   r   abcabstractmethodrS   r4   r   r   r2   r   r6      s(    
" 

V
/r6   c                       s.   e Zd ZdZd fdd	Zedd Z  ZS )	ResourceCachezA resource cache object.NTc                    s&   |s|   }tt| j||td dS )a  ResourceCache constructor.

    Args:
      name: The persistent cache object name. If None then a default name
        conditioned on the account name is used.
          <GLOBAL_CONFIG_DIR>/cache/<ACCOUNT>/resource.cache
      create: Create the cache if it doesn't exist if True.
    r*   r~   versionN)GetDefaultNamer,   r   r   VERSION)r   r*   r~   r2   r   r   r     s
   	

zResourceCache.__init__c                  C   sT   t  jg} tjjjjdd}|r| | t	
tjj|   | d tjj|  S )z(Returns the default resource cache name.F)requiredzresource.cache)r   Paths	cache_dirr   VALUEScoreaccountGetrC   r   MakeDirospathr@   )r   r   r   r   r   r     s   

zResourceCache.GetDefaultNamer   )r$   r%   r&   r'   r   staticmethodr   r4   r   r   r2   r   r     s
    r   c              	   C   sT   | st  } ttfD ]}|sq
z|j| dtd  W  dS  tjy'   Y q
w dS )zGDeletes the current persistent resource cache however it's implemented.Fr   N)	r   r   r   r
   Cacher   Deleter	   CacheInvalid)r*   implementationr   r   r   r     s   r   r   )%r'   
__future__r   r   r   r   r   googlecloudsdk.corer   r   r   r   googlecloudsdk.core.cacher	   r
   googlecloudsdk.core.utilr   r   sixr   ImportErrorGetEncodedValueenvironPERSISTENT_CACHE_IMPLEMENTATIONr   r   objectr   r(   r+   r5   add_metaclassABCMetar6   r   r   r   r   r   r   r   <module>   sL   58
  8