diff --git a/README.md b/README.md index 38c1c08..b4e51be 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ response = client.colas.list( volume_min=375, volume_max=750, container_type="bottle,can", + sort="relevance_desc", # Or approval_date_desc page=1, per_page=20 # Max 100 ) @@ -184,6 +185,7 @@ response = client.permittees.list( q="distillery", # Search by company name state="CA", # Two-letter state code is_active=True, # Active permit status + sort="relevance_desc", page=1, per_page=20 ) diff --git a/src/colacloud/async_client.py b/src/colacloud/async_client.py index ad821bf..e5987d4 100644 --- a/src/colacloud/async_client.py +++ b/src/colacloud/async_client.py @@ -65,6 +65,7 @@ async def list( volume_min: float | None = None, volume_max: float | None = None, container_type: str | None = None, + sort: str | None = None, page: int = 1, per_page: int = 20, ) -> ColaListResponse: @@ -89,6 +90,7 @@ async def list( volume_min: Filter by minimum package volume. volume_max: Filter by maximum package volume. container_type: Filter by one or more derived container types. + sort: Sort order, such as "approval_date_desc" or "relevance_desc". page: Page number (default: 1). per_page: Results per page (default: 20, max: 100). @@ -139,6 +141,8 @@ async def list( params["volume_max"] = volume_max if container_type: params["container_type"] = container_type + if sort: + params["sort"] = sort data = await self._client._request("GET", "/colas", params=params) return ColaListResponse.model_validate(data) @@ -183,6 +187,7 @@ def iterate( volume_min: float | None = None, volume_max: float | None = None, container_type: str | None = None, + sort: str | None = None, per_page: int = 100, ) -> AsyncPaginatedIterator[ColaSummary]: """Iterate through all matching COLAs with automatic pagination. @@ -209,6 +214,7 @@ def iterate( volume_min: Filter by minimum package volume. volume_max: Filter by maximum package volume. container_type: Filter by one or more derived container types. + sort: Sort order, such as "approval_date_desc" or "relevance_desc". per_page: Results per page (default: 100, max: 100). Yields: @@ -241,6 +247,7 @@ async def fetch_page(page: int) -> tuple[list[ColaSummary], Pagination]: volume_min=volume_min, volume_max=volume_max, container_type=container_type, + sort=sort, page=page, per_page=per_page, ) @@ -261,6 +268,7 @@ async def list( q: str | None = None, state: str | None = None, is_active: bool | None = None, + sort: str | None = None, page: int = 1, per_page: int = 20, ) -> PermitteeListResponse: @@ -270,6 +278,7 @@ async def list( q: Search by company name (partial match). state: Filter by state (two-letter code, e.g., "CA", "NY"). is_active: Filter by active status. + sort: Sort order, such as "colas_desc" or "relevance_desc". page: Page number (default: 1). per_page: Results per page (default: 20, max: 100). @@ -290,6 +299,8 @@ async def list( params["state"] = state if is_active is not None: params["is_active"] = "true" if is_active else "false" + if sort: + params["sort"] = sort data = await self._client._request("GET", "/permittees", params=params) return PermitteeListResponse.model_validate(data) @@ -319,6 +330,7 @@ def iterate( q: str | None = None, state: str | None = None, is_active: bool | None = None, + sort: str | None = None, per_page: int = 100, ) -> AsyncPaginatedIterator[PermitteeSummary]: """Iterate through all matching permittees with automatic pagination. @@ -330,6 +342,7 @@ def iterate( q: Search by company name (partial match). state: Filter by state (two-letter code). is_active: Filter by active status. + sort: Sort order, such as "colas_desc" or "relevance_desc". per_page: Results per page (default: 100, max: 100). Yields: @@ -347,6 +360,7 @@ async def fetch_page(page: int) -> tuple[list[PermitteeSummary], Pagination]: q=q, state=state, is_active=is_active, + sort=sort, page=page, per_page=per_page, ) diff --git a/src/colacloud/client.py b/src/colacloud/client.py index 33295f2..01d54e2 100644 --- a/src/colacloud/client.py +++ b/src/colacloud/client.py @@ -65,6 +65,7 @@ def list( volume_min: float | None = None, volume_max: float | None = None, container_type: str | None = None, + sort: str | None = None, page: int = 1, per_page: int = 20, ) -> ColaListResponse: @@ -89,6 +90,7 @@ def list( volume_min: Filter by minimum package volume. volume_max: Filter by maximum package volume. container_type: Filter by one or more derived container types. + sort: Sort order, such as "approval_date_desc" or "relevance_desc". page: Page number (default: 1). per_page: Results per page (default: 20, max: 100). @@ -139,6 +141,8 @@ def list( params["volume_max"] = volume_max if container_type: params["container_type"] = container_type + if sort: + params["sort"] = sort data = self._client._request("GET", "/colas", params=params) return ColaListResponse.model_validate(data) @@ -183,6 +187,7 @@ def iterate( volume_min: float | None = None, volume_max: float | None = None, container_type: str | None = None, + sort: str | None = None, per_page: int = 100, ) -> PaginatedIterator[ColaSummary]: """Iterate through all matching COLAs with automatic pagination. @@ -209,6 +214,7 @@ def iterate( volume_min: Filter by minimum package volume. volume_max: Filter by maximum package volume. container_type: Filter by one or more derived container types. + sort: Sort order, such as "approval_date_desc" or "relevance_desc". per_page: Results per page (default: 100, max: 100). Yields: @@ -241,6 +247,7 @@ def fetch_page(page: int) -> tuple[list[ColaSummary], Pagination]: volume_min=volume_min, volume_max=volume_max, container_type=container_type, + sort=sort, page=page, per_page=per_page, ) @@ -261,6 +268,7 @@ def list( q: str | None = None, state: str | None = None, is_active: bool | None = None, + sort: str | None = None, page: int = 1, per_page: int = 20, ) -> PermitteeListResponse: @@ -270,6 +278,7 @@ def list( q: Search by company name (partial match). state: Filter by state (two-letter code, e.g., "CA", "NY"). is_active: Filter by active status. + sort: Sort order, such as "colas_desc" or "relevance_desc". page: Page number (default: 1). per_page: Results per page (default: 20, max: 100). @@ -290,6 +299,8 @@ def list( params["state"] = state if is_active is not None: params["is_active"] = "true" if is_active else "false" + if sort: + params["sort"] = sort data = self._client._request("GET", "/permittees", params=params) return PermitteeListResponse.model_validate(data) @@ -319,6 +330,7 @@ def iterate( q: str | None = None, state: str | None = None, is_active: bool | None = None, + sort: str | None = None, per_page: int = 100, ) -> PaginatedIterator[PermitteeSummary]: """Iterate through all matching permittees with automatic pagination. @@ -330,6 +342,7 @@ def iterate( q: Search by company name (partial match). state: Filter by state (two-letter code). is_active: Filter by active status. + sort: Sort order, such as "colas_desc" or "relevance_desc". per_page: Results per page (default: 100, max: 100). Yields: @@ -347,6 +360,7 @@ def fetch_page(page: int) -> tuple[list[PermitteeSummary], Pagination]: q=q, state=state, is_active=is_active, + sort=sort, page=page, per_page=per_page, ) diff --git a/tests/test_async_client.py b/tests/test_async_client.py index bae077f..07dd511 100644 --- a/tests/test_async_client.py +++ b/tests/test_async_client.py @@ -45,10 +45,11 @@ async def test_list_colas(self, httpx_mock: HTTPXMock, cola_list_response): httpx_mock.add_response(json=cola_list_response) async with AsyncColaCloud(api_key="test-key") as client: - response = await client.colas.list(q="bourbon") + response = await client.colas.list(q="bourbon", sort="relevance_desc") assert len(response.data) == 1 assert response.data[0].ttb_id == "12345678" + assert "sort=relevance_desc" in str(httpx_mock.get_request().url) async def test_get_cola(self, httpx_mock: HTTPXMock, cola_detail_response): httpx_mock.add_response(json=cola_detail_response) @@ -78,10 +79,11 @@ async def test_list_permittees(self, httpx_mock: HTTPXMock, permittee_list_respo httpx_mock.add_response(json=permittee_list_response) async with AsyncColaCloud(api_key="test-key") as client: - response = await client.permittees.list(state="KY") + response = await client.permittees.list(state="KY", sort="company_name_asc") assert len(response.data) == 1 assert response.data[0].permit_number == "KY-I-12345" + assert "sort=company_name_asc" in str(httpx_mock.get_request().url) async def test_get_permittee(self, httpx_mock: HTTPXMock, permittee_detail_response): httpx_mock.add_response(json=permittee_detail_response) @@ -173,12 +175,13 @@ async def test_iterate_colas(self, httpx_mock: HTTPXMock, sample_cola_summary): async with AsyncColaCloud(api_key="test-key") as client: colas = [] - async for cola in client.colas.iterate(q="test", per_page=1): + async for cola in client.colas.iterate(q="test", sort="relevance_desc", per_page=1): colas.append(cola) assert len(colas) == 2 assert colas[0].ttb_id == "12345678" assert colas[1].ttb_id == "87654321" + assert "sort=relevance_desc" in str(httpx_mock.get_requests()[0].url) async def test_iterate_permittees(self, httpx_mock: HTTPXMock, sample_permittee_summary): httpx_mock.add_response( @@ -190,11 +193,14 @@ async def test_iterate_permittees(self, httpx_mock: HTTPXMock, sample_permittee_ async with AsyncColaCloud(api_key="test-key") as client: permittees = [] - async for permittee in client.permittees.iterate(state="KY", per_page=1): + async for permittee in client.permittees.iterate( + state="KY", sort="company_name_asc", per_page=1 + ): permittees.append(permittee) assert len(permittees) == 1 assert permittees[0].permit_number == "KY-I-12345" + assert "sort=company_name_asc" in str(httpx_mock.get_request().url) @pytest.mark.asyncio diff --git a/tests/test_client.py b/tests/test_client.py index 75cf69c..0813bee 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -92,6 +92,7 @@ def test_list_colas_with_filters(self, httpx_mock: HTTPXMock, cola_list_response volume_min=375, volume_max=750, container_type="bottle,can", + sort="relevance_desc", page=1, per_page=50, ) @@ -109,6 +110,7 @@ def test_list_colas_with_filters(self, httpx_mock: HTTPXMock, cola_list_response assert "volume_min=375" in str(request.url) assert "volume_max=750" in str(request.url) assert "container_type=bottle%2Ccan" in str(request.url) + assert "sort=relevance_desc" in str(request.url) def test_get_cola(self, httpx_mock: HTTPXMock, cola_detail_response): httpx_mock.add_response(json=cola_detail_response) @@ -152,6 +154,7 @@ def test_list_permittees_with_filters(self, httpx_mock: HTTPXMock, permittee_lis q="distillery", state="CA", is_active=True, + sort="relevance_desc", page=2, per_page=50, ) @@ -160,6 +163,7 @@ def test_list_permittees_with_filters(self, httpx_mock: HTTPXMock, permittee_lis assert "q=distillery" in str(request.url) assert "state=CA" in str(request.url) assert "is_active=true" in str(request.url) + assert "sort=relevance_desc" in str(request.url) def test_get_permittee(self, httpx_mock: HTTPXMock, permittee_detail_response): httpx_mock.add_response(json=permittee_detail_response) @@ -328,11 +332,12 @@ def test_iterate_colas(self, httpx_mock: HTTPXMock, sample_cola_summary): ) with ColaCloud(api_key="test-key") as client: - colas = list(client.colas.iterate(q="test", per_page=1)) + colas = list(client.colas.iterate(q="test", sort="relevance_desc", per_page=1)) assert len(colas) == 2 assert colas[0].ttb_id == "12345678" assert colas[1].ttb_id == "87654321" + assert "sort=relevance_desc" in str(httpx_mock.get_requests()[0].url) def test_iterate_permittees(self, httpx_mock: HTTPXMock, sample_permittee_summary): httpx_mock.add_response( @@ -343,10 +348,13 @@ def test_iterate_permittees(self, httpx_mock: HTTPXMock, sample_permittee_summar ) with ColaCloud(api_key="test-key") as client: - permittees = list(client.permittees.iterate(state="KY", per_page=1)) + permittees = list( + client.permittees.iterate(state="KY", sort="company_name_asc", per_page=1) + ) assert len(permittees) == 1 assert permittees[0].permit_number == "KY-I-12345" + assert "sort=company_name_asc" in str(httpx_mock.get_request().url) class TestProcessingTimesResource: