B
    ˆuf30  ã               @   sì   d Z ddlmZ ddlZddlmZ dZdZdZdZ	d	Z
e
d
 ZdZe
e Ze d¡Ze d¡ZdddgZd dd„ eD ƒ¡Ze e¡Zedœdd„Zedœdd„Zedœdd„Zee dœdd„ZeZeedœd d!„ZG d"d#„ d#eƒZdS )$zBUtilities for managing / converting field paths to / from strings.é    )ÚabcN)ÚIterablez!{!r} is not contained in the dataz2{!r} is not contained in the data for the key {!r}zGThe data at {!r} is not a dictionary, so it cannot contain the key {!r}Ú.ú\é   ú`z^[_a-zA-Z][_a-zA-Z0-9]*$z$^[_a-zA-Z][_a-zA-Z0-9]*[^_a-zA-Z0-9])ÚSIMPLEz[_a-zA-Z][_a-zA-Z0-9]*)ZQUOTEDz`(?:\\`|[^`])*?`)ÚDOTz\.ú|c             c   s   | ]}d j |Ž V  qdS )z
(?P<{}>{})N)Úformat)Ú.0Úpair© r   úf/home/ankuromar296_gmail_com/myenv/lib/python3.7/site-packages/google/cloud/firestore_v1/field_path.pyú	<genexpr>*   s    r   )Úpathc             c   sp   d}t j}|| ƒ}x4|dk	rF|j}| |¡}|V  | ¡ }|| |ƒ}qW |t| ƒkrltd | | |d… ¡ƒ‚dS )z‘Lex a field path into tokens (including dots).

    Args:
        path (str): field path to be lexed.
    Returns:
        List(str): tokens
    r   Nz!Path {} not consumed, residue: {})ÚTOKENS_REGEXÚmatchÚ	lastgroupÚgroupÚendÚlenÚ
ValueErrorr   )r   ÚposÚ	get_tokenr   Útype_Úvaluer   r   r   Ú_tokenize_field_path.   s    

r   c             C   s‚   | sg S g }d}xVt | ƒD ]J}|r@|dkr:td | ¡ƒ‚qdd}q|dkrVtd | ¡ƒ‚| |¡ d}qW |rp|s~td | ¡ƒ‚|S )a  Split a field path into valid elements (without dots).

    Args:
        path (str): field path to be lexed.
    Returns:
        List(str): tokens
    Raises:
        ValueError: if the path does not match the elements-interspersed-
                    with-dots pattern.
    Fr   zInvalid path: {}T)r   r   r   Úappend)r   ÚelementsZwant_dotÚelementr   r   r   Úsplit_field_pathC   s     
r!   )Úapi_reprc             C   s`   g }xVt | ƒD ]J}|d dkrN|d dkrN|dd… }| tt¡}| tt¡}| |¡ qW |S )a;  Parse a **field path** from into a list of nested field names.

    See :func:`field_path` for more on **field paths**.

    Args:
        api_repr (str):
            The unique Firestore api representation which consists of
            either simple or UTF-8 field names. It cannot exceed
            1500 bytes, and cannot be empty. Simple field names match
            ``'^[_a-zA-Z][_a-zA-Z0-9]*$'``. All other field names are
            escaped by surrounding them with backticks.

    Returns:
        List[str, ...]: The list of field names in the field path.
    r   r   éÿÿÿÿé   )r!   ÚreplaceÚ_ESCAPED_BACKTICKÚ	_BACKTICKÚ_ESCAPED_BACKSLASHÚ
_BACKSLASHr   )r"   Úfield_namesÚ
field_namer   r   r   Úparse_field_pathf   s    r,   )r*   c             C   sj   g }xZ| D ]R}t  |¡}|r6| d¡|kr6| |¡ q
| tt¡ tt¡}| t| t ¡ q
W t	 
|¡S )aC  Create a **field path** from a list of nested field names.

    A **field path** is a ``.``-delimited concatenation of the field
    names. It is used to represent a nested field. For example,
    in the data

    .. code-block:: python

       data = {
          'aa': {
              'bb': {
                  'cc': 10,
              },
          },
       }

    the field path ``'aa.bb.cc'`` represents that data stored in
    ``data['aa']['bb']['cc']``.

    Args:
        field_names: The list of field names.

    Returns:
        str: The ``.``-delimited field path.
    r   )Ú_SIMPLE_FIELD_NAMEr   r   r   r%   r)   r(   r'   r&   Ú_FIELD_PATH_DELIMITERÚjoin)r*   Úresultr+   r   Zreplacedr   r   r   Úrender_field_pathƒ   s    

r1   )Ú
field_pathÚdatac             C   sª   t | ƒ}|}x˜t|ƒD ]Œ\}}t|tjƒr~||kr<|| }q¢|dkrXt |¡}t|ƒ‚q¢t|d|… ƒ}t	 ||¡}t|ƒ‚qt|d|… ƒ}t
 ||¡}t|ƒ‚qW |S )a  Get a (potentially nested) value from a dictionary.

    If the data is nested, for example:

    .. code-block:: python

       >>> data
       {
           'top1': {
               'middle2': {
                   'bottom3': 20,
                   'bottom4': 22,
               },
               'middle5': True,
           },
           'top6': b'  foo',
       }

    a **field path** can be used to access the nested data. For
    example:

    .. code-block:: python

       >>> get_nested_value('top1', data)
       {
           'middle2': {
               'bottom3': 20,
               'bottom4': 22,
           },
           'middle5': True,
       }
       >>> get_nested_value('top1.middle2', data)
       {
           'bottom3': 20,
           'bottom4': 22,
       }
       >>> get_nested_value('top1.middle2.bottom3', data)
       20

    See :meth:`~google.cloud.firestore_v1.client.Client.field_path` for
    more information on **field paths**.

    Args:
        field_path (str): A field path (``.``-delimited list of
            field names).
        data (Dict[str, Any]): The (possibly nested) data.

    Returns:
        Any: (A copy of) the value stored for the ``field_path``.

    Raises:
        KeyError: If the ``field_path`` does not match nested data.
    r   N)r,   Ú	enumerateÚ
isinstancer   ÚMappingÚ_FIELD_PATH_MISSING_TOPr   ÚKeyErrorr1   Ú_FIELD_PATH_MISSING_KEYÚ_FIELD_PATH_WRONG_TYPE)r2   r3   r*   Znested_dataÚindexr+   ÚmsgÚpartialr   r   r   Úget_nested_value¯   s     6



r>   c               @   sˆ   e Zd ZdZdd„ Zeedœdd„ƒZee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„ Zedd„ ƒZdS )Ú	FieldPathaÛ  Field Path object for client use.

    A field path is a sequence of element keys, separated by periods.
    Each element key can be either a simple identifier, or a full unicode
    string.

    In the string representation of a field path, non-identifier elements
    must be quoted using backticks, with internal backticks and backslashes
    escaped with a backslash.

    Args:
        parts: (one or more strings)
            Indicating path of the key to be used.
    c             G   s6   x&|D ]}t |tƒr|sd}t|ƒ‚qW t|ƒ| _d S )Nz3One or more components is not a string or is empty.)r5   Ústrr   ÚtupleÚparts)ÚselfrB   ÚpartÚerrorr   r   r   Ú__init__  s
    
zFieldPath.__init__)r"   c             C   s    |  ¡ }|stdƒ‚| t|ƒŽ S )a€  Factory: create a FieldPath from the string formatted per the API.

        Args:
            api_repr (str): a string path, with non-identifier elements quoted
            It cannot exceed 1500 characters, and cannot be empty.
        Returns:
            (:class:`FieldPath`) An instance parsed from ``api_repr``.
        Raises:
            ValueError if the parsing fails
        z.Field path API representation cannot be empty.)Ústripr   r,   )Úclsr"   r   r   r   Úfrom_api_repr  s    zFieldPath.from_api_repr)Úpath_stringc             C   sd   y
|   |¡S  tk
r^   | d¡}x0|D ](}|s:tdƒ‚t |¡r*td |¡ƒ‚q*W t|Ž S X dS )a  Factory: create a FieldPath from a unicode string representation.

        This method splits on the character `.` and disallows the
        characters `~*/[]`. To create a FieldPath whose components have
        those characters, call the constructor.

        Args:
            path_string (str): A unicode string which cannot contain
            `~*/[]` characters, cannot exceed 1500 bytes, and cannot be empty.

        Returns:
            (:class:`FieldPath`) An instance parsed from ``path_string``.
        r   zEmpty elementz3Non-alphanum char in element with leading alpha: {}N)rI   r   ÚsplitÚ_LEADING_ALPHA_INVALIDr   r   r?   )rH   rJ   r   r    r   r   r   Úfrom_string$  s    



zFieldPath.from_stringc             C   s:   d}x| j D ]}|d| d 7 }qW |d d… }d |¡S )NÚ ú'z',r#   zFieldPath({}))rB   r   )rC   ÚpathsrD   r   r   r   Ú__repr__B  s
    zFieldPath.__repr__c             C   s   t |  ¡ ƒS )N)ÚhashÚto_api_repr)rC   r   r   r   Ú__hash__I  s    zFieldPath.__hash__c             C   s   t |tƒr| j|jkS tS )N)r5   r?   rB   ÚNotImplemented)rC   Úotherr   r   r   Ú__eq__L  s    
zFieldPath.__eq__c             C   s   t |tƒr| j|jk S tS )N)r5   r?   rB   rU   )rC   rV   r   r   r   Ú__lt__Q  s    
zFieldPath.__lt__c             C   sJ   t |tƒr| j|j }t|Ž S t |tƒrB| jt |¡j }t|Ž S tS dS )zØAdds `other` field path to end of this field path.

        Args:
            other (~google.cloud.firestore_v1._helpers.FieldPath, str):
                The field path to add to the end of this `FieldPath`.
        N)r5   r?   rB   r@   rM   rU   )rC   rV   rB   r   r   r   Ú__add__V  s    

zFieldPath.__add__c             C   s
   t | jƒS )z¶Render a quoted string representation of the FieldPath

        Returns:
            (str) Quoted string representation of the path stored
            within this FieldPath.
        )r1   rB   )rC   r   r   r   rS   f  s    zFieldPath.to_api_reprc             C   s(   | j dt|j ƒ… |j dt| j ƒ… kS )z¥Check whether ``other`` is an ancestor.

        Returns:
            (bool) True IFF ``other`` is an ancestor or equal to ``self``,
            else False.
        N)rB   r   )rC   rV   r   r   r   Úeq_or_parento  s    zFieldPath.eq_or_parentc                s"   t dtˆ jƒƒ}‡ fdd„|D ƒS )zVReturn field paths for all parents.

        Returns: Set[:class:`FieldPath`]
        r$   c                s   h | ]}t ˆ jd |… Ž ’qS )N)r?   rB   )r   r;   )rC   r   r   ú	<setcomp>~  s    z$FieldPath.lineage.<locals>.<setcomp>)Úranger   rB   )rC   Zindexesr   )rC   r   Úlineagex  s    zFieldPath.lineagec               C   s   dS )zÜA special FieldPath value to refer to the ID of a document. It can be used
           in queries to sort or filter by the document ID.

        Returns: A special sentinel value to refer to the ID of a document.
        Ú__name__r   r   r   r   r   Údocument_id€  s    zFieldPath.document_idN)r^   Ú
__module__Ú__qualname__Ú__doc__rF   Úclassmethodr@   rI   rM   rQ   rT   rW   rX   rY   rS   rZ   r]   Ústaticmethodr_   r   r   r   r   r?   ü   s   		r?   )rb   Úcollectionsr   ÚreÚtypingr   r7   r9   r:   r.   r)   r(   r'   r&   Úcompiler-   rL   ZPATH_ELEMENT_TOKENSr/   ZTOKENS_PATTERNr   r@   r   r!   r,   r1   Zget_field_pathÚdictr>   Úobjectr?   r   r   r   r   Ú<module>   s2   


#)M