o
    ˷e)                     @   s4  U d Z ddl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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 m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( ej)e*d< e+e*d< dZ,dZ-dZ.dZ/dZ0dZ1ej2j3j4Z5ej6j7ej8ej6j9ej:iZ;G dd de<Z=dtddZ>dejj?fd d!Z@de+fd"d#ZAd$d%de&d& fd'd(ZBG d)d* d*ZCde fd+d,ZDde(deEeFeGeHejeIeJe+e=f
 fd-d.ZKde+fd/d0ZLdeIfd1d2ZMe)d3ZN	4dud5ede"e'e e f e df fd6d7ZOdtd8d9ZPde fd:d;ZQG d<d= d=e<ZRde$ejjS fd>d?ZTde$ejjS fd@dAZUG dBdC dCeRZVde$ejjS fdDdEZWG dFdG dGeRZXde$ejjS fdHdIZYdejjSfdJdKZZG dLdM dMe[Z\dvde(eJdf fdOdPZ]dQeIde$e'eIeIf  fdRdSZ^G dTdU dUe<Z_G dVdW dWe_Z`G dXdY dYe_Zade+fdZd[Zb	dwd\e&e(eejf  defd]d^Zcd_e(eejf d`e(eejf deFfdadbZddce(eIeJf dddeddffdgdhZedce(eIeJf de"e!ddf fdidjZfddkdle&eI de"dm fdndoZgdpeIde&dq fdrdsZhdS )xz<Common helpers shared across Google Cloud Firestore modules.    N)DatetimeWithNanoseconds)gapic_v1)
struct_pb2)
latlng_pb2)
exceptions)_datetime_to_pb_timestamp)DocumentTransform)
transforms)types)	FieldPath)parse_field_path)common)document)write)	Timestamp)	AnyDict	GeneratorIteratorListNoReturnOptionalTupleUnion
_EmptyDict_GRPC_ERROR_MAPPINGz<A path element must be a string. Received {}, which is a {}./z<Transaction not in progress, cannot be used in API requests.z,Attempted read after write in a transaction.zReference value {!r} in unexpected format, expected to be of the form ``projects/{{project}}/databases/{{database}}/documents/{{document_path}}``.zLDocument {!r} does not correspond to the same database ({!r}) as the client.c                   @   s:   e Zd ZdZdddZdejfddZdd	 Zd
d Z	dS )GeoPointzSimple container for a geo point value.

    Args:
        latitude (float): Latitude of a point.
        longitude (float): Longitude of a point.
    returnNc                 C   s   || _ || _d S Nlatitude	longitude)selfr!   r"    r$   Y/var/www/ideatree/venv/lib/python3.10/site-packages/google/cloud/firestore_v1/_helpers.py__init__Q   s   
zGeoPoint.__init__c                 C   s   t j| j| jdS )zConvert the current object to protobuf.

        Returns:
            google.type.latlng_pb2.LatLng: The current point as a protobuf.
        r    )r   LatLngr!   r"   r#   r$   r$   r%   to_protobufU   s   zGeoPoint.to_protobufc                 C   s&   t |tstS | j|jko| j|jkS )zCompare two geo points for equality.

        Returns:
            Union[bool, NotImplemented]: :data:`True` if the points compare
            equal, else :data:`False`. (Or :data:`NotImplemented` if
            ``other`` is not a geo point.)
        )
isinstancer   NotImplementedr!   r"   r#   otherr$   r$   r%   __eq__]   s   
zGeoPoint.__eq__c                 C   s   |  |}|tu rtS | S )zCompare two geo points for inequality.

        Returns:
            Union[bool, NotImplemented]: :data:`False` if the points compare
            equal, else :data:`True`. (Or :data:`NotImplemented` if
            ``other`` is not a geo point.)
        )r.   r+   )r#   r-   equality_valr$   r$   r%   __ne__j   s   
zGeoPoint.__ne__r   N)
__name__
__module____qualname____doc__r&   r   r'   r)   r.   r0   r$   r$   r$   r%   r   I   s    
r   r   c                 C   sv   t | }|dkrtd|r|d dkrtdn
|d dkr#td| D ]}t|ts8t|t|}t|q%dS )aR  Verifies that a ``path`` has the correct form.

    Checks that all of the elements in ``path`` are strings.

    Args:
        path (Tuple[str, ...]): The components in a collection or
            document path.
        is_collection (bool): Indicates if the ``path`` represents
            a document or a collection.

    Raises:
        ValueError: if

            * the ``path`` is empty
            * ``is_collection=True`` and there are an even number of elements
            * ``is_collection=False`` and there are an odd number of elements
            * an element is not a string
    r   z+Document or collection path cannot be empty   z5A collection must have an odd number of path elements   z4A document must have an even number of path elementsN)len
ValueErrorr*   strBAD_PATH_TEMPLATEformattype)pathis_collectionnum_elementselementmsgr$   r$   r%   verify_pathy   s   
rC   c                 C   sl  | du rt jtjdS t| trt j| dS t| tr!t j| dS t| tr,t j| dS t| tr9t j| 	 dS t| t
j
rGt jt| dS t| trRt j| dS t| tr]t j| dS t| d	d}|durmt j|d
S t| trzt j|  dS t| ttttfrtdd | D }t j|d}t j|dS t| trt| }t j|d}t j|dS td| dt| )a  Converts a native Python value into a Firestore protobuf ``Value``.

    Args:
        value (Union[NoneType, bool, int, float, datetime.datetime,             str, bytes, dict, ~google.cloud.Firestore.GeoPoint]): A native
            Python value to convert to a protobuf field.

    Returns:
        ~google.cloud.firestore_v1.types.Value: A
        value encoded as a Firestore protobuf.

    Raises:
        TypeError: If the ``value`` is not one of the accepted types.
    N)
null_value)boolean_value)integer_value)double_value)timestamp_value)string_value)bytes_value_document_path)reference_value)geo_point_valuec                 s   s    | ]}t |V  qd S r   encode_value.0rA   r$   r$   r%   	<genexpr>   s    zencode_value.<locals>.<genexpr>values)array_value)fields)	map_valuez#Cannot convert to a Firestore ValuezInvalid type)r   Valuer   
NULL_VALUEr*   boolintfloatr   timestamp_pbdatetimer   r:   bytesgetattrr   r)   listtupleset	frozenset
ArrayValuedictencode_dictMapValue	TypeErrorr=   )valuedocument_path
value_listvalue_pb
value_dictr$   r$   r%   rO      s@   







rO   c                 C   s   dd |   D S )a*  Encode a dictionary into protobuf ``Value``-s.

    Args:
        values_dict (dict): The dictionary to encode as protobuf fields.

    Returns:
        Dict[str, ~google.cloud.firestore_v1.types.Value]: A
        dictionary of string keys and ``Value`` protobufs as dictionary
        values.
    c                 S   s   i | ]	\}}|t |qS r$   rN   rQ   keyrj   r$   r$   r%   
<dictcomp>   s    zencode_dict.<locals>.<dictcomp>)items)values_dictr$   r$   r%   rg      s   rg   snapshotz8google.cloud.firestore_v1.base_document.DocumentSnapshotz(google.cloud.firestore_v1.types.Documentc                 C   s4   ddl m} | jsd S || jjt| j| j| jdS )Nr   )Document)namerV   create_timeupdate_time)	google.cloud.firestore_v1.typesru   exists	referencerK   rg   _datarw   rx   )rt   ru   r$   r$   r%   document_snapshot_to_protobuf   s   r}   c                   @   sB   e Zd ZdZdefddZedefddZedefdd	Zd
S )DocumentReferenceValuea  DocumentReference path container with accessors for each relevant chunk.

    Usage:
        doc_ref_val = DocumentReferenceValue(
            'projects/my-proj/databases/(default)/documents/my-col/my-doc',
        )
        assert doc_ref_val.project_name == 'my-proj'
        assert doc_ref_val.collection_name == 'my-col'
        assert doc_ref_val.document_id == 'my-doc'
        assert doc_ref_val.database_name == '(default)'

    Raises:
        ValueError: If the supplied value cannot satisfy a complete path.
    rL   c                 C   sd   || _ |t}t|dk rt|}t||d | _|d | _|d | _	d
|dd  | _d S )N   r7         r      )_reference_valuesplitDOCUMENT_PATH_DELIMITERr8   BAD_REFERENCE_ERRORr<   r9   project_namecollection_namedatabase_namejoindocument_id)r#   rL   partsrB   r$   r$   r%   r&   
  s   




zDocumentReferenceValue.__init__r   c                 C   s   d | j| jgS )zSComputed property for a DocumentReference's collection_name and
        document Idr   )r   r   r   r(   r$   r$   r%   full_key  s   zDocumentReferenceValue.full_keyc              	   C   s&   | j pdd| jd| jd| j| jgS )Nr   projects	databases	documents)r   r   r   r   r   r   r(   r$   r$   r%   	full_path  s   
z DocumentReferenceValue.full_pathN)	r2   r3   r4   r5   r:   r&   propertyr   r   r$   r$   r$   r%   r~      s    r~   c                 C   sD   ddl m} t| }||j}|j| kr t| |j}t	||S )a  Convert a reference value string to a document.

    Args:
        reference_value (str): A document reference value.
        client (:class:`~google.cloud.firestore_v1.client.Client`):
            A client that has a document factory.

    Returns:
        :class:`~google.cloud.firestore_v1.document.DocumentReference`:
            The document corresponding to ``reference_value``.

    Raises:
        ValueError: If the ``reference_value`` is not of the expected
            format: ``projects/{project}/databases/{database}/documents/...``.
        ValueError: If the ``reference_value`` does not come from the same
            project / database combination as the ``client``.
    r   )BaseDocumentReference)
'google.cloud.firestore_v1.base_documentr   r~   r   r   rK   WRONG_APP_REFERENCEr<   _database_stringr9   )rL   clientr   doc_ref_valuer   rB   r$   r$   r%   reference_value_to_document.  s   
r   c                    s   t | d| }|d}|dkrdS |dkr|jS |dkr|jS |dkr&|jS |dkr0t|jS |d	kr7|jS |d
kr>|j	S |dkrHt
|j S |dkrUt|jj|jjS |dkrd fdd|jjD S |dkrot|jj S td|)a  Converts a Firestore protobuf ``Value`` to a native Python value.

    Args:
        value (google.cloud.firestore_v1.types.Value): A
            Firestore protobuf to be decoded / parsed / converted.
        client (:class:`~google.cloud.firestore_v1.client.Client`):
            A client that has a document factory.

    Returns:
        Union[NoneType, bool, int, float, datetime.datetime,             str, bytes, dict, ~google.cloud.Firestore.GeoPoint]: A native
        Python value converted from the ``value``.

    Raises:
        NotImplementedError: If the ``value_type`` is ``reference_value``.
        ValueError: If the ``value_type`` is unknown.
    _pb
value_typerD   NrE   rF   rG   rH   rI   rJ   rL   rM   rU   c                    s   g | ]}t | qS r$   decode_valuerP   r   r$   r%   
<listcomp>x  s    
z decode_value.<locals>.<listcomp>rW   zUnknown ``value_type``)r`   
WhichOneofrE   rF   rG   r   from_timestamp_pbrH   rI   rJ   r   rL   r   rM   r!   r"   rU   rT   decode_dictrW   rV   r9   )rj   r   rm   r   r$   r   r%   r   L  s:   


r   c                    s"   t | d| } fdd| D S )a   Converts a protobuf map of Firestore ``Value``-s.

    Args:
        value_fields (google.protobuf.pyext._message.MessageMapContainer): A
            protobuf map of Firestore ``Value``-s.
        client (:class:`~google.cloud.firestore_v1.client.Client`):
            A client that has a document factory.

    Returns:
        Dict[str, Union[NoneType, bool, int, float, datetime.datetime,             str, bytes, dict, ~google.cloud.Firestore.GeoPoint]]: A dictionary
        of native Python values converted from the ``value_fields``.
    r   c                    s   i | ]
\}}|t | qS r$   r   ro   r   r$   r%   rq     s    zdecode_dict.<locals>.<dictcomp>)r`   rr   )value_fieldsr   value_fields_pbr$   r   r%   r     s   r   c                 C   s.   | j td\}}||krtd| j d||S )a  Parse a document ID from a document protobuf.

    Args:
        document_pb (google.cloud.proto.firestore.v1.            document.Document): A protobuf for a document that
            was created in a ``CreateDocument`` RPC.
        expected_prefix (str): The expected collection prefix for the
            fully-qualified document name.

    Returns:
        str: The document ID from the protobuf.

    Raises:
        ValueError: If the name does not begin with the prefix.
    r7   zUnexpected document namezExpected to begin with)rv   rsplitr   r9   )document_pbexpected_prefixprefixr   r$   r$   r%   
get_doc_id  s   r   zMarker for an empty dict valueFprefix_pathc           	      c   s    | s
|t fV  dS t|  D ]2\}}|rt|}nt|}t|j|j  }t|tr=t||D ]	\}}||fV  q2q||fV  qdS )z7Do depth-first walk of tree, yielding field_path, valueN)	r   sortedrr   r   from_stringr   r*   rf   extract_fields)	document_datar   expand_dotsrp   rj   sub_key
field_paths_paths_valuer$   r$   r%   r     s   
r   c                 C   sB   | }|j dd D ]}||i }q	|tu ri }|||j d < dS )z,Set a value into a document for a field_pathN)r   
setdefaultr   )r   r   rj   currentrA   r$   r$   r%   set_field_value  s   r   c                 C   s<   |j std| }|j d d D ]}|| }q||j d  S )Nz
Empty pathr   )r   r9   )r   r   r   rA   r$   r$   r%   get_field_value  s   
r   c                   @   s   e Zd ZdZdddZdedeeeef edf fddZ	e
d	d
 Ze
dd ZddddZ	ddejjfddZdeejjj fddZddejjfddZdS )DocumentExtractora  Break document data up into actual data and transforms.

    Handle special values such as ``DELETE_FIELD``, ``SERVER_TIMESTAMP``.

    Args:
        document_data (dict):
            Property names and values to use for sending a change to
            a document.
    r   Nc                 C   sH  || _ g | _g | _g | _i | _i | _i | _i | _i | _i | _	d| _
t }| |}|D ]v\}}||kr;|tu r;d| _
q+|tju rG| j| q+|tju rS| j| q+t|tjr`|j| j|< q+t|tjrm|j| j|< q+t|tjrz|j| j|< q+t|tjr|j| j|< q+t|tjr|j| j|< q+| j| t| j	|| q+d S )NFT)r   field_pathsdeleted_fieldsserver_timestampsarray_removesarray_unions
incrementsminimumsmaximums
set_fieldsempty_documentr   _get_document_iteratorr   r	   DELETE_FIELDappendSERVER_TIMESTAMPr*   ArrayRemoverT   
ArrayUnion	Incrementrj   MaximumMinimumr   )r#   r   r   iteratorr   rj   r$   r$   r%   r&     sB   


zDocumentExtractor.__init__r   c                 C   s   t | j|S r   r   r   r#   r   r$   r$   r%   r     s   z(DocumentExtractor._get_document_iteratorc                 C   s(   t | jp| jp| jp| jp| jp| jS r   )rZ   r   r   r   r   r   r   r(   r$   r$   r%   has_transforms  s   z DocumentExtractor.has_transformsc                 C   s<   t | jt| j t| j t| j t| j t| j S r   )r   r   ra   r   r   r   r   r   r(   r$   r$   r%   transform_paths'  s   z!DocumentExtractor.transform_pathsFc                 C   s   d S r   r$   )r#   allow_empty_maskr$   r$   r%   _get_update_mask2  s   z"DocumentExtractor._get_update_maskc                 C   sD   |d urt j|d}nd }tjtj|t| jd| ||d}|S )Nrz   )rv   rV   )updateupdate_maskcurrent_document)	r   Preconditionr   Writer   ru   rg   r   r   )r#   rk   rz   r   r   	update_pbr$   r$   r%   get_update_pb5  s   
zDocumentExtractor.get_update_pbc                    s   dd  dd | j D  fdd| j D   fdd| j D  dd | j D  dd | j D  d	d | j D  }d
d t|D S )Nc                 S   s   dd | D }t j|dS )Nc                 S   s   g | ]}t |qS r$   rN   rP   r$   r$   r%   r   L      zWDocumentExtractor.get_field_transform_pbs.<locals>.make_array_value.<locals>.<listcomp>rS   )r   re   )rT   rl   r$   r$   r%   make_array_valueK  s   zCDocumentExtractor.get_field_transform_pbs.<locals>.make_array_valuec                 S   s$   g | ]}|t jj| td fqS ))r   set_to_server_value)r   r   FieldTransformto_api_reprREQUEST_TIME_ENUMrQ   r>   r$   r$   r%   r   P  s    z=DocumentExtractor.get_field_transform_pbs.<locals>.<listcomp>c                    ,   g | ]\}}|t jj|  |d fqS ))r   remove_all_from_arrayr   r   r   r   rQ   r>   rT   r   r$   r%   r   Z      c                    r   ))r   append_missing_elementsr   r   r   r$   r%   r   d  r   c                 S   ,   g | ]\}}|t jj| t|d fqS ))r   	incrementr   r   r   r   rO   rQ   r>   rj   r$   r$   r%   r   n      c                 S   r   ))r   maximumr   r   r$   r$   r%   r   w  r   c                 S   r   ))r   minimumr   r   r$   r$   r%   r     r   c                 S   s   g | ]\}}|qS r$   r$   )rQ   r>   	transformr$   r$   r%   r     r   )r   r   rr   r   r   r   r   r   )r#   rk   path_field_transformsr$   r   r%   get_field_transform_pbsH  s4   


'0;z)DocumentExtractor.get_field_transform_pbsc                 C   sD   |  |}tjtj||dd}|d ur |jjtj|dj |S )N)r   field_transforms)r   r   )	r   r   r   r   r   r   CopyFromr   r   )r#   rk   rz   r   transform_pbr$   r$   r%   get_transform_pb  s   
z"DocumentExtractor.get_transform_pbr1   F)NFr   )r2   r3   r4   r5   r&   r   r   r   r   r   r   r   r   r   r
   r   r   r   r   r   r   r   r   r$   r$   r$   r%   r     s*    

.






Dr   c                 C   sF   t |}|jrtd|j| dd}|jr || }|j| |gS )ai  Make ``Write`` protobufs for ``create()`` methods.

    Args:
        document_path (str): A fully-qualified document path.
        document_data (dict): Property names and values to use for
            creating a document.

    Returns:
        List[google.cloud.firestore_v1.types.Write]: One or two
        ``Write`` protobuf instances for ``create()``.
    z.Cannot apply DELETE_FIELD in a create request.Fr   r   r   r9   r   r   r   update_transformsextend)rk   r   	extractor	create_pbfield_transform_pbsr$   r$   r%   pbs_for_create  s   
r   c                 C   sB   t |}|jrtd|| }|jr|| }|j| |gS )ad  Make ``Write`` protobufs for ``set()`` methods.

    Args:
        document_path (str): A fully-qualified document path.
        document_data (dict): Property names and values to use for
            replacing a document.

    Returns:
        List[google.cloud.firestore_v1.types.Write]: One
        or two ``Write`` protobuf instances for ``set()``.
    zdCannot apply DELETE_FIELD in a set request without specifying 'merge=True' or 'merge=[field_paths]'.r   )rk   r   r   set_pbr   r$   r$   r%   pbs_for_set_no_merge  s   

r  c                       s   e Zd ZdZd fddZdddZdeeedf fdd	Zde	fd
dZ
dddZdddZ	ddeejj fddZ  ZS )DocumentExtractorForMerge7Break document data up into actual data and transforms.r   Nc                    s&   t t| | g | _g | _g | _d S r   )superr  r&   
data_mergetransform_mergemerge)r#   r   	__class__r$   r%   r&     s   
z"DocumentExtractorForMerge.__init__c                 C   s0   t | j| j | _| j| _t | j| j | _d S r   )r   r   r   r  r   r  r  r(   r$   r$   r%   _apply_merge_all  s   z*DocumentExtractorForMerge._apply_merge_allc                 c   s0    |D ]}t |tr|V  qtt| V  qd S r   )r*   r   r   )r#   r  merge_fieldr$   r$   r%   _construct_merge_paths  s   
z0DocumentExtractorForMerge._construct_merge_pathsc              	   C   s   t | |}tt|d D ]}|| ||d  }}||r)td||q|D ]}|| jv r4q,zt| j	| W q, t
yJ   td|w |S )Nr7   zMerge paths overlap: {}, {}zInvalid merge path: {})r   r  ranger8   eq_or_parentr9   r<   r   r   r   KeyError)r#   r  merge_pathsindexlhsrhs
merge_pathr$   r$   r%   _normalize_merge_paths  s   

z0DocumentExtractorForMerge._normalize_merge_pathsc                    s\  j rtd|}jd d = jd d = |_|D ]  jv r*j  jD ]} 	|r:j| q-qi }jD ]}t
j|}t||| qA|_fddjD }|rftd|tjj _t jD ]  fddjD }| qufddjD _fddj D _fd	dj D _d S )
Nz1Cannot merge specific fields with empty document.c                    s   g | ]	}| j vr|qS r$   )r  rQ   r   r(   r$   r%   r     s
    
z@DocumentExtractorForMerge._apply_merge_paths.<locals>.<listcomp>z!Cannot delete unmerged fields: {}c                    s   g | ]	}  |r|qS r$   )r  )rQ   transform_path)r  r$   r%   r   %  s    c                    s   g | ]}| v r|qS r$   r$   r   merged_transform_pathsr$   r%   r   ,  s    c                       i | ]\}}| v r||qS r$   r$   r   r  r$   r%   rq   0  
    z@DocumentExtractorForMerge._apply_merge_paths.<locals>.<dictcomp>c                    r  r$   r$   r   r  r$   r%   rq   6  r  )r   r9   r  r  r  r  r   r   r   r  r   r   r   r   r   r<   r   rc   r   r   r   rr   r   )r#   r  r  r   merged_set_fieldsrj   unmerged_deleted_fieldstranform_merge_pathsr$   )r  r  r#   r%   _apply_merge_paths  sT   










z,DocumentExtractorForMerge._apply_merge_pathsc                 C   s"   |du r
|    d S | | d S )NT)r
  r  )r#   r  r$   r$   r%   apply_merge<  s   z%DocumentExtractorForMerge.apply_mergeFc                    s     fdd j D }tj|dS )Nc                    s   g | ]}| j vr| qS r$   )r  r   r  r(   r$   r%   r   F  s
    
z>DocumentExtractorForMerge._get_update_mask.<locals>.<listcomp>r   )r  r   DocumentMask)r#   r   
mask_pathsr$   r(   r%   r   B  s   
z*DocumentExtractorForMerge._get_update_maskr1   r   )r2   r3   r4   r5   r&   r
  r   r   r  ra   r  r  r   r   r
   r   r"  r   __classcell__r$   r$   r  r%   r    s    


@
r  c                 C   s>   t |}|| || }|jr|| }|j| |gS )a  Make ``Write`` protobufs for ``set()`` methods.

    Args:
        document_path (str): A fully-qualified document path.
        document_data (dict): Property names and values to use for
            replacing a document.
        merge (Optional[bool] or Optional[List<apispec>]):
            If True, merge all fields; else, merge only the named fields.

    Returns:
        List[google.cloud.firestore_v1.types.Write]: One
        or two ``Write`` protobuf instances for ``set()``.
    )r  r   r   r   r   r   r   )rk   r   r  r   r   r   r$   r$   r%   pbs_for_set_with_mergeO  s   


r%  c                       sZ   e Zd ZdZd fddZdedeeeef edf fddZ	dde
jjfd
dZ  ZS )DocumentExtractorForUpdater  r   Nc                    s   t t| | tdd |D | _t| j}| jD ]}| D ]}||v r.td||q q| j	D ]}||vr@td|q3d S )Nc                 S   s   g | ]}t |qS r$   )r   r   )rQ   rp   r$   r$   r%   r   q  s    z7DocumentExtractorForUpdate.__init__.<locals>.<listcomp>zConflicting field path: {}, {}z"Cannot update with nest delete: {})
r  r&  r&   r   top_level_pathsrc   lineager9   r<   r   )r#   r   topstop_level_pathancestorr   r  r$   r%   r&   n  s,   


z#DocumentExtractorForUpdate.__init__r   c                 C   s   t | j|ddS )NT)r   r   r   r$   r$   r%   r     s   z1DocumentExtractorForUpdate._get_document_iteratorFc                 C   s4   g }| j D ]}|| jvr||  qtj|dS )Nr!  )r'  r   r   r   r   r"  )r#   r   r#  r   r$   r$   r%   r     s   

z+DocumentExtractorForUpdate._get_update_maskr1   r   )r2   r3   r4   r5   r&   r   r   r   r   r   r
   r   r"  r   r$  r$   r$   r  r%   r&  k  s    
r&  c                 C   s^   t |}|jrtd|du rtdd}|| }|| |jr,|| }|j	| |gS )aC  Make ``Write`` protobufs for ``update()`` methods.

    Args:
        document_path (str): A fully-qualified document path.
        field_updates (dict): Field names or paths to update and values
            to update with.
        option (optional[:class:`~google.cloud.firestore_v1.client.WriteOption`]):
            A write option to make assertions / preconditions on the server
            state of the document before applying changes.

    Returns:
        List[google.cloud.firestore_v1.types.Write]: One
        or two ``Write`` protobuf instances for ``update()``.
    z%Cannot update with an empty document.NTr   )
r&  r   r9   ExistsOptionr   modify_writer   r   r   r   )rk   field_updatesoptionr   r   r   r$   r$   r%   pbs_for_update  s   



r0  c                 C   s"   t j| d}|dur|| |S )a  Make a ``Write`` protobuf for ``delete()`` methods.

    Args:
        document_path (str): A fully-qualified document path.
        option (optional[:class:`~google.cloud.firestore_v1.client.WriteOption`]):
            A write option to make assertions / preconditions on the server
            state of the document before applying changes.

    Returns:
        google.cloud.firestore_v1.types.Write: A
        ``Write`` protobuf instance for the ``delete()``.
    )deleteN)r   r   r-  )rk   r/  write_pbr$   r$   r%   pb_for_delete  s   
r3  c                   @   s   e Zd ZdZdS )ReadAfterWriteErrorzhRaised when a read is attempted after a write.

    Raised by "read" methods that use transactions.
    N)r2   r3   r4   r5   r$   r$   r$   r%   r4    s    r4  Tc                 C   s:   | du rdS | j stt|rt| jdkrtt| jS )a  Get the transaction ID from a ``Transaction`` object.

    Args:
        transaction (Optional[:class:`~google.cloud.firestore_v1.transaction.            Transaction`]):
            An existing transaction that this query will run in.
        read_operation (Optional[bool]): Indicates if the transaction ID
            will be used in a read operation. Defaults to :data:`True`.

    Returns:
        Optional[bytes]: The ID of the transaction, or :data:`None` if the
        ``transaction`` is :data:`None`.

    Raises:
        ValueError: If the ``transaction`` is not in progress (only if
            ``transaction`` is not :data:`None`).
        ReadAfterWriteError: If the ``transaction`` has writes stored on
            it and ``read_operation`` is :data:`True`.
    Nr   )in_progressr9   INACTIVE_TXNr8   
_write_pbsr4  READ_AFTER_WRITE_ERRORid)transactionread_operationr$   r$   r%   get_transaction_id  s   r<  r   c                 K   s
   d| fgS )zCreate RPC metadata containing a prefix.

    Args:
        prefix (str): appropriate resource path.

    Returns:
        List[Tuple[str, str]]: RPC metadata with supplied prefix
    zgoogle-cloud-resource-prefixr$   )r   kwr$   r$   r%   metadata_with_prefix  s   
	r>  c                   @   s    e Zd ZdZddefddZdS )WriteOptionz7Option used to assert a condition on a write operation.Nr   c                 C   s   t )a>  Modify a ``Write`` protobuf based on the state of this write option.

        This is a virtual method intended to be implemented by subclasses.

        Args:
            write (google.cloud.firestore_v1.types.Write): A
                ``Write`` protobuf instance to be modified with a precondition
                determined by the state of this option.
            no_create_msg (Optional[str]): A message to use to indicate that
                a create operation is not allowed.

        Raises:
            NotImplementedError: Always, this method is virtual.
        )NotImplementedError)r#   r   no_create_msgr$   r$   r%   r-    s   zWriteOption.modify_writer   )r2   r3   r4   r5   r   r-  r$   r$   r$   r%   r?    s    r?  c                   @   ,   e Zd ZdZd
ddZdd Zd
dd	ZdS )LastUpdateOptiona*  Option used to assert a "last update" condition on a write operation.

    This will typically be created by
    :meth:`~google.cloud.firestore_v1.client.Client.write_option`.

    Args:
        last_update_time (google.protobuf.timestamp_pb2.Timestamp): A
            timestamp. When set, the target document must exist and have
            been last updated at that time. Protobuf ``update_time`` timestamps
            are typically returned from methods that perform write operations
            as part of a "write result" protobuf or directly.
    r   Nc                 C   
   || _ d S r   )_last_update_time)r#   last_update_timer$   r$   r%   r&        
zLastUpdateOption.__init__c                 C      t || jstS | j|jkS r   )r*   r	  r+   rE  r,   r$   r$   r%   r.        zLastUpdateOption.__eq__c                 K   "   t j| jd}|jj|j dS )ac  Modify a ``Write`` protobuf based on the state of this write option.

        The ``last_update_time`` is added to ``write_pb`` as an "update time"
        precondition. When set, the target document must exist and have been
        last updated at that time.

        Args:
            write_pb (google.cloud.firestore_v1.types.Write): A
                ``Write`` protobuf instance to be modified with a precondition
                determined by the state of this option.
            unused_kwargs (Dict[str, Any]): Keyword arguments accepted by
                other subclasses that are unused here.
        )rx   N)r
   r   rE  r   r   r   r#   r   unused_kwargscurrent_docr$   r$   r%   r-  "  s   zLastUpdateOption.modify_writer1   r2   r3   r4   r5   r&   r.   r-  r$   r$   r$   r%   rC    s
    
rC  c                   @   rB  )r,  a  Option used to assert existence on a write operation.

    This will typically be created by
    :meth:`~google.cloud.firestore_v1.client.Client.write_option`.

    Args:
        exists (bool): Indicates if the document being modified
            should already exist.
    r   Nc                 C   rD  r   )_exists)r#   rz   r$   r$   r%   r&   ?  rG  zExistsOption.__init__c                 C   rH  r   )r*   r	  r+   rO  r,   r$   r$   r%   r.   B  rI  zExistsOption.__eq__c                 K   rJ  )aB  Modify a ``Write`` protobuf based on the state of this write option.

        If:

        * ``exists=True``, adds a precondition that requires existence
        * ``exists=False``, adds a precondition that requires non-existence

        Args:
            write (google.cloud.firestore_v1.types.Write): A
                ``Write`` protobuf instance to be modified with a precondition
                determined by the state of this option.
            unused_kwargs (Dict[str, Any]): Keyword arguments accepted by
                other subclasses that are unused here.
        r   N)r
   r   rO  r   r   r   rK  r$   r$   r%   r-  G  s   zExistsOption.modify_writer1   rN  r$   r$   r$   r%   r,  4  s
    

r,  c                 C   s,   i }| t jjur| |d< |dur||d< |S )zCHelper fo API methods which take optional 'retry' / 'timeout' args.retryNtimeout)r   methodDEFAULT)rP  rQ  kwargsr$   r$   r%   make_retry_timeout_kwargsZ  s   rU  dtc                 C   s   t | pt S )z7Returns the supplied datetime (or "now") as a Timestamp)r   r   utcnow)rV  r$   r$   r%   build_timestampg  s   rX  ts1ts2c                 C   sh   t | ts	t| n| } t |tst|n|}| j| jd  }|j|jd  }||kr,dS ||kr2dS dS )Ng    eAr   r7   r   )r*   r   rX  nanosseconds)rY  rZ  	ts1_nanos	ts2_nanosr$   r$   r%   compare_timestampsn  s   r_  
serializedr   z+google.cloud.firestore_v1.client.BaseClientz-google.cloud.firestore_bundle.FirestoreBundlec                 C   s@  ddl m}m} dgg dg ddgddgd}|d	 }d
}d
}t| D ]i}t| }	t|	dkr6td|	d }
|
|vrHtd|
 d| z
|t	
|}W n tyk } z|jd dkretd|d
}~ww |d
u r|
dksvJ |||
 d }|}n|j|||
d ||
 }q$d|vrtd|j||dd |S )a  Inverse operation to a `FirestoreBundle` instance's `build()` method.

    Args:
        serialized (Union[str, bytes]): The result of `FirestoreBundle.build()`.
            Should be a list of dictionaries in string format.
        client (BaseClient): A connected Client instance.

    Returns:
        FirestoreBundle: A bundle equivalent to that which called `build()` and
            initially created the `serialized` value.

    Raises:
        ValueError: If any of the dictionaries in the list contain any more than
            one top-level key.
        ValueError: If any unexpected BundleElement types are encountered.
        ValueError: If the serialized bundle ends before expected.
    r   )BundleElementFirestoreBundlemetadata)
namedQuerydocumentMetadata__end__r   re  rf  )__initial__rc  rd  re  r   rg  Nr7   z8Expected serialized BundleElement with one top-level keyz"Encountered BundleElement of type z. Expected one of z%'dict' object has no attribute 'find'z[Invalid serialization of datetimes. Cannot deserialize Bundles created from the NodeJS SDK.r9  )r   r=   z,Unexpected end to serialized FirestoreBundle)google.cloud.firestore_bundlera  rb  _parse_bundle_elements_datara   keysr8   r9   	from_jsonjsondumpsAttributeErrorargs_add_bundle_element)r`  r   ra  rb  bundle_state_machineallowed_next_element_typesmetadata_bundle_elementbundledatarj  rp   bundle_elementer$   r$   r%   deserialize_bundle{  sZ   	
rx  c                 c   s    t t| tr	| n| d}d}	 t|d}|du rdS t|}| r*||7 }n1|dkr2tdt|}d}t	|g}d}||k rR|
t| |d7 }||k sCt|dV  q)a
  Reads through a serialized FirestoreBundle and yields JSON chunks that
    were created via `BundleElement.to_json(bundle_element)`.

    Serialized FirestoreBundle instances are length-prefixed JSON objects, and
    so are of the form "123{...}57{...}"
    To correctly and safely read a bundle, we must first detect these length
    prefixes, read that many bytes of data, and attempt to JSON-parse that.

    Raises:
        ValueError: If a chunk of JSON ever starts without following a length
            prefix.
    zutf-8 TNzExpected length prefixr7   )iterr*   r_   encodenextchr	isnumericr9   r[   	bytearrayr   rl  loadsdecode)r`  _serializedlength_prefixbyte_str_length_prefix_bytes_counterr$   r$   r%   ri    s0   


ri  )
query_namer  )'google.cloud.firestore.DocumentSnapshotNNc                c   s<    ddl m} | j D ]}|r||jjvrq|jV  qd S )Nr   )_BundledDocument)$google.cloud.firestore_bundle.bundler  r   rT   rc  queriesrt   )rt  r  r  bundled_docr$   r$   r%   _get_documents_from_bundle  s   
r  r   r  c                C   s   | j |}|r|jS d S r   )r   getrt   )rt  r   r  r$   r$   r%   _get_document_from_bundle  s   r  r1   r   )Tr   )ir5   r^   rl  google google.api_core.datetime_helpersr   google.api_corer   google.protobufr   google.typer   grpcgoogle.cloudr   google.cloud._helpersr   %google.cloud.firestore_v1.types.writer   google.cloud.firestore_v1r	   r
   $google.cloud.firestore_v1.field_pathr   r   ry   r   r   r   google.protobuf.timestamp_pb2r   typingr   r   r   r   r   r   r   r   r   Sentinel__annotations__rf   r;   r   r6  r8  r   r   r   ServerValueREQUEST_TIMEr   
StatusCodeALREADY_EXISTSConflict	NOT_FOUNDNotFoundr   objectr   rC   rX   rO   rg   r}   r~   r   rZ   r[   r\   ra   r:   r_   r   r   r   r   r   r   r   r   r   r   r  r  r%  r&  r0  r3  	Exceptionr4  r<  r>  r?  rC  r,  rU  rX  r_  rx  ri  r  r  r$   r$   r$   r%   <module>   s   ,




0%@4
5




 >}

&!(&



$a+
