U
    Zf                      @   s   d Z ddlmZ ddlmZmZ dddZdd	 Zd
d Zdd Z	dddZ
G dd deZG dd deZG dd deZdddZdd ZdS )a  
This module contains a collection of utility function for dealing with property
groupings.

Terminology:

For the purpose of grouping and ungrouping, tuples/lists and dictionaries are considered
"composite values" and all other values are considered "scalar values".

A "grouping value" is either composite or scalar.

A "schema" is a grouping value that can be used to encode an expected grouping
structure

    )InvalidCallbackReturnValue   )AttributeDictstringify_idNc                    s^   dkr n
t   tttfr:dd t D S ttrX fddD S  gS )a  
    Convert a grouping value to a list of scalar values

    :param grouping: grouping value to flatten
    :param schema: If provided, a grouping value representing the expected structure of
        the input grouping value. If not provided, the grouping value is its own schema.
        A schema is required in order to be able treat tuples and dicts in the input
        grouping as scalar values.

    :return: list of the scalar values in the input grouping
    Nc                 S   s$   g | ]\}}t ||D ]}|qqS  flatten_grouping).0group_elZ	schema_elgr   r   2/tmp/pip-unpacked-wheel-47crqvv_/dash/_grouping.py
<listcomp>&   s    z$flatten_grouping.<locals>.<listcomp>c                    s(   g | ] }t  | | D ]}|qqS r   r   r	   kr   groupingschemar   r   r   -   s       )validate_grouping
isinstancetuplelistzipdictr   r   r   r   r      s    

r   c                 C   sD   t | ttfr tdd | D S t | tr@tdd |  D S dS )aU  
    Get the length of a grouping. The length equal to the number of scalar values
    contained in the grouping, which is equivalent to the length of the list that would
    result from calling flatten_grouping on the grouping value.

    :param grouping: The grouping value to calculate the length of
    :return: non-negative integer
    c                 S   s   g | ]}t |qS r   grouping_lenr	   r
   r   r   r   r   <   s     z grouping_len.<locals>.<listcomp>c                 S   s   g | ]}t |qS r   r   r   r   r   r   r   ?   s     r   )r   r   r   sumr   values)r   r   r   r   r   2   s
    	
r   c              	      sv    fdd t |ts(tdt| tt| }t||krhtd| dt| dt|  d|  | t|S )a  
    Make a grouping like the provided grouping schema, with scalar values drawn from a
    flat list by index.

    Note: Scalar values in schema are not used

    :param schema: Grouping value encoding the structure of the grouping to return
    :param flat_values: List of values with length matching the grouping_len of schema.
        Elements of flat_values will become the scalar values in the resulting grouping
    c                    sZ   t | ttfr*t fddt| D S t | trP fddt|  D S  dS )Nc                 3   s   | ]\}} |V  qd S Nr   )r	   iel_perform_make_grouping_likenext_valuesr   r   	<genexpr>R   s   zNmake_grouping_by_index.<locals>._perform_make_grouping_like.<locals>.<genexpr>c                    s    i | ]\}\}}| |qS r   r   )r	   r   r   vr!   r   r   
<dictcomp>X   s   
 zOmake_grouping_by_index.<locals>._perform_make_grouping_like.<locals>.<dictcomp>r   )r   r   r   	enumerater   itemspop)valuer#   r"   )r#   r   r"   P   s    

z;make_grouping_by_index.<locals>._perform_make_grouping_likez@The flat_values argument must be a list. Received value of type z(The specified grouping pattern requires z elements but received z
    Grouping pattern: z
    Values: )r   r   
ValueErrortypelenr   repr)r   Zflat_valuesZexpected_lengthr   r+   r   make_grouping_by_indexD   s    
"r0   c                    sL   t |ttfr  fdd|D S t |trDt fdd| D S  |S )a  
    Map a function over all of the scalar values of a grouping, maintaining the
    grouping structure

    :param fn: Single-argument function that accepts and returns scalar grouping values
    :param grouping: The grouping to map the function over
    :return: A new grouping with the same structure as input grouping with scalar
        values updated by the input function.
    c                    s   g | ]}t  |qS r   map_grouping)r	   r   fnr   r   r   |   s     z map_grouping.<locals>.<listcomp>c                    s   i | ]\}}|t  |qS r   r1   r   r3   r   r   r&      s      z map_grouping.<locals>.<dictcomp>)r   r   r   r   r   r(   )r4   r   r   r3   r   r2   q   s
    

r2   c                    s   t  fdd| S )a  
    Create a grouping from a schema by using the schema's scalar values to look up
    items in the provided source object.

    :param schema: A grouping of potential keys in source
    :param source: Dict-like object to use to look up scalar grouping value using
        scalar grouping values as keys
    :param default: Default scalar value to use if grouping scalar key is not present
        in source
    :return: grouping
    c                    s    |  S r   )get)sdefaultsourcer   r   <lambda>       z&make_grouping_by_key.<locals>.<lambda>r1   )r   r9   r8   r   r7   r   make_grouping_by_key   s    r<   c                       s(   e Zd Z fddZedd Z  ZS )SchemaTypeValidationErrorc                    s>   t  jd| dt| d| dt| dt| dd d S )N
                Schema: 
                Path: z 
                Expected type: z(
                Received value of type :
                    
                msg)super__init__r/   r-   )selfr*   full_schemapathexpected_type	__class__r   r   rE      s    z"SchemaTypeValidationError.__init__c                 C   s   t ||st||||d S r   )r   r=   )clsr*   rG   rH   rI   r   r   r   check   s    
zSchemaTypeValidationError.check__name__
__module____qualname__rE   classmethodrM   __classcell__r   r   rJ   r   r=      s   r=   c                       s(   e Zd Z fddZedd Z  ZS )SchemaLengthValidationErrorc                    s>   t  jd| dt| d| dt| dt| dd d S )Nr>   r?   z"
                Expected length: z*
                Received value of length r@   rA   rB   )rD   rE   r/   r.   )rF   r*   rG   rH   expected_lenrJ   r   r   rE      s    z$SchemaLengthValidationError.__init__c                 C   s   t ||krt||||d S r   )r.   rT   )rL   r*   rG   rH   rU   r   r   r   rM      s    z!SchemaLengthValidationError.checkrN   r   r   rJ   r   rT      s   rT   c                       s(   e Zd Z fddZedd Z  ZS )SchemaKeysValidationErrorc                    sB   t  jd| dt| d| dt|  dt| dd d S )Nr>   r?   z 
                Expected keys: z*
                Received value with keys r@   rA   rB   )rD   rE   r/   setkeys)rF   r*   rG   rH   expected_keysrJ   r   r   rE      s    
z"SchemaKeysValidationError.__init__c                 C   s&   t | t |kr"t||||d S r   )rW   rX   rV   )rL   r*   rG   rH   rY   r   r   r   rM      s    zSchemaKeysValidationError.checkrN   r   r   rJ   r   rV      s   rV   r   c                 C   s   |dkr|}t |ttfrvt| ||ttf t| ||t| tt| |D ]"\}\}}t	|||||f d qPnXt |t
rt| ||t
 t| ||t| |D ]"}t	| | || |||f d qn dS )zx
    Validate that the provided grouping conforms to the provided schema.
    If not, raise a SchemaValidationError
    N)rG   rH   )r   r   r   r=   rM   rT   r.   r'   r   r   r   rV   rW   )r   r   rG   rH   r   r   r6   r   r   r   r   r      s$    
   
r   c                 C   sl   t | trht| d }| d| d  }| d|||kt | d trRt| d n| d d}| | d S )Nid.propertyr*   )r*   str_id	triggeredrZ   )r   r   r   r5   r   update)r   r^   r]   Zprop_idZ
new_valuesr   r   r   update_args_group   s    
 r`   )N)N)Nr   )__doc__Zdash.exceptionsr   _utilsr   r   r   r   r0   r2   r<   r=   rT   rV   r   r`   r   r   r   r   <module>   s   
-

