2d753d0e86
* Let API callers supply a token for gr.OAuthToken endpoints `gr.OAuthToken` was only ever populated from the OAuth session cookie, so it was always `None` for an API caller — no browser, no session. Any app whose function takes one could not be driven programmatically at all, which is how this surfaced: a deployed `gr.Workflow` reached its model nodes with no token and failed with "Sign in with your HF account to use this model". Callers can now pass `Client(..., oauth_token=...)`, which travels in the request body as a reserved `oauth_token` field rather than a header — a Space sits behind a proxy that strips `x-hf-*`, so a header never arrives. Because it rides beside `data` instead of in it, it never becomes a positional argument or appears in an endpoint's parameter schema, and it can't be captured by flagging or cached examples. It also works from `curl` and any other client, with no client-side support needed. A token is sent only to endpoints that declare they take one: `get_api_info` reports `oauth_token: "required" | "optional"` per endpoint, derived from the function signature, and the client consults that before including the field. So an app cannot collect tokens from calls that had no reason to carry one, and `view_api()` states plainly which endpoints act on the caller's behalf. `oauth_token=` is deliberately separate from `token=`, which only authenticates the caller to the app, and is never inferred from a locally saved token. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Support oauth_token in the JS client, and move the e2e test The JS client gains the same `oauth_token` option and the same gating: it is included in the payload only for endpoints whose api_info declares they take a gr.OAuthToken, so parity with the Python client holds and an app still cannot collect tokens from calls that had no reason to carry one. The end-to-end check moves into test_external.py, which already hits real Spaces and is marked flaky and serial, rather than living in a file of its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Address review: narrow the token flag, and close two ways to bypass the gate `oauth_token_requirement` scanned every annotation, including the return type, so a function that *returned* an OAuthToken was reported as one that receives one. It now looks only at parameters. `/call/v2` popped `oauth_token` from every request body, which reserved the name globally and would swallow a real parameter that happened to be called that. It is only treated as reserved for endpoints that declare they take a token. In the client, `**kwargs` expanded after the gated payload, so passing `oauth_token=` as an ordinary keyword argument would have sent a token to an endpoint that never asked for one. The computed payload now goes last and wins. Also reworded a docstring that opened with a quoted word, which `ruff format` had to space away from the opening triple quote. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Satisfy the backend type checker `oauth_token_requirement` returned plain `str`, which cannot be assigned to the `Literal["required", "optional"]` key on the APIEndpointInfo TypedDict, and the e2e test subscripted `view_api()` (overloaded on return_format) and iterated client.endpoints without narrowing the value type. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Surface oauth_token in the API docs, and fix the JS client gate The per-endpoint `oauth_token` requirement reached `/info` but stopped there, so nothing downstream showed it or acted on it: - `transform_api_info()` rebuilt each endpoint as {parameters, returns, type}, dropping `oauth_token`. `submit()`'s gate therefore never matched and the JS client never sent a token at all. - The view-API page said nothing about which endpoints act on the caller's behalf, and its snippets omitted `oauth_token` so copy-paste didn't work. - Sending `oauth_token` to an endpoint that takes no token 500'd on `construct_args`; it is now stripped from the args either way and only honored where the fn declares one. Also trims the explanatory inline comments added across the branch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Make the oauth_token notice font sizes consistent The first paragraph inherited --text-md while .desc set --text-lg, so the subdued explanation rendered larger than the primary statement. Both are prose now at --text-lg, and the inline mono spans drop a step to sit optically level with it — matching the sibling parameters section (h4 14px, prose 16px, mono 14px). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Stop reserving the oauth_token body key on every endpoint Popping it unconditionally fixed the 500 on endpoints that take no token, but it also swallowed the value of any endpoint whose own parameter is named oauth_token (github-pilot caught this). The name is now reserved only where the fn declares a gr.OAuthToken; elsewhere it stays an ordinary argument if the endpoint has one by that name, and is dropped if it does not — so neither the 500 nor the swallowing happens. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Backend Testing Guidelines
- All the tests should test Backend functionalities. Frontend functionalities and e2e tests are done in Frontend.
- Make use of pytest fixtures whenever it is possible. With fixtures, objects with high initialize durations are reused within tests, ex. a client session.
- All testdata resides within _gradio/test_data and all test_files reside within test/test_files.
- When doing network operations do not forget to make use of async to make tests faster.
- Have clear class and function naming within the tests.
- Short descriptions within test functions are great.
- Library function docstrings is expected to contain an example, please add missing docstrings to the library while you are writing tests the related function.
- Library docstring examples and descriptions are expected to align with tests, please fix divergent tests and library docstrings.