a
    !f?                     @   s   d 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 dZdd ZdddZdddZG dd de	eZdS )z=Convenience wrapper for invoking APIs/factories w/ a project.    N)_LocalStack_determine_default_project)_ClientProjectMixin)Client)helpers)
ConnectionBatch)Entity)Key)QueryTransaction)GCD_DATASET   c                   C   s
   t tS )z2Gets the GCD application ID if it can be inferred.)osgetenvr    r   r   X/var/www/html/python-backend/venv/lib/python3.9/site-packages/gcloud/datastore/client.py_get_gcd_project$   s    r   c                 C   s$   | du rt  } | du r t| d} | S )aD  Determine default project explicitly or implicitly as fall-back.

    In implicit case, supports four environments. In order of precedence, the
    implicit environments are:

    * DATASTORE_DATASET environment variable (for ``gcd`` / emulator testing)
    * GCLOUD_PROJECT environment variable
    * Google App Engine application ID
    * Google Compute Engine project ID (from metadata server)

    :type project: string
    :param project: Optional. The project to use as default.

    :rtype: string or ``NoneType``
    :returns: Default project if it can be determined.
    Nproject)r   _base_default_projectr   r   r   r   r   )   s
    
r   Fc                 C   s   |dur|g krt d|dur0|g kr0t dg }d}|tk r|d7 }| j||||d\}	}
}||	 |dur|||
 |dur|| qt|dkrq|}q8|S )a  Repeat lookup until all keys found (unless stop requested).

    Helper function for :meth:`Client.get_multi`.

    :type connection: :class:`gcloud.datastore.connection.Connection`
    :param connection: The connection used to connect to datastore.

    :type project: string
    :param project: The project to make the request for.

    :type key_pbs: list of :class:`gcloud.datastore._generated.entity_pb2.Key`
    :param key_pbs: The keys to retrieve from the datastore.

    :type missing: list
    :param missing: (Optional) If a list is passed, the key-only entity
                    protobufs returned by the backend as "missing" will be
                    copied into it.

    :type deferred: list
    :param deferred: (Optional) If a list is passed, the key protobufs returned
                     by the backend as "deferred" will be copied into it.

    :type eventual: bool
    :param eventual: If False (the default), request ``STRONG`` read
                     consistency.  If True, request ``EVENTUAL`` read
                     consistency.

    :type transaction_id: string
    :param transaction_id: If passed, make the request in the scope of
                           the given transaction.  Incompatible with
                           ``eventual==True``.

    :rtype: list of :class:`gcloud.datastore._generated.entity_pb2.Entity`
    :returns: The requested entities.
    :raises: :class:`ValueError` if missing / deferred are not null or
             empty list.
    Nz%missing must be None or an empty listz&deferred must be None or an empty listr      )r   key_pbseventualtransaction_id)
ValueError
_MAX_LOOPSlookupextendlen)
connectionr   r   missingdeferredr   r   resultsZloop_numZresults_foundZmissing_foundZdeferred_foundr   r   r   _extended_lookupC   s0    (


r'   c                       s   e Zd ZdZeZd% fdd	Zedd Zdd Z	d	d
 Z
edd Zedd Zd&ddZ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d#d$ Z  ZS )(r   a  Convenience wrapper for invoking APIs/factories w/ a project.

    :type project: string
    :param project: (optional) The project to pass to proxied API methods.

    :type namespace: string
    :param namespace: (optional) namespace to pass to proxied API methods.

    :type credentials: :class:`oauth2client.client.OAuth2Credentials` or
                       :class:`NoneType`
    :param credentials: The OAuth2 Credentials to use for the connection
                        owned by this client. If not passed (and if no ``http``
                        object is passed), falls back to the default inferred
                        from the environment.

    :type http: :class:`httplib2.Http` or class that defines ``request()``.
    :param http: An optional HTTP object to make requests. If not passed, an
                 ``http`` object is created that is bound to the
                 ``credentials`` for the current object.
    Nc                    s2   t j| |d || _t | _tt| || d S )Nr   )r   __init__	namespacer   _batch_stacksuperr   )selfr   r)   credentialshttp	__class__r   r   r(      s    zClient.__init__c                 C   s   t | S )z,Helper:  override default project detection.r   r   r   r   r   _determine_default   s    zClient._determine_defaultc                 C   s   | j | dS )a(  Push a batch/transaction onto our stack.

        "Protected", intended for use by batch / transaction context mgrs.

        :type batch: :class:`gcloud.datastore.batch.Batch`, or an object
                     implementing its API.
        :param batch: newly-active batch/transaction.
        N)r*   push)r,   batchr   r   r   _push_batch   s    	zClient._push_batchc                 C   s
   | j  S )a`  Pop a batch/transaction from our stack.

        "Protected", intended for use by batch / transaction context mgrs.

        :raises: IndexError if the stack is empty.
        :rtype: :class:`gcloud.datastore.batch.Batch`, or an object
                 implementing its API.
        :returns: the top-most batch/transaction, after removing it.
        )r*   popr,   r   r   r   
_pop_batch   s    
zClient._pop_batchc                 C   s   | j jS )zCurrently-active batch.

        :rtype: :class:`gcloud.datastore.batch.Batch`, or an object
                implementing its API, or ``NoneType`` (if no batch is active).
        :returns: The batch/transaction at the top of the batch stack.
        )r*   topr6   r   r   r   current_batch   s    zClient.current_batchc                 C   s   | j }t|tr|S dS )a  Currently-active transaction.

        :rtype: :class:`gcloud.datastore.transaction.Transaction`, or an object
                implementing its API, or ``NoneType`` (if no transaction is
                active).
        :returns: The transaction at the top of the batch stack.
        N)r9   
isinstancer   )r,   transactionr   r   r   current_transaction   s    	
zClient.current_transactionc                 C   s$   | j |g|||d}|r |d S dS )a{  Retrieve an entity from a single key (if it exists).

        .. note::

           This is just a thin wrapper over :meth:`get_multi`.
           The backend API does not make a distinction between a single key or
           multiple keys in a lookup request.

        :type key: :class:`gcloud.datastore.key.Key`
        :param key: The key to be retrieved from the datastore.

        :type missing: list
        :param missing: (Optional) If a list is passed, the key-only entities
                        returned by the backend as "missing" will be copied
                        into it.

        :type deferred: list
        :param deferred: (Optional) If a list is passed, the keys returned
                         by the backend as "deferred" will be copied into it.

        :type transaction: :class:`gcloud.datastore.transaction.Transaction`
        :param transaction: (Optional) Transaction to use for read consistency.
                            If not passed, uses current transaction, if set.

        :rtype: :class:`gcloud.datastore.entity.Entity` or ``NoneType``
        :returns: The requested entity if it exists.
        )keysr$   r%   r;   r   N)	get_multi)r,   keyr$   r%   r;   entitiesr   r   r   get   s
    
z
Client.getc                 C   s   |sg S t dd |D }|D ]}|| jkrtdq|du rD| j}t| j| jdd |D |||of|jd}|durdd |D |dd< |durd	d |D |dd< d
d |D S )a  Retrieve entities, along with their attributes.

        :type keys: list of :class:`gcloud.datastore.key.Key`
        :param keys: The keys to be retrieved from the datastore.

        :type missing: list
        :param missing: (Optional) If a list is passed, the key-only entities
                        returned by the backend as "missing" will be copied
                        into it. If the list is not empty, an error will occur.

        :type deferred: list
        :param deferred: (Optional) If a list is passed, the keys returned
                         by the backend as "deferred" will be copied into it.
                         If the list is not empty, an error will occur.

        :type transaction: :class:`gcloud.datastore.transaction.Transaction`
        :param transaction: (Optional) Transaction to use for read consistency.
                            If not passed, uses current transaction, if set.

        :rtype: list of :class:`gcloud.datastore.entity.Entity`
        :returns: The requested entities.
        :raises: :class:`ValueError` if one or more of ``keys`` has a project
                 which does not match our project.
        c                 s   s   | ]}|j V  qd S )Nr   ).0r?   r   r   r   	<genexpr>      z#Client.get_multi.<locals>.<genexpr>zKeys do not match projectNc                 S   s   g | ]}|  qS r   )to_protobuf)rB   kr   r   r   
<listcomp>*  rD   z$Client.get_multi.<locals>.<listcomp>)r#   r   r   r$   r%   r   c                 S   s   g | ]}t |qS r   r   Zentity_from_protobuf)rB   Z	missed_pbr   r   r   rG   1  s   c                 S   s   g | ]}t |qS r   )r   Zkey_from_protobuf)rB   Zdeferred_pbr   r   r   rG   6  s   c                 S   s   g | ]}t |qS r   rH   )rB   Z	entity_pbr   r   r   rG   :  s   )setr   r   r<   r'   r#   id)r,   r=   r$   r%   r;   ZidsZ
current_idZ
entity_pbsr   r   r   r>     s6    

	zClient.get_multic                 C   s   | j |gd dS )a  Save an entity in the Cloud Datastore.

        .. note::

           This is just a thin wrapper over :meth:`put_multi`.
           The backend API does not make a distinction between a single
           entity or multiple entities in a commit request.

        :type entity: :class:`gcloud.datastore.entity.Entity`
        :param entity: The entity to be saved to the datastore.
        )r@   N)	put_multi)r,   entityr   r   r   put=  s    z
Client.putc                 C   sX   t |trtd|sdS | j}|du}|s4|  }|D ]}|| q8|sT|  dS )a  Save entities in the Cloud Datastore.

        :type entities: list of :class:`gcloud.datastore.entity.Entity`
        :param entities: The entities to be saved to the datastore.

        :raises: :class:`ValueError` if ``entities`` is a single entity.
        zPass a sequence of entitiesN)r:   r   r   r9   r3   rM   commit)r,   r@   currentin_batchrL   r   r   r   rK   K  s    
zClient.put_multic                 C   s   | j |gd dS )av  Delete the key in the Cloud Datastore.

        .. note::

           This is just a thin wrapper over :meth:`delete_multi`.
           The backend API does not make a distinction between a single key or
           multiple keys in a commit request.

        :type key: :class:`gcloud.datastore.key.Key`
        :param key: The key to be deleted from the datastore.
        )r=   N)delete_multi)r,   r?   r   r   r   deletee  s    zClient.deletec                 C   sF   |sdS | j }|du}|s"|  }|D ]}|| q&|sB|  dS )zDelete keys from the Cloud Datastore.

        :type keys: list of :class:`gcloud.datastore.key.Key`
        :param keys: The keys to be deleted from the datastore.
        N)r9   r3   rR   rN   )r,   r=   rO   rP   r?   r   r   r   rQ   s  s    zClient.delete_multic                    sX    j std f  }|g| }| j}| j|}dd |D } fdd|D S )a  Allocate a list of IDs from a partial key.

        :type incomplete_key: :class:`gcloud.datastore.key.Key`
        :param incomplete_key: Partial key to use as base for allocated IDs.

        :type num_ids: int
        :param num_ids: The number of IDs to allocate.

        :rtype: list of :class:`gcloud.datastore.key.Key`
        :returns: The (complete) keys allocated with ``incomplete_key`` as
                  root.
        :raises: :class:`ValueError` if ``incomplete_key`` is not a
                 partial key.
        zKey is not partial.c                 S   s   g | ]}|j d  jqS ))pathrJ   )rB   Zallocated_key_pbr   r   r   rG     s   z'Client.allocate_ids.<locals>.<listcomp>c                    s   g | ]}  |qS r   )Zcompleted_key)rB   Zallocated_idincomplete_keyr   r   rG     s   )Z
is_partialr   rE   r#   allocate_idsr   )r,   rV   Znum_idsZincomplete_key_pbZincomplete_key_pbsconnZallocated_key_pbsZallocated_idsr   rU   r   rW     s    

zClient.allocate_idsc                 O   s:   d|v rt d| j|d< d|vr,| j|d< t|i |S )zUProxy to :class:`gcloud.datastore.key.Key`.

        Passes our ``project``.
        r   Cannot pass projectr)   )	TypeErrorr   r)   r   )r,   Z	path_argskwargsr   r   r   r?     s    

z
Client.keyc                 C   s   t | S )z/Proxy to :class:`gcloud.datastore.batch.Batch`.r	   r6   r   r   r   r3     s    zClient.batchc                 C   s   t | S )z;Proxy to :class:`gcloud.datastore.transaction.Transaction`.r   r6   r   r   r   r;     s    zClient.transactionc                 K   sL   d|v rt dd|v r t d| j|d< d|vr<| j|d< t| fi |S )zYProxy to :class:`gcloud.datastore.query.Query`.

        Passes our ``project``.
        clientzCannot pass clientr   rY   r)   )rZ   r   r)   r   )r,   r[   r   r   r   query  s    

zClient.query)NNNN)NNN)NNN)__name__
__module____qualname____doc__r   Z_connection_classr(   staticmethodr1   r4   r7   propertyr9   r<   rA   r>   rM   rK   rR   rQ   rW   r?   r3   r;   r]   __classcell__r   r   r/   r   r      s0     

	

!
:r   )N)NNFN)ra   r   Zgcloud._helpersr   r   r   Zgcloud.clientr   r   Z_BaseClientZgcloud.datastorer   Zgcloud.datastore.connectionr   Zgcloud.datastore.batchr
   Zgcloud.datastore.entityr   Zgcloud.datastore.keyr   Zgcloud.datastore.queryr   Zgcloud.datastore.transactionr   Zgcloud.environment_varsr   r   r   r'   r   r   r   r   <module>   s(   
  
N