From d99c68f9bffb2c3b21a9adf59ca6b32e4163829e Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Mon, 26 Oct 2026 09:52:31 +0100 Subject: [PATCH] fix: forward timeout in child find_all FindAllChildrenCommandMixin.find_all took a misspelled `timetour` argument and never passed it to the request, so the twelve child listings used the 5s httpx default instead of DEFAULT_TIMEOUT. Add `timeout` with the DEFAULT_TIMEOUT default and forward it. Keep `timetour` as a deprecated keyword-only alias; forwarding it as is would disable the timeout through its None default. Closes #410 Co-Authored-By: Claude Opus 5.5 --- lago_python_client/mixins.py | 7 ++++++ tests/test_find_all_children.py | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lago_python_client/mixins.py b/lago_python_client/mixins.py index 8c510b5..5c4d7df 100644 --- a/lago_python_client/mixins.py +++ b/lago_python_client/mixins.py @@ -1,3 +1,4 @@ +import warnings from typing import Any, Generic, Optional, Type, TypeVar, Union import httpx @@ -157,9 +158,14 @@ def find_all( self: _ClientMixin[_M], resource_id: str, options: QueryPairs = None, + timeout: Optional[httpx.Timeout] = DEFAULT_TIMEOUT, + *, timetour: Optional[httpx.Timeout] = None, ) -> Mapping[str, Any]: """Execute `find_all` child command.""" + if timetour is not None: + warnings.warn("timetour is deprecated, use timeout instead", DeprecationWarning, stacklevel=2) + timeout = timetour # Send request and save response if options is None: options = {} @@ -174,6 +180,7 @@ def find_all( query_pairs=options, ), headers=make_headers(api_key=self.api_key), + timeout=timeout, rate_limit_retry_config=self.rate_limit_retry_config, ) diff --git a/tests/test_find_all_children.py b/tests/test_find_all_children.py index 37b25d7..17f37cf 100644 --- a/tests/test_find_all_children.py +++ b/tests/test_find_all_children.py @@ -1,7 +1,9 @@ +import httpx import pytest from pytest_httpx import HTTPXMock from lago_python_client.client import Client +from lago_python_client.mixins import DEFAULT_TIMEOUT @pytest.mark.parametrize( @@ -38,3 +40,39 @@ def test_find_all_children_sends_authentication_headers( assert request.headers["Authorization"] == "Bearer test-api-key" assert request.headers["Content-Type"] == "application/json" assert response == response_data + + +def mock_invoices_response(httpx_mock: HTTPXMock): + httpx_mock.add_response( + method="GET", + url="https://api.getlago.com/api/v1/customers/parent-id/invoices", + json={"invoices": [], "meta": {"current_page": 1}}, + ) + + +def test_find_all_children_uses_default_timeout(httpx_mock: HTTPXMock): + client = Client(api_key="test-api-key") + mock_invoices_response(httpx_mock) + + client.customer_invoices.find_all(resource_id="parent-id") + + assert httpx_mock.get_request().extensions["timeout"] == DEFAULT_TIMEOUT.as_dict() + + +def test_find_all_children_with_custom_timeout(httpx_mock: HTTPXMock): + client = Client(api_key="test-api-key") + mock_invoices_response(httpx_mock) + + client.customer_invoices.find_all(resource_id="parent-id", timeout=httpx.Timeout(30.0)) + + assert httpx_mock.get_request().extensions["timeout"] == httpx.Timeout(30.0).as_dict() + + +def test_find_all_children_with_deprecated_timetour(httpx_mock: HTTPXMock): + client = Client(api_key="test-api-key") + mock_invoices_response(httpx_mock) + + with pytest.warns(DeprecationWarning, match="timetour is deprecated"): + client.customer_invoices.find_all(resource_id="parent-id", timetour=httpx.Timeout(30.0)) + + assert httpx_mock.get_request().extensions["timeout"] == httpx.Timeout(30.0).as_dict()