fern icon indicating copy to clipboard operation
fern copied to clipboard

HttpClient ignores timeout specified in httpx.Client

Open alexkuzmik opened this issue 1 year ago • 4 comments

CLI Version from fern.config.json

0.45.0

Generator & Version from generators.yml

fernapi/fern-python-sdk 4.3.8

Minimal API Specification

If you pass your own httpx.Client to fern generated API object, whenever any request is done, the timeout specified in httpx client will be ignored in favor of the timeout from request_options. If no timeout was provided in request_options, no timeout will be used at all.

Actual Generated Code

This is the line that sets timeout to None if httpx.Client was passed to Fern client __init__ function.

_defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None

This is the code for choosing timeout whenever any request is made (it's always None if no request_options provided and using your own httpx Client).

        timeout = (
            request_options.get("timeout_in_seconds")
            if request_options is not None
            and request_options.get("timeout_in_seconds") is not None
            else self.base_timeout()
        )

Expected Generated Code

Instead of setting the timeout to None if it was not passed in request_options, I think it should either not be passed to httpx.Client.request at all because httpx's default value for it is USE_CLIENT_DEFAULT = UseClientDefault(), or it should pass USE_CLIENT_DEFAULT object instead.

alexkuzmik avatar Dec 03 '24 16:12 alexkuzmik

@alexkuzmik is this blocking Python SDK consumption at Comet?

Tagging @eyw520 so this is on his radar.

dannysheridan avatar Dec 17 '24 01:12 dannysheridan

Hi @dannysheridan! Sorry, I missed your message. We are using a workaround at the moment, a bit dirty because of double private attribute access, but it works.

rest_client = rest_api_client.OpikApi(  # OpikApi is a Fern class
    base_url=base_url,
    httpx_client=httpx_client_,
)       
rest_client._client_wrapper._timeout = OPIK_API_REQUESTS_TIMEOUT_SECONDS

The hardest part was to detect that :)

alexkuzmik avatar Feb 21 '25 09:02 alexkuzmik

@dannysheridan FYI this issue became a more serious problem after we needed to configure different timeouts for connection, read and write operations.

alexkuzmik avatar Mar 12 '25 16:03 alexkuzmik

@dannysheridan UPD. the new workaround which allows using configured timeouts from your HTTPX client directly:

rest_client = rest_api_client.OpikApi(  # OpikApi is a Fern class
    base_url=base_url,
    httpx_client=httpx_client_,
)
rest_client._client_wrapper._timeout = httpx.USE_CLIENT_DEFAULT 

alexkuzmik avatar Mar 12 '25 17:03 alexkuzmik