o
    ˷e30                     @   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g dZddd eD ZeeZdefddZdefddZdefddZdee fddZeZdedef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]*)QUOTEDz`(?:\\`|[^`])*?`)DOTz\.|c                 c   s    | ]}d j | V  qdS )z
(?P<{}>{})N)format).0pair r   [/var/www/ideatree/venv/lib/python3.10/site-packages/google/cloud/firestore_v1/field_path.py	<genexpr>*   s    r   pathc                 c   st    d}t j}|| }|dur&|j}||}|V  | }|| |}|dus|t| kr8td| | |d dS )zLex 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}t | D ]$}|r|dkrtd| d}q|dkr)td| || d}q|r5|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   elementswant_dotelementr   r   r   split_field_pathC   s    
r#   api_reprc                 C   s\   g }t | D ]%}|d dkr&|d dkr&|dd }|tt}|tt}|| q|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   sf   g }| D ])}t |}|r|d|kr|| q|tttt}|t| t  q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   replacedr   r   r   render_field_path   s   

r4   
field_pathdatac                 C   s   t | }|}t|D ]C\}}t|tjr<||v r|| }q
|dkr*t|}t|t|d| }t	||}t|t|d| }t
||}t||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   KeyErrorr4   _FIELD_PATH_MISSING_KEY_FIELD_PATH_WRONG_TYPE)r5   r6   r,   nested_dataindexr-   msgpartialr   r   r   get_nested_value   s    6

rB   c                   @   s   e Zd ZdZdd ZedefddZedef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   s2   |D ]}t |tr|sd}t|qt|| _d S )Nz3One or more components is not a string or is empty.)r8   strr   tupleparts)selfrF   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   s`   z|  |W S  ty/   |d}|D ]}|stdt|r(td|qt|  Y S w )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: {})rM   r   split_LEADING_ALPHA_INVALIDr   r   rC   )rL   rN   r    r"   r   r   r   from_string$  s    

zFieldPath.from_stringc                 C   s6   d}| j D ]
}|d| d 7 }q|d d }d|S )N 'z',r%   zFieldPath({}))rF   r   )rG   pathsrH   r   r   r   __repr__B  s
   

zFieldPath.__repr__c                 C   s   t |  S N)hashto_api_reprrG   r   r   r   __hash__I  s   zFieldPath.__hash__c                 C   s   t |tr| j|jkS tS rV   r8   rC   rF   NotImplementedrG   otherr   r   r   __eq__L     
zFieldPath.__eq__c                 C   s   t |tr| j|jk S tS rV   r[   r]   r   r   r   __lt__Q  r`   zFieldPath.__lt__c                 C   sF   t |tr| j|j }t| S t |tr!| jt|j }t| S tS )zAdds `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`.
        )r8   rC   rF   rD   rQ   r\   )rG   r^   rF   r   r   r   __add__V  s   

zFieldPath.__add__c                 C   s
   t | jS )zRender a quoted string representation of the FieldPath

        Returns:
            (str) Quoted string representation of the path stored
            within this FieldPath.
        )r4   rF   rY   r   r   r   rX   f  s   
zFieldPath.to_api_reprc                 C   s(   | j dt|j  |j dt| j  kS )zCheck whether ``other`` is an ancestor.

        Returns:
            (bool) True IFF ``other`` is an ancestor or equal to ``self``,
            else False.
        N)rF   r   r]   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 rV   )rC   rF   )r   r?   rY   r   r   	<setcomp>~  s    z$FieldPath.lineage.<locals>.<setcomp>)ranger   rF   )rG   indexesr   rY   r   lineagex  s   zFieldPath.lineagec                   C   s   dS )zA 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)rh   
__module____qualname____doc__rJ   classmethodrD   rM   rQ   rU   rZ   r_   ra   rb   rX   rc   rg   staticmethodri   r   r   r   r   rC      s"    		rC   )rl   collectionsr   retypingr   r:   r<   r=   r0   r+   r*   r)   r(   compiler/   rP   PATH_ELEMENT_TOKENSr1   TOKENS_PATTERNr   rD   r   r#   r.   r4   get_field_pathdictrB   objectrC   r   r   r   r   <module>   s2   


#)M