U
    
ڲg'K                     @  sb  d Z ddlmZ ddlmZmZ ddlmZ ddlZddlZddl	m
Z
 ddlmZmZmZ ddlmZ dd	lm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ZddgZdZde ZdZddejdZ dZ!ddddZ"d*dddddd dZ#G d!d dZ$G d"d dZ%G d#d$ d$Z&eG d%d dZ'eG d&d' d'Z(eG d(d) d)Z)dS )+zFirebase Functions module.    )annotations)datetime	timedelta)parseN)	b64encode)AnyOptionalDict)	dataclass)Credentials)App)_http_client)_utilsZ
_functionsTaskOptions
task_queuezHprojects/{project_id}/locations/{location_id}/queues/{resource_id}/tasksz%https://cloudtasks.googleapis.com/v2/zChttps://{location_id}-{project_id}.cloudfunctions.net/{resource_id}2zfire-admin-python/{0})zX-GOOG-API-FORMAT-VERSIONzX-FIREBASE-CLIENTzus-central1_FunctionsService)returnc                 C  s   t | ttS )N)r   Zget_app_service_FUNCTIONS_ATTRIBUTEr   app r   </tmp/pip-unpacked-wheel-p0r7i5ii/firebase_admin/functions.py_get_functions_service9   s    r   strOptional[str]zOptional[App]	TaskQueue)function_nameextension_idr   r   c                 C  s   t || |S )am  Creates a reference to a TaskQueue for a given function name.

    The function name can be either:
        1. A fully qualified function resource name:
            `projects/{project-id}/locations/{location-id}/functions/{function-name}`

        2. A partial resource name with location and function name, in which case
            the runtime project ID is used:
            `locations/{location-id}/functions/{function-name}`

        3. A partial function name, in which case the runtime project ID and the
            default location, `us-central1`, is used:
            `{function-name}`

    Args:
        function_name: Name of the function.
        extension_id: Firebase extension ID (optional).
        app: An App instance (optional).

    Returns:
        TaskQueue: A TaskQueue instance.

    Raises:
        ValueError: If the input arguments are invalid.
    )r   r   )r   r   r   r   r   r   r   <   s    c                   @  sD   e Zd ZdZddddZdddd	d
ddZeddddZdS )r   z?Service class that implements Firebase Functions functionality.r   r   c                 C  s6   |j | _| jstd|j | _tj| jd| _d S )NzProject ID is required to access the Cloud Functions service. Either set the projectId option, or use service account credentials. Alternatively, set the GOOGLE_CLOUD_PROJECT environment variable.)
credential)
project_id_project_id
ValueErrorr   get_credential_credentialr   ZJsonHttpClient)selfr   r   r   r   __init__^   s    z_FunctionsService.__init__Nr   r   r   r   r   r   c                 C  s   t ||| j| j| jS )zCreates a TaskQueue instance.)r   r!   r$   r   )r%   r   r   r   r   r   r   i   s        z_FunctionsService.task_queuer   )errorc                 C  s
   t |S )z5Handles errors received from the Cloud Functions API.)r   Z#handle_platform_error_from_requests)clsr(   r   r   r   handle_functions_errorn   s    z(_FunctionsService.handle_functions_error)N)__name__
__module____qualname____doc__r&   r   classmethodr*   r   r   r   r   r   \   s
   c                   @  s   e Zd ZdZddddddZdd	d
ddddZdddddZddddddZddddddZd d	dd
ddddZ	dddddddZ
dS )!r   zJTaskQueue class that implements Firebase Cloud Tasks Queues functionality.r   r   Noner'   c                 C  s   t d| || _|| _|| _|| _|| _| | jd| _| jj	pF| j| j_	| jj
pVt| j_
t d| jj | jd k	rt d| j d| j d| jj | j_d S )Nr   Z	functionszresource.resource_idr   zext--)_Validatorscheck_non_empty_stringr!   r$   r   Z_function_name_extension_id_parse_resource_name	_resourcer    location_id_DEFAULT_LOCATIONresource_id)r%   r   r   r    r   http_clientr   r   r   r&   v   s    

zTaskQueue.__init__Nr   zOptional[TaskOptions])	task_dataoptsr   c           
   
   C  s   |  || j|}| | jt}| || j| j}zF| jjd|td|j	id}|
dd}| |d| jj d}|jW S  tjjk
r }	 zt|	W 5 d}	~	X Y nX dS )a\  Creates a task and adds it to the queue. Tasks cannot be updated after creation.

        This action requires `cloudtasks.tasks.create` IAM permission on the service account.

        Args:
            task_data: The data payload of the task.
            opts: Options when enqueuing a new task (optional).

        Raises:
            FirebaseError: If an error occurs while requesting the task to be queued by
                the Cloud Functions service.
            ValueError: If the input arguments are invalid.

        Returns:
            str: The ID of the task relative to this queue.
        posttask)urlheadersjsonnameNzqueues/z/tasks)_validate_task_optionsr6   _get_url_CLOUD_TASKS_API_URL_FORMAT_update_task_payloadr4   r   body_FUNCTIONS_HEADERS__dict__getr5   r9   requests
exceptionsRequestExceptionr   r*   )
r%   r;   r<   r>   service_urlZtask_payloadrespZ	task_nameZtask_resourcer(   r   r   r   enqueue   s     zTaskQueue.enqueue)task_idr   c              
   C  sp   t d| | | jtd|  }z| jjd|td W n0 tj	j
k
rj } zt|W 5 d}~X Y nX dS )a  Deletes an enqueued task if it has not yet started.

        This action requires `cloudtasks.tasks.delete` IAM permission on the service account.

        Args:
            task_id: The ID of the task relative to this queue.

        Raises:
            FirebaseError: If an error occurs while requesting the task to be deleted by
                the Cloud Functions service.
            ValueError: If the input arguments are invalid.
        rQ   /delete)r?   r@   N)r2   r3   rD   r6   rE   r   rG   rH   rK   rL   rM   r   r*   )r%   rQ   rN   r(   r   r   r   rS      s    
zTaskQueue.deleteResource)resource_nameresource_id_keyr   c                 C  sT   d|krt |dS d| d}t||}|dkr:tdt |d |d |d	 d
S )z;Parses a full or partial resource path into a ``Resource``.rR   )r9   z'^(projects/([^/]+)/)?locations/([^/]+)/z	/([^/]+)$NzInvalid resource name format.         r    r7   r9   )rT   researchr"   )r%   rU   rV   regmatchr   r   r   r5      s    
zTaskQueue._parse_resource_name)resource
url_formatr   c                 C  s   |j |j|j|jdS )z=Generates url path from a ``Resource`` and url format string.rZ   )formatr    r7   r9   )r%   r_   r`   r   r   r   rD      s
    zTaskQueue._get_urlTask)datar_   r<   r   c                 C  s  dddit t|  ddid}t|d}|dk	r|jdk	r\|jd |j|jd< |jdk	rx|j	dk	rxt
d	|jdk	r|j	dkrt|jtst
d
|jd|_|j	dk	r|jdkrt|j	tr|j	dk rt
dt t|j	d }|d|_|jdk	rLt|jtr6|jdk s6|jdkr>t
d|j d|_|jdk	rt|jsnt
d| |td|j  |_|jdk	rt|jst
d|j|jd< |S )z9Validate and create a Task from optional ``TaskOptions``. service_account_emailzContent-Typezapplication/json)r?   
oidc_tokenrG   r@   )http_requestNr@   zMBoth sechdule_delay_seconds and schedule_time cannot be set at the same time.z%schedule_time should be UTC datetime.z%Y-%m-%dT%H:%M:%S.%fZr   z.schedule_delay_seconds should be positive int.)seconds   i  zOdispatch_deadline_seconds should be int in the range of 15s to 1800s (30 mins).sztask_id can contain only letters ([A-Za-z]), numbers ([0-9]), hyphens (-), or underscores (_). The maximum length is 500 characters.rR   zFuri must be a valid RFC3986 URI string using the https or http schema.r?   )r   rA   dumpsencodedecoderb   r@   rg   schedule_timeschedule_delay_secondsr"   
isinstancer   strftimeintutcnowr   dispatch_deadline_secondsdispatch_deadlinerQ   r2   
is_task_idrD   _CLOUD_TASKS_API_RESOURCE_PATHrB   uriis_url)r%   rc   r_   r<   Ztask_http_requestr>   rn   r   r   r   rC      sl      



 z TaskQueue._validate_task_options)r>   r_   r   r   c                 C  s~   t |jd s"| |t|jd< t |rht| jtrh| jj}|jd dd| i|jd< |jd= nd| jj	i|jd< |S )z*Prepares task to be sent with credentials.r?   r@   AuthorizationzBearer $rf   re   )
r2   is_non_empty_stringrg   rD   _FIREBASE_FUNCTION_URL_FORMATrp   r$   ComputeEngineCredentialstokenre   )r%   r>   r_   r   Zid_tokenr   r   r   rF     s    



zTaskQueue._update_task_payload)N)N)r+   r,   r-   r.   r&   rP   rS   r5   rD   rC   rF   r   r   r   r   r   t   s   " 9c                   @  sZ   e Zd ZdZedddddZedddd	Zedd
ddZeddddZdS )r2   z*A collection of data validation utilities.r   r   )labelvaluec                 C  s6   t |tstd|||dkr2td||dS )zDChecks if given value is a non-empty string and throws error if not.z{0} "{1}" must be a string.rd   z%{0} "{1}" must be a non-empty string.N)rp   r   r"   ra   )r)   r   r   r   r   r   r3   1  s    
z"_Validators.check_non_empty_string)r   c                 C  s   t |tr|dkrdS dS )z=Checks if given value is a non-empty string and returns bool.rd   FT)rp   r   )r)   r   r   r   r   r{   9  s    z_Validators.is_non_empty_string)rQ   c                 C  s(   d}t ||dk	r$t|dkr$dS dS )z)Checks if given value is a valid task id.z^[A-Za-z0-9_-]+$Ni  TF)r[   r^   len)r)   rQ   r]   r   r   r   rv   @  s    z_Validators.is_task_id)r?   c                 C  sP   t |tsdS z&t|}|jr*|jdkr0W dS W dS  tk
rJ   Y dS X dS )z%Checks if given value is a valid url.F)httphttpsTN)rp   r   r   urlparsenetlocscheme	Exception)r)   r?   parsedr   r   r   ry   H  s    

z_Validators.is_urlN)	r+   r,   r-   r.   r/   r3   r{   rv   ry   r   r   r   r   r2   /  s   r2   c                   @  sZ   e Zd ZU dZdZded< dZded< dZded< dZded	< dZ	d
ed< dZ
ded< dS )r   aD  Task Options that can be applied to a Task.

    Args:
        schedule_delay_seconds: The number of seconds after the current time at which to attempt or
            retry the task. Should only be set if ``schedule_time`` is not set.

        schedule_time: The time when the task is scheduled to be attempted or retried. Should only
            be set if ``schedule_delay_seconds`` is not set.

        dispatch_deadline_seconds: The deadline for requests sent to the worker. If the worker does
            not respond by this deadline then the request is cancelled and the attempt is marked as
            a ``DEADLINE_EXCEEDED`` failure. Cloud Tasks will retry the task according to the
            ``RetryConfig``. The default is 10 minutes. The deadline must be in the range of 15
            seconds and 30 minutes (1800 seconds).

        task_id: The ID to use for the enqueued task. If not provided, one will be automatically
            generated.

            If provided, an explicitly specified task ID enables task de-duplication.
            Task IDs should be strings that contain only letters ([A-Za-z]), numbers ([0-9]),
            hyphens (-), and underscores (_) with a maximum length of 500 characters. If a task's
            ID is identical to that of an existing task or a task that was deleted or executed
            recently then the call will throw an error with code `functions/task-already-exists`.
            Another task with the same ID can't be created for ~1hour after the original task was
            deleted or executed.

            Because there is an extra lookup cost to identify duplicate task IDs, setting ID
            significantly increases latency.

            Also, note that the infrastructure relies on an approximately uniform distribution
            of task IDs to store and serve tasks efficiently. For this reason, using hashed strings
            for the task ID or for the prefix of the task ID is recommended. Choosing task IDs that
            are sequential or have sequential prefixes, for example using a timestamp, causes an
            increase in latency and error rates in all task commands.

            Push IDs from the Firebase Realtime Database make poor IDs because they are based on
            timestamps and will cause contention (slowdowns) in your task queue. Reversed push IDs
            however form a perfect distribution and are an ideal key. To reverse a string in Python
            use ``reversedString = someString[::-1]``

        headers: HTTP request headers to include in the request to the task queue function. These
            headers represent a subset of the headers that will accompany the task's HTTP request.
            Some HTTP request headers will be ignored or replaced: `Authorization`, `Host`,
            `Content-Length`, `User-Agent` and others cannot be overridden.

            A complete list of these ignored or replaced headers can be found in the following
            definition of the HttpRequest.headers property:
            https://cloud.google.com/tasks/docs/reference/rest/v2/projects.locations.queues.tasks#httprequest

            By default, Content-Type is set to 'application/json'.

            The size of the headers must be less than 80KB.

        uri: The full URL that the request will be sent to. Must be a valid RFC3986 https or
            http URL.
    NzOptional[int]ro   zOptional[datetime]rn   rt   r   rQ   zOptional[Dict[str, str]]r@   rx   )r+   r,   r-   r.   ro   __annotations__rn   rt   rQ   r@   rx   r   r   r   r   r   V  s   
8c                   @  s>   e Zd ZU dZded< dZded< dZded< dZded< dS )	rb   a  Contains the relevant fields for enqueueing tasks that trigger Cloud Functions.

    This is a limited subset of the Cloud Functions `Task` resource. See the following
    page for definitions of this class's properties:
    https://cloud.google.com/tasks/docs/reference/rest/v2/projects.locations.queues.tasks#resource:-task

    Args:
        httpRequest: The request to be made by the task worker.
        name: The name of the function. See the Cloud docs for the format of this property.
        schedule_time: The time when the task is scheduled to be attempted or retried.
        dispatch_deadline: The deadline for requests sent to the worker.
    zDict[str, Optional[str | dict]]rg   Nr   rB   rn   ru   )r+   r,   r-   r.   r   rB   rn   ru   r   r   r   r   rb     s
   
rb   c                   @  s2   e Zd ZU dZded< dZded< dZded< dS )rT   zContains the parsed address of a resource.

    Args:
        resource_id: The ID of the resource.
        project_id: The project ID of the resource.
        location_id: The location ID of the resource.
    r   r9   Nr   r    r7   )r+   r,   r-   r.   r   r    r7   r   r   r   r   rT     s   
rT   )NN)*r.   
__future__r   r   r   urllibr   r[   rA   base64r   typingr   r   r	   Zdataclassesr
   Zgoogle.auth.compute_enginer   r}   rK   Zfirebase_adminr   r   r   r   __all__rw   rE   r|   ra   __version__rH   r8   r   r   r   r   r2   r   rb   rT   r   r   r   r   <module>   sT   
    <'@