Ë
    rPêjœ=  ã                   ój  — 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	m
Z
mZ ddlmZmZmZ e	rddlZddlmama dd	lma daed
   ed<   ej2                  j5                  d«      du Ze G d„ d
«      «       Zeddedz  defd„«       Zdefd„Zdd„Z dedz  ddfd„Z!dededefd„Z"dededefd„Z#y)zSContains `WebhooksServer` and `webhook_endpoint` to create a webhook server easily.é    N)ÚCallable)Úwraps)ÚTYPE_CHECKINGÚAnyÚOptionalé   )ÚexperimentalÚis_fastapi_availableÚis_gradio_available©ÚFastAPIÚRequest©ÚJSONResponseÚWebhooksServerÚ_global_appÚSPACE_IDc                   ó€   ‡ — e Zd ZdZdˆ fd„Z	 	 dded   dedz  ddfd„Zdd	edz  defd
„Z	dde
deddfd„Zdd„Zˆ xZS )r   a  
    The [`WebhooksServer`] class lets you create an instance of a Gradio app that can receive Huggingface webhooks.
    These webhooks can be registered using the [`~WebhooksServer.add_webhook`] decorator. Webhook endpoints are added to
    the app as a POST endpoint to the FastAPI router. Once all the webhooks are registered, the `launch` method has to be
    called to start the app.

    It is recommended to accept [`WebhookPayload`] as the first argument of the webhook function. It is a Pydantic
    model that contains all the information about the webhook event. The data will be parsed automatically for you.

    Check out the [webhooks guide](../guides/webhooks_server) for a step-by-step tutorial on how to set up your
    WebhooksServer and deploy it on a Space.

    > [!WARNING]
    > `WebhooksServer` is experimental. Its API is subject to change in the future.

    > [!WARNING]
    > You must have `gradio` installed to use `WebhooksServer` (`pip install --upgrade gradio`).

    Args:
        ui (`gradio.Blocks`, optional):
            A Gradio UI instance to be used as the Space landing page. If `None`, a UI displaying instructions
            about the configured webhooks is created.
        webhook_secret (`str`, optional):
            A secret key to verify incoming webhook requests. You can set this value to any secret you want as long as
            you also configure it in your [webhooks settings panel](https://huggingface.co/settings/webhooks). You
            can also set this value as the `WEBHOOK_SECRET` environment variable. If no secret is provided, the
            webhook endpoints are opened without any security.

    Example:

        ```python
        import gradio as gr
        from huggingface_hub import WebhooksServer, WebhookPayload

        with gr.Blocks() as ui:
            ...

        app = WebhooksServer(ui=ui, webhook_secret="my_secret_key")

        @app.add_webhook("/say_hello")
        async def hello(payload: WebhookPayload):
            return {"message": "hello"}

        app.launch()
        ```
    Úreturnc                 óŠ   •— t        «       st        d«      ‚t        «       st        d«      ‚t        «        t        ‰| �  | «      S )NzjYou must have `gradio` installed to use `WebhooksServer`. Please run `pip install --upgrade gradio` first.zlYou must have `fastapi` installed to use `WebhooksServer`. Please run `pip install --upgrade fastapi` first.)r   ÚImportErrorr
   Ú_load_fastapiÚsuperÚ__new__)ÚclsÚargsÚkwargsÚ	__class__s      €úe/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/huggingface_hub/_webhooks_server.pyr   zWebhooksServer.__new__U   sK   ø€ Ü"Ô$Üðóð ô $Ô%Üðóð ô 	ŒÜ‰w‰˜sÓ#Ð#ó    NÚuiú	gr.BlocksÚwebhook_secretc                 ó†   — || _         |xs t        j                  d«      | _        i | _        t        | j                  «       y )NÚWEBHOOK_SECRET)Ú_uiÚosÚgetenvr#   Úregistered_webhooksÚ_warn_on_empty_secret)Úselfr!   r#   s      r   Ú__init__zWebhooksServer.__init__c   s8   € ð
 ˆŒà,ÒK´·	±	Ð:JÓ0KˆÔØ8:ˆÔ Ü˜d×1Ñ1Õ2r    Úpathc                 ó�   ‡ ‡— t        ‰«      r ‰ j                  «       ‰«      S t        t        j                  «      ˆˆ fd„«       }|S )ax  
        Decorator to add a webhook to the [`WebhooksServer`] server.

        Args:
            path (`str`, optional):
                The URL path to register the webhook function. If not provided, the function name will be used as the
                path. In any case, all webhooks are registered under `/webhooks`.

        Raises:
            ValueError: If the provided path is already registered as a webhook.

        Example:
            ```python
            from huggingface_hub import WebhooksServer, WebhookPayload

            app = WebhooksServer()

            @app.add_webhook
            async def trigger_training(payload: WebhookPayload):
                if payload.repo.type == "dataset" and payload.event.action == "update":
                    # Trigger a training job if a dataset is updated
                    ...

            app.launch()
        ```
        c                  ó¬   •— | d   }d‰xs |j                   j                  d«      › �}|‰j                  v rt        d|› d�«      ‚|‰j                  |<   y )Nr   z
/webhooks/ú/zWebhook z already exists.)Ú__name__Ústripr)   Ú
ValueError)r   r   ÚfuncÚabs_pathr-   r+   s       €€r   Ú_inner_postz/WebhooksServer.add_webhook.<locals>._inner_post�   s`   ø€ à˜‘7ˆDØ# TÒ%:¨T¯]©]×$AÑ$AÀ#Ó$FÐ#GÐHˆHØ˜4×3Ñ3Ñ3Ü  8¨H¨:Ð5EÐ!FÓGÐGØ15ˆD×$Ñ$ XÒ.r    )ÚcallableÚadd_webhookr   r   Úpost)r+   r-   r6   s   `` r   r8   zWebhooksServer.add_webhookn   sG   ù€ ô8 �DŒ>à%�4×#Ñ#Ó% dÓ+Ð+ô 
Œw�|‰|Ó	ô	6ó 
ð	6ð Ðr    Úprevent_thread_lockÚlaunch_kwargsc                 óÎ  ‡	— | j                   xs | j                  «       }|j                  dt        «        |j                  dddi|¤Ž\  | _        }}| j                  j                  «       D ]I  \  }}| j                  �t        || j                  ¬«      } | j
                  j                  |«      |«       ŒK t        j                  j                  d«      }|�d|z   n|j                  xs |j                  Š	‰	€t!        d«      ‚‰	j#                  d	«      Š	d
}|ddj%                  ˆ	fd„| j                  D «       «      z   z  }|dz  }t'        |«       |s|j)                  «        yy)z Launch the Gradio app and register webhooks to the underlying FastAPI server.

        Input parameters are forwarded to Gradio when launching the app.
        Úsharer:   TN©r#   Ú
SPACE_HOSTzhttps://zWCannot find the URL of the app. Please provide a valid `ui` or update `gradio` version.r0   z/
Webhooks are correctly setup and ready to use:ú
c              3   ó,   •K  — | ]  }d ‰› |› �–— Œ y­w)z	  - POST N© )Ú.0ÚwebhookÚurls     €r   ú	<genexpr>z(WebhooksServer.launch.<locals>.<genexpr>¶   s   øè ø€ Ò#gÀ7 i°¨u°W°IÔ$>Ñ#gùs   ƒzG
Go to https://huggingface.co/settings/webhooks to setup your webhooks.rB   )r&   Ú_get_default_uiÚ
setdefaultÚ	_is_localÚlaunchÚfastapi_appr)   Úitemsr#   Ú_wrap_webhook_to_check_secretr9   r'   ÚenvironÚgetÚ	share_urlÚ	local_urlr3   r2   ÚjoinÚprintÚblock_thread)
r+   r:   r;   r!   Ú_r-   r4   Ú
space_hostÚmessagerE   s
            @r   rJ   zWebhooksServer.launch™   sO  ø€ ð
 �X‰XÒ/˜×-Ñ-Ó/ˆð
 	× Ñ  ¬)Ô4Ø!* §¡Ñ!U¸tÐ!UÀ}Ñ!UÑˆÔ˜!˜Qð ×2Ñ2×8Ñ8Ó:ò 	.‰JˆD�$à×"Ñ"Ð.Ü4°TÈ$×J]ÑJ]Ô^�ð (ˆD×Ñ×!Ñ! $Ó'¨Õ-ð	.ô —Z‘Z—^‘^ LÓ1ˆ
Ø)3Ð)?ˆj˜:Ò%ÀbÇlÁlÒFbÐVX×VbÑVbˆØˆ;ÜÐvÓwÐwØ�i‰i˜‹nˆØDˆØ�4˜$Ÿ)™)Ó#gÈd×NfÑNfÔ#gÓgÑgÑgˆØÐ]Ñ]ˆÜˆgŒá"Ø�O‰OÕð #r    c           	      ó�  — ddl } |j                  «       5 } |j                  d«        |j                  d«        |j                  t        | j                  «      › d�dz   dj                  d„ | j                  j                  «       D «       «      z   «        |j                  t        rd	nd
«       ddd«       |S # 1 sw Y   S xY w)zLDefault UI if not provided (lists webhooks and provides basic instructions).r   Nu)   # This is an app to process ðŸ¤— WebhooksaT  Webhooks are a foundation for MLOps-related features. They allow you to listen for new changes on specific repos or to all repos belonging to particular set of users/organizations (not just your repos, but any repo). Check out this [guide](https://huggingface.co/docs/hub/webhooks) to get to know more about webhooks on the Huggingface Hub.z webhook(s) are registered:z

z
 c              3   ó\   K  — | ]$  \  }}d |› dt        |j                  |«      › d�–— Œ& y­w)z- [z](ú)N)Ú_get_webhook_doc_urlr1   )rC   Úwebhook_pathrD   s      r   rF   z1WebhooksServer._get_default_ui.<locals>.<genexpr>Ì   s<   è ø€ ò á-˜ gð ˜,˜ rÔ*>¸w×?OÑ?OÐQ]Ó*^Ð)_Ð_`Ôañùs   ‚*,z¡Go to https://huggingface.co/settings/webhooks to setup your webhooks.
You app is running locally. Please look at the logs to check the full URL you need to set.z¶
This app is running on a Space. You can find the corresponding URL in the options menu (top-right) > 'Embed the Space'. The URL looks like 'https://{username}-{repo_name}.hf.space'.)ÚgradioÚBlocksÚMarkdownÚlenr)   rR   rL   rI   )r+   Úgrr!   s      r   rG   zWebhooksServer._get_default_ui½   sÐ   € ãàˆR�Y‰Y‹[ð 	˜BØˆB�K‰KÐCÔDØˆB�K‰KðDôð ˆB�K‰KÜ�t×/Ñ/Ó0Ð1Ð1LÐMØñà—*‘*ñ à15×1IÑ1I×1OÑ1OÓ1Qôó ñôð ˆB�K‰Kõ ñqðvô÷!	ð2 ˆ	÷3	ð2 ˆ	ús   –BB;Â;C)r   r   )NN©N)F)r   r"   )r1   Ú
__module__Ú__qualname__Ú__doc__r   r   Ústrr,   r   r8   Úboolr   rJ   rG   Ú__classcell__)r   s   @r   r   r   $   sy   ø„ ñ-õ^$ð  %)Ø%)ñ	3à�[Ñ!ð	3ð ˜d™
ð	3ð 
ó		3ñ)  d¡
ð )°hó )ñV"¨$ð "Èð "ÐQUó "÷Hr    r-   r   c                 óš   ‡ — t        ‰ «      r t        «       ‰ «      S t        t        j                  «      dt
        dt
        fˆ fd„«       }|S )a§  Decorator to start a [`WebhooksServer`] and register the decorated function as a webhook endpoint.

    This is a helper to get started quickly. If you need more flexibility (custom landing page or webhook secret),
    you can use [`WebhooksServer`] directly. You can register multiple webhook endpoints (to the same server) by using
    this decorator multiple times.

    Check out the [webhooks guide](../guides/webhooks_server) for a step-by-step tutorial on how to set up your
    server and deploy it on a Space.

    > [!WARNING]
    > `webhook_endpoint` is experimental. Its API is subject to change in the future.

    > [!WARNING]
    > You must have `gradio` installed to use `webhook_endpoint` (`pip install --upgrade gradio`).

    Args:
        path (`str`, optional):
            The URL path to register the webhook function. If not provided, the function name will be used as the path.
            In any case, all webhooks are registered under `/webhooks`.

    Examples:
        The default usage is to register a function as a webhook endpoint. The function name will be used as the path.
        The server will be started automatically at exit (i.e. at the end of the script).

        ```python
        from huggingface_hub import webhook_endpoint, WebhookPayload

        @webhook_endpoint
        async def trigger_training(payload: WebhookPayload):
            if payload.repo.type == "dataset" and payload.event.action == "update":
                # Trigger a training job if a dataset is updated
                ...

        # Server is automatically started at the end of the script.
        ```

        Advanced usage: register a function as a webhook endpoint and start the server manually. This is useful if you
        are running it in a notebook.

        ```python
        from huggingface_hub import webhook_endpoint, WebhookPayload

        @webhook_endpoint
        async def trigger_training(payload: WebhookPayload):
            if payload.repo.type == "dataset" and payload.event.action == "update":
                # Trigger a training job if a dataset is updated
                ...

        # Start the server manually
        trigger_training.launch()
        ```
    r4   r   c                 ó  •‡— t        «       Š ‰j                  ‰«      | «       t        ‰j                  «      dk(  rt	        j
                  ‰j                  «       t        ‰j                  «      ˆfd„«       }|| _        | S )Nr   c                  ód   •— t        j                  ‰ j                  «       ‰ j                  «        y rb   )ÚatexitÚ
unregisterrJ   )Úapps   €r   Ú_launch_nowz5webhook_endpoint.<locals>._inner.<locals>._launch_now  s    ø€ ô ×Ñ˜cŸj™jÔ)Ø�J‰J�Lr    )Ú_get_global_appr8   r`   r)   rl   ÚregisterrJ   r   )r4   ro   rn   r-   s     @€r   Ú_innerz webhook_endpoint.<locals>._inner  sj   ù€ äÓˆØˆ�‰˜Ó˜dÔ#Üˆs×&Ñ&Ó'¨1Ò,ä�O‰O˜CŸJ™JÔ'ä	ˆs�z‰zÓ	ó	ó 
ð	ð
 "ˆŒØˆr    )r7   Úwebhook_endpointr   r   r8   r   )r-   rr   s   ` r   rs   rs   Ý   sP   ø€ ôl �„~à!ÔÓ! $Ó'Ð'ä
Œ>×%Ñ%Ó&ð”Xð ¤(ô ó 'ðð  €Mr    c                  ó.   — t         €
t        «       a t         S rb   )r   r   rB   r    r   rp   rp   +  s   € äÐÜ$Ó&ˆÜÐr    c                  ó    — ddl mama ddlma y )Nr   r   r   )Úfastapir   r   Úfastapi.responsesr   rB   r    r   r   r   2  s
   € ÷ )Þ.r    r#   c                 ób   — | €"t        d«       t        d«       t        d«       y t        d«       y )NzZWebhook secret is not defined. This means your webhook endpoints will be open to everyone.z•To add a secret, set `WEBHOOK_SECRET` as environment variable or pass it at initialization: 
	`app = WebhooksServer(webhook_secret='my_secret', ...)`zpFor more details about webhook secrets, please refer to https://huggingface.co/docs/hub/webhooks#webhook-secret.z$Webhook secret is correctly defined.)rS   r>   s    r   r*   r*   9  s:   € ØÐÜÐjÔkÜðJô	
ô 	ðHõ	
ô
 	Ð4Õ5r    Úwebhook_namer\   c                 ó8   — d| z   |j                  dd«      z   dz   S )z@Returns the anchor to a given webhook in the docs (experimental)z/docs#/default/r0   rU   Ú_post)Úreplace)ry   r\   s     r   r[   r[   H  s$   € à˜|Ñ+¨l×.BÑ.BÀ3ÈÓ.LÑLÈwÑVÐVr    r4   c                 óf  ‡ ‡‡— t        j                  ‰ «      Št        ‰ «      dt        fˆ ˆˆfd„«       }d‰j                  vrn‰j                  t        j                  dt         j                  j                  t        ¬«      ft        ‰j                  j                  «       «      z   ¬«      |_
        |S )a²  Wraps a webhook function to check the webhook secret before calling the function.

    This is a hacky way to add the `request` parameter to the function signature. Since FastAPI based itself on route
    parameters to inject the values to the function, we need to hack the function signature to retrieve the `Request`
    object (and hence the headers). A far cleaner solution would be to use a middleware. However, since
    `fastapi==0.90.1`, a middleware cannot be added once the app has started. And since the FastAPI app is started by
    Gradio internals (and not by us), we cannot add a middleware.

    This method is called only when a secret has been defined by the user. If a request is sent without the
    "x-webhook-secret", the function will return a 401 error (unauthorized). If the header is sent but is incorrect,
    the function will return a 403 error (forbidden).

    Inspired by https://stackoverflow.com/a/33112180.
    Úrequestc              ›   ó  •K  — | j                   j                  d«      }|€t        ddid¬«      S |‰k7  rt        ddid¬«      S d‰j                  v r| |d<   t	        j
                  ‰«      r ‰d	i |¤Žƒ d {  –—† S  ‰d	i |¤ŽS 7 Œ­w)
Nzx-webhook-secretÚerrorz x-webhook-secret header not set.i‘  )Ústatus_codezInvalid webhook secret.i“  r~   rB   )ÚheadersrO   r   Ú
parametersÚinspectÚiscoroutinefunction)r~   r   Úrequest_secretr4   Úinitial_sigr#   s      €€€r   Ú_protected_funcz6_wrap_webhook_to_check_secret.<locals>._protected_func^  sœ   øè ø€ à Ÿ™×,Ñ,Ð-?Ó@ˆØÐ!Ü Ð*LÐ MÐ[^Ô_Ð_Ø˜^Ò+Ü Ð*CÐ DÐRUÔVÐVð ˜×.Ñ.Ñ.Ø 'ˆF�9Ñô ×&Ñ& tÔ,Ù™ ™×'Ð'á‘>˜&‘>Ð!ð (ús   ƒA4BÁ7BÁ8B)ÚnameÚkindÚ
annotation)rƒ   )r„   Ú	signaturer   r   rƒ   r|   Ú	ParameterÚPOSITIONAL_OR_KEYWORDÚtupleÚvaluesÚ__signature__)r4   r#   rˆ   r‡   s   `` @r   rM   rM   M  s¤   ú€ ô ×#Ñ# DÓ)€Kä
ˆ4ƒ[ð"¤wö "ó ð"ð$ ˜×.Ñ.Ñ.Ø(3×(;Ñ(;ä×!Ñ! y´w×7HÑ7H×7^Ñ7^ÔkrÔsðô �K×*Ñ*×1Ñ1Ó3Ó4ñ5ð )<ó )
ˆÔ%ð Ðr    rb   )r   N)$re   rl   r„   r'   Úcollections.abcr   Ú	functoolsr   Útypingr   r   r   Úutilsr	   r
   r   r]   ra   rv   r   r   rw   r   r   Ú__annotations__rN   rO   rI   r   rf   rs   rp   r   r*   r[   rM   rB   r    r   ú<module>r—      s  ðò Zã Û Û 	Ý $Ý ß /Ñ /ç JÑ Jñ Ûß(Ý.ð +/€ˆXÐ&Ñ'Ó .Ø�J‰J�N‰N˜:Ó&¨$Ð.€	ð ÷uð uó ðuðp ñJ˜3 ™:ð J°ò Jó ðJðZ˜ó ó/ð6¨#°©*ð 6¸ó 6ðW sð W¸#ð WÀ#ó Wð
-¨ð -À#ð -È(ô -r    