wL i8=UdZddlZddlZddlZddlmZddlmZmZm Z m Z m Z ddl m Z mZmZer ddlZddlmZerddlmZmZdd lmZndxZxZZdae d ed <ej2j5d duZe Gd d Ze dde ede fdZdefdZde eddfdZ dededefdZ!de dede fdZ"y)zSContains `WebhooksServer` and `webhook_endpoint` to create a webhook server easily.N)wraps) TYPE_CHECKINGAnyCallableDictOptional) experimentalis_fastapi_availableis_gradio_available)Request)FastAPIr ) JSONResponseWebhooksServer _global_appSPACE_IDceZdZdZdfd Z ddeddeeddfdZdd eedefd Z dd e d e ddfd Z ddZ xZS)ra 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 setup 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() ``` returncvts tdts tdt||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 super__new__)clsargskwargs __class__s f/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/huggingface_hub/_webhooks_server.pyrzWebhooksServer.__new__[sF"$ $% ws##Nui gr.Blockswebhook_secretc||_|xstjd|_i|_t |jy)NWEBHOOK_SECRET)_uiosgetenvr!registered_webhooks_warn_on_empty_secret)selfrr!s r__init__zWebhooksServer.__init__hs8 ,K :J0K8: d112rpathctrjSttjfd}|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}dxs |jjd}|jvrtd|d|j|<y)Nrz /webhooks//zWebhook z already exists.)__name__stripr' ValueError)rrfuncabs_pathr+r)s r _inner_postz/WebhooksServer.add_webhook.._inner_posts`7D#T%:T]]$A$A#$F#GHH4333 8H:5E!FGG15D $ $X .r)callable add_webhookrrpost)r)r+r4s`` rr6zWebhooksServer.add_webhookssG8 D>%4##%d+ + w||  6  6rprevent_thread_lock launch_kwargsc  |jxs|j}|jdt|jdddi|\|_}}|j jD]I\}}|jt||j}|j j||Ktjjd}|d|zn|jxs |j t!d j#d  d }|d d j% fd |j Dzz }|d z }t'||s|j)yy)zLaunch the Gradio app and register webhooks to the underlying FastAPI server. Input parameters are forwarded to Gradio when launching the app. sharer8TNr! SPACE_HOSTzhttps://zWCannot find the URL of the app. Please provide a valid `ui` or update `gradio` version.r.z/ Webhooks are correctly setup and ready to use: c3,K|] }d| yw)z - POST N).0webhookurls r z(WebhooksServer.launch..s#g7iuWI$>#gszG Go to https://huggingface.co/settings/webhooks to setup your webhooks.r@)r$_get_default_ui setdefault _is_locallaunch fastapi_appr'itemsr!_wrap_webhook_to_check_secretr7r%environget share_url local_urlr1r0joinprint block_thread) r)r8r9r_r+r2 space_hostmessagerCs @rrHzWebhooksServer.launchsO XX /--/   )4!*!Ut!U}!U!Q2288: .JD$"".4T$J]J]^ (D   ! !$ ' -  .ZZ^^L1 )3)?j:%bllFbVXVbVb ;vw wiinD4$))#gdNfNf#gggg]] g" OO #rc ddl}|j5}|jd|jd|jt|jddzdj d|jj Dz|jtrd nd ddd|S#1swYSxYw) zLDefault UI if not provided (lists webhooks and provides basic instructions).rNu)# This is an app to process 🤗 WebhooksaTWebhooks 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 c3\K|]$\}}d|dt|j|d&yw)z- [z]()N)_get_webhook_doc_urlr/)rA webhook_pathrBs rrDz1WebhooksServer._get_default_ui..s<- g,r*>w?O?OQ]*^)__`as*,zGo 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'.)gradioBlocksMarkdownlenr'rPrJrG)r)grrs rrEzWebhooksServer._get_default_uis RYY[ B BKKC D BKKD  BKKt//011LM**151I1I1O1O1Q  BKKqv  ! 2 3 2 s BB;;C)rr)NNN)F)rr )r/ __module__ __qualname____doc__rrstrr*rr6boolrrHrE __classcell__)rs@rrr*sy-^ $%)(, 3 [ ! 3!  3  3) ))V"$""QU"Hrr+rctrtSttjdt dt ffd }|S)aDecorator 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 setup 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() ``` r2rctj|tjdk(rt j j tj fd}||_|S)Nr cdtjjjyr`)atexit unregisterrH)appsr _launch_nowz5webhook_endpoint.._inner.._launch_now$s    cjj ) JJLr)_get_global_appr6r^r'rjregisterrHr)r2rmrlr+s @r_innerz webhook_endpoint.._innersjd# s&& '1 , OOCJJ ' szz     "  r)r5webhook_endpointrrr6r)r+rps` rrqrqsPl~!!$'' > % %&X(' Mrc.t tatSr`)rrr@rrrnrn0s$& rr!cb|"tdtdtdytdy)NzZWebhook secret is not defined. This means your webhook endpoints will be open to everyone.zTo 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.)rQr<s rr(r(7s: jk  J   H 45r webhook_namerZc8d|z|jddzdzS)z@Returns the anchor to a given webhook in the docs (experimental)z/docs#/default/r.rS_post)replace)rtrZs rrYrYFs$ | +l.B.B3.L Lw VVrr2cftjtdtffd }djvrnj tj dtj jtftjjz|_ |S)aWraps 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. requestcK|jjd}|tddidS|k7rtddidSdjvr||d<t j rd i|d{Sd i|S7 w) Nzx-webhook-secreterrorz x-webhook-secret header not set.i) status_codezInvalid webhook secret.iryr@)headersrMr parametersinspectiscoroutinefunction)ryrrequest_secretr2 initial_sigr!s r_protected_funcz6_wrap_webhook_to_check_secret.._protected_func\s ,,-?@  !*L M[^_ _ ^ +*C DRUV V  .. . 'F9   & &t ,' '>&> !(sA4B7B8 B)namekind annotation)r~) r signaturerr r~rw ParameterPOSITIONAL_OR_KEYWORDtuplevalues __signature__)r2r!rrs`` @rrKrKKs##D)K 4["w""$ ...(3(;(;!!yw7H7H7^7^krsK**11345)<) % rr`)#rcrjrr% functoolsrtypingrrrrrutilsr r r r[r_fastapir rfastapi.responsesrr__annotations__rLrMrGrrdrqrnr(rYrKr@rrrsZ  ??JJ(.(,+G+g +/ X& '. JJNN: &$ . tttnJ8C=JHJJZ 6(3- 6D 6WsW#W#W --#-(-r