From a5c305c7a5614588dd3fb14607dd2489aab8b3c6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:23:53 +0000 Subject: [PATCH 01/18] feat(api): OpenAPI spec update via Stainless API (#48) --- .stats.yml | 4 +- api.md | 12 ++ src/onebusaway/_client.py | 12 ++ src/onebusaway/resources/__init__.py | 14 ++ .../resources/route_ids_for_agency.py | 141 ++++++++++++++++++ src/onebusaway/types/__init__.py | 1 + .../route_ids_for_agency_list_response.py | 23 +++ .../test_route_ids_for_agency.py | 98 ++++++++++++ 8 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 src/onebusaway/resources/route_ids_for_agency.py create mode 100644 src/onebusaway/types/route_ids_for_agency_list_response.py create mode 100644 tests/api_resources/test_route_ids_for_agency.py diff --git a/.stats.yml b/.stats.yml index 0915939..f38736f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 17 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-e1da29690ebfb4c6c07ede3d292a4f6babcd2202d6f3bb38bfa287ae04dfeb50.yml +configured_endpoints: 18 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-745fc14b503259d6b0d29d50d4277b86cada74faf6f831bb19710d2e7ead8a7c.yml diff --git a/api.md b/api.md index 8404d9c..1aa1c4c 100644 --- a/api.md +++ b/api.md @@ -136,6 +136,18 @@ Methods: - client.route.retrieve(route_id) -> RouteRetrieveResponse +# RouteIDsForAgency + +Types: + +```python +from onebusaway.types import RouteIDsForAgencyListResponse +``` + +Methods: + +- client.route_ids_for_agency.list(agency_id) -> RouteIDsForAgencyListResponse + # ArrivalAndDeparture Types: diff --git a/src/onebusaway/_client.py b/src/onebusaway/_client.py index 4d0abe9..12680ce 100644 --- a/src/onebusaway/_client.py +++ b/src/onebusaway/_client.py @@ -57,6 +57,7 @@ class OnebusawaySDK(SyncAPIClient): stop_ids_for_agency: resources.StopIDsForAgencyResource schedule_for_stop: resources.ScheduleForStopResource route: resources.RouteResource + route_ids_for_agency: resources.RouteIDsForAgencyResource arrival_and_departure: resources.ArrivalAndDepartureResource trip: resources.TripResource trips_for_location: resources.TripsForLocationResource @@ -130,6 +131,7 @@ def __init__( self.stop_ids_for_agency = resources.StopIDsForAgencyResource(self) self.schedule_for_stop = resources.ScheduleForStopResource(self) self.route = resources.RouteResource(self) + self.route_ids_for_agency = resources.RouteIDsForAgencyResource(self) self.arrival_and_departure = resources.ArrivalAndDepartureResource(self) self.trip = resources.TripResource(self) self.trips_for_location = resources.TripsForLocationResource(self) @@ -263,6 +265,7 @@ class AsyncOnebusawaySDK(AsyncAPIClient): stop_ids_for_agency: resources.AsyncStopIDsForAgencyResource schedule_for_stop: resources.AsyncScheduleForStopResource route: resources.AsyncRouteResource + route_ids_for_agency: resources.AsyncRouteIDsForAgencyResource arrival_and_departure: resources.AsyncArrivalAndDepartureResource trip: resources.AsyncTripResource trips_for_location: resources.AsyncTripsForLocationResource @@ -336,6 +339,7 @@ def __init__( self.stop_ids_for_agency = resources.AsyncStopIDsForAgencyResource(self) self.schedule_for_stop = resources.AsyncScheduleForStopResource(self) self.route = resources.AsyncRouteResource(self) + self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResource(self) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResource(self) self.trip = resources.AsyncTripResource(self) self.trips_for_location = resources.AsyncTripsForLocationResource(self) @@ -472,6 +476,7 @@ def __init__(self, client: OnebusawaySDK) -> None: self.stop_ids_for_agency = resources.StopIDsForAgencyResourceWithRawResponse(client.stop_ids_for_agency) self.schedule_for_stop = resources.ScheduleForStopResourceWithRawResponse(client.schedule_for_stop) self.route = resources.RouteResourceWithRawResponse(client.route) + self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithRawResponse(client.arrival_and_departure) self.trip = resources.TripResourceWithRawResponse(client.trip) self.trips_for_location = resources.TripsForLocationResourceWithRawResponse(client.trips_for_location) @@ -494,6 +499,7 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: self.stop_ids_for_agency = resources.AsyncStopIDsForAgencyResourceWithRawResponse(client.stop_ids_for_agency) self.schedule_for_stop = resources.AsyncScheduleForStopResourceWithRawResponse(client.schedule_for_stop) self.route = resources.AsyncRouteResourceWithRawResponse(client.route) + self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithRawResponse( client.arrival_and_departure ) @@ -518,6 +524,9 @@ def __init__(self, client: OnebusawaySDK) -> None: self.stop_ids_for_agency = resources.StopIDsForAgencyResourceWithStreamingResponse(client.stop_ids_for_agency) self.schedule_for_stop = resources.ScheduleForStopResourceWithStreamingResponse(client.schedule_for_stop) self.route = resources.RouteResourceWithStreamingResponse(client.route) + self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithStreamingResponse( + client.route_ids_for_agency + ) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithStreamingResponse( client.arrival_and_departure ) @@ -548,6 +557,9 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: ) self.schedule_for_stop = resources.AsyncScheduleForStopResourceWithStreamingResponse(client.schedule_for_stop) self.route = resources.AsyncRouteResourceWithStreamingResponse(client.route) + self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithStreamingResponse( + client.route_ids_for_agency + ) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithStreamingResponse( client.arrival_and_departure ) diff --git a/src/onebusaway/resources/__init__.py b/src/onebusaway/resources/__init__.py index 48fb9f8..53d412c 100644 --- a/src/onebusaway/resources/__init__.py +++ b/src/onebusaway/resources/__init__.py @@ -112,6 +112,14 @@ VehiclesForAgencyResourceWithStreamingResponse, AsyncVehiclesForAgencyResourceWithStreamingResponse, ) +from .route_ids_for_agency import ( + RouteIDsForAgencyResource, + AsyncRouteIDsForAgencyResource, + RouteIDsForAgencyResourceWithRawResponse, + AsyncRouteIDsForAgencyResourceWithRawResponse, + RouteIDsForAgencyResourceWithStreamingResponse, + AsyncRouteIDsForAgencyResourceWithStreamingResponse, +) from .arrival_and_departure import ( ArrivalAndDepartureResource, AsyncArrivalAndDepartureResource, @@ -196,6 +204,12 @@ "AsyncRouteResourceWithRawResponse", "RouteResourceWithStreamingResponse", "AsyncRouteResourceWithStreamingResponse", + "RouteIDsForAgencyResource", + "AsyncRouteIDsForAgencyResource", + "RouteIDsForAgencyResourceWithRawResponse", + "AsyncRouteIDsForAgencyResourceWithRawResponse", + "RouteIDsForAgencyResourceWithStreamingResponse", + "AsyncRouteIDsForAgencyResourceWithStreamingResponse", "ArrivalAndDepartureResource", "AsyncArrivalAndDepartureResource", "ArrivalAndDepartureResourceWithRawResponse", diff --git a/src/onebusaway/resources/route_ids_for_agency.py b/src/onebusaway/resources/route_ids_for_agency.py new file mode 100644 index 0000000..cf5ab88 --- /dev/null +++ b/src/onebusaway/resources/route_ids_for_agency.py @@ -0,0 +1,141 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.route_ids_for_agency_list_response import RouteIDsForAgencyListResponse + +__all__ = ["RouteIDsForAgencyResource", "AsyncRouteIDsForAgencyResource"] + + +class RouteIDsForAgencyResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> RouteIDsForAgencyResourceWithRawResponse: + return RouteIDsForAgencyResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> RouteIDsForAgencyResourceWithStreamingResponse: + return RouteIDsForAgencyResourceWithStreamingResponse(self) + + def list( + self, + agency_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> RouteIDsForAgencyListResponse: + """ + Get route IDs for a specific agency + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agency_id: + raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") + return self._get( + f"/api/where/route-ids-for-agency/agencyID.json", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RouteIDsForAgencyListResponse, + ) + + +class AsyncRouteIDsForAgencyResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncRouteIDsForAgencyResourceWithRawResponse: + return AsyncRouteIDsForAgencyResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncRouteIDsForAgencyResourceWithStreamingResponse: + return AsyncRouteIDsForAgencyResourceWithStreamingResponse(self) + + async def list( + self, + agency_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> RouteIDsForAgencyListResponse: + """ + Get route IDs for a specific agency + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agency_id: + raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") + return await self._get( + f"/api/where/route-ids-for-agency/agencyID.json", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RouteIDsForAgencyListResponse, + ) + + +class RouteIDsForAgencyResourceWithRawResponse: + def __init__(self, route_ids_for_agency: RouteIDsForAgencyResource) -> None: + self._route_ids_for_agency = route_ids_for_agency + + self.list = to_raw_response_wrapper( + route_ids_for_agency.list, + ) + + +class AsyncRouteIDsForAgencyResourceWithRawResponse: + def __init__(self, route_ids_for_agency: AsyncRouteIDsForAgencyResource) -> None: + self._route_ids_for_agency = route_ids_for_agency + + self.list = async_to_raw_response_wrapper( + route_ids_for_agency.list, + ) + + +class RouteIDsForAgencyResourceWithStreamingResponse: + def __init__(self, route_ids_for_agency: RouteIDsForAgencyResource) -> None: + self._route_ids_for_agency = route_ids_for_agency + + self.list = to_streamed_response_wrapper( + route_ids_for_agency.list, + ) + + +class AsyncRouteIDsForAgencyResourceWithStreamingResponse: + def __init__(self, route_ids_for_agency: AsyncRouteIDsForAgencyResource) -> None: + self._route_ids_for_agency = route_ids_for_agency + + self.list = async_to_streamed_response_wrapper( + route_ids_for_agency.list, + ) diff --git a/src/onebusaway/types/__init__.py b/src/onebusaway/types/__init__.py index 87b7d0c..a8bf612 100644 --- a/src/onebusaway/types/__init__.py +++ b/src/onebusaway/types/__init__.py @@ -19,6 +19,7 @@ from .schedule_for_stop_retrieve_params import ScheduleForStopRetrieveParams as ScheduleForStopRetrieveParams from .stop_ids_for_agency_list_response import StopIDsForAgencyListResponse as StopIDsForAgencyListResponse from .vehicles_for_agency_list_response import VehiclesForAgencyListResponse as VehiclesForAgencyListResponse +from .route_ids_for_agency_list_response import RouteIDsForAgencyListResponse as RouteIDsForAgencyListResponse from .stops_for_location_retrieve_params import StopsForLocationRetrieveParams as StopsForLocationRetrieveParams from .trip_for_vehicle_retrieve_response import TripForVehicleRetrieveResponse as TripForVehicleRetrieveResponse from .trips_for_location_retrieve_params import TripsForLocationRetrieveParams as TripsForLocationRetrieveParams diff --git a/src/onebusaway/types/route_ids_for_agency_list_response.py b/src/onebusaway/types/route_ids_for_agency_list_response.py new file mode 100644 index 0000000..ffe9c32 --- /dev/null +++ b/src/onebusaway/types/route_ids_for_agency_list_response.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .shared.references import References +from .shared.response_wrapper import ResponseWrapper + +__all__ = ["RouteIDsForAgencyListResponse", "RouteIDsForAgencyListResponseData"] + + +class RouteIDsForAgencyListResponseData(BaseModel): + list: List[str] + + references: References + + limit_exceeded: Optional[bool] = FieldInfo(alias="limitExceeded", default=None) + + +class RouteIDsForAgencyListResponse(ResponseWrapper): + data: RouteIDsForAgencyListResponseData diff --git a/tests/api_resources/test_route_ids_for_agency.py b/tests/api_resources/test_route_ids_for_agency.py new file mode 100644 index 0000000..867c19a --- /dev/null +++ b/tests/api_resources/test_route_ids_for_agency.py @@ -0,0 +1,98 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from onebusaway import OnebusawaySDK, AsyncOnebusawaySDK +from tests.utils import assert_matches_type +from onebusaway.types import RouteIDsForAgencyListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestRouteIDsForAgency: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: OnebusawaySDK) -> None: + route_ids_for_agency = client.route_ids_for_agency.list( + "agencyID", + ) + assert_matches_type(RouteIDsForAgencyListResponse, route_ids_for_agency, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: OnebusawaySDK) -> None: + response = client.route_ids_for_agency.with_raw_response.list( + "agencyID", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + route_ids_for_agency = response.parse() + assert_matches_type(RouteIDsForAgencyListResponse, route_ids_for_agency, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: OnebusawaySDK) -> None: + with client.route_ids_for_agency.with_streaming_response.list( + "agencyID", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + route_ids_for_agency = response.parse() + assert_matches_type(RouteIDsForAgencyListResponse, route_ids_for_agency, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: OnebusawaySDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agency_id` but received ''"): + client.route_ids_for_agency.with_raw_response.list( + "", + ) + + +class TestAsyncRouteIDsForAgency: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_list(self, async_client: AsyncOnebusawaySDK) -> None: + route_ids_for_agency = await async_client.route_ids_for_agency.list( + "agencyID", + ) + assert_matches_type(RouteIDsForAgencyListResponse, route_ids_for_agency, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncOnebusawaySDK) -> None: + response = await async_client.route_ids_for_agency.with_raw_response.list( + "agencyID", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + route_ids_for_agency = await response.parse() + assert_matches_type(RouteIDsForAgencyListResponse, route_ids_for_agency, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncOnebusawaySDK) -> None: + async with async_client.route_ids_for_agency.with_streaming_response.list( + "agencyID", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + route_ids_for_agency = await response.parse() + assert_matches_type(RouteIDsForAgencyListResponse, route_ids_for_agency, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncOnebusawaySDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agency_id` but received ''"): + await async_client.route_ids_for_agency.with_raw_response.list( + "", + ) From 6d1fdf78cf6d63079bf037b88ac0540e619f9ae7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:26:24 +0000 Subject: [PATCH 02/18] chore(internal): bump pyright (#50) --- requirements-dev.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index bc4b747..ca77645 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -71,7 +71,7 @@ pydantic-core==2.18.2 # via pydantic pygments==2.18.0 # via rich -pyright==1.1.364 +pyright==1.1.374 pytest==7.1.1 # via pytest-asyncio pytest-asyncio==0.21.1 From 97156e5dff5d743d04ecc0dbe73ec7c690dfb4fe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:26:45 +0000 Subject: [PATCH 03/18] feat(client): add `retry_count` to raw response class (#51) --- src/onebusaway/_base_client.py | 8 ++++++ src/onebusaway/_response.py | 5 ++++ tests/test_client.py | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/onebusaway/_base_client.py b/src/onebusaway/_base_client.py index d17404e..a38363f 100644 --- a/src/onebusaway/_base_client.py +++ b/src/onebusaway/_base_client.py @@ -1049,6 +1049,7 @@ def _request( response=response, stream=stream, stream_cls=stream_cls, + retries_taken=options.get_max_retries(self.max_retries) - retries, ) def _retry_request( @@ -1090,6 +1091,7 @@ def _process_response( response: httpx.Response, stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, + retries_taken: int = 0, ) -> ResponseT: origin = get_origin(cast_to) or cast_to @@ -1107,6 +1109,7 @@ def _process_response( stream=stream, stream_cls=stream_cls, options=options, + retries_taken=retries_taken, ), ) @@ -1120,6 +1123,7 @@ def _process_response( stream=stream, stream_cls=stream_cls, options=options, + retries_taken=retries_taken, ) if bool(response.request.headers.get(RAW_RESPONSE_HEADER)): return cast(ResponseT, api_response) @@ -1610,6 +1614,7 @@ async def _request( response=response, stream=stream, stream_cls=stream_cls, + retries_taken=options.get_max_retries(self.max_retries) - retries, ) async def _retry_request( @@ -1649,6 +1654,7 @@ async def _process_response( response: httpx.Response, stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, + retries_taken: int = 0, ) -> ResponseT: origin = get_origin(cast_to) or cast_to @@ -1666,6 +1672,7 @@ async def _process_response( stream=stream, stream_cls=stream_cls, options=options, + retries_taken=retries_taken, ), ) @@ -1679,6 +1686,7 @@ async def _process_response( stream=stream, stream_cls=stream_cls, options=options, + retries_taken=retries_taken, ) if bool(response.request.headers.get(RAW_RESPONSE_HEADER)): return cast(ResponseT, api_response) diff --git a/src/onebusaway/_response.py b/src/onebusaway/_response.py index 40d4fb2..c0ca840 100644 --- a/src/onebusaway/_response.py +++ b/src/onebusaway/_response.py @@ -55,6 +55,9 @@ class BaseAPIResponse(Generic[R]): http_response: httpx.Response + retries_taken: int + """The number of retries made. If no retries happened this will be `0`""" + def __init__( self, *, @@ -64,6 +67,7 @@ def __init__( stream: bool, stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None, options: FinalRequestOptions, + retries_taken: int = 0, ) -> None: self._cast_to = cast_to self._client = client @@ -72,6 +76,7 @@ def __init__( self._stream_cls = stream_cls self._options = options self.http_response = raw + self.retries_taken = retries_taken @property def headers(self) -> httpx.Headers: diff --git a/tests/test_client.py b/tests/test_client.py index a099efe..a68fac1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -734,6 +734,27 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> Non assert _get_open_connections(self.client) == 0 + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("onebusaway._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + def test_retries_taken(self, client: OnebusawaySDK, failures_before_success: int, respx_mock: MockRouter) -> None: + client = client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.get("/api/where/current-time.json").mock(side_effect=retry_handler) + + response = client.current_time.with_raw_response.retrieve() + + assert response.retries_taken == failures_before_success + class TestAsyncOnebusawaySDK: client = AsyncOnebusawaySDK(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -1423,3 +1444,27 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) ) assert _get_open_connections(self.client) == 0 + + @pytest.mark.parametrize("failures_before_success", [0, 2, 4]) + @mock.patch("onebusaway._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) + @pytest.mark.respx(base_url=base_url) + @pytest.mark.asyncio + async def test_retries_taken( + self, async_client: AsyncOnebusawaySDK, failures_before_success: int, respx_mock: MockRouter + ) -> None: + client = async_client.with_options(max_retries=4) + + nb_retries = 0 + + def retry_handler(_request: httpx.Request) -> httpx.Response: + nonlocal nb_retries + if nb_retries < failures_before_success: + nb_retries += 1 + return httpx.Response(500) + return httpx.Response(200) + + respx_mock.get("/api/where/current-time.json").mock(side_effect=retry_handler) + + response = await client.current_time.with_raw_response.retrieve() + + assert response.retries_taken == failures_before_success From f3b7cb00c4302b0ac1b8497835f2db0d3f9e7949 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:27:31 +0000 Subject: [PATCH 04/18] chore(internal): test updates (#52) --- src/onebusaway/_utils/_reflection.py | 2 +- tests/utils.py | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/onebusaway/_utils/_reflection.py b/src/onebusaway/_utils/_reflection.py index 9a53c7b..89aa712 100644 --- a/src/onebusaway/_utils/_reflection.py +++ b/src/onebusaway/_utils/_reflection.py @@ -34,7 +34,7 @@ def assert_signatures_in_sync( if custom_param.annotation != source_param.annotation: errors.append( - f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(source_param.annotation)}" + f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(custom_param.annotation)}" ) continue diff --git a/tests/utils.py b/tests/utils.py index d274fec..dd259a5 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -8,7 +8,7 @@ from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type -from onebusaway._types import NoneType +from onebusaway._types import Omit, NoneType from onebusaway._utils import ( is_dict, is_list, @@ -139,11 +139,15 @@ def _assert_list_type(type_: type[object], value: object) -> None: @contextlib.contextmanager -def update_env(**new_env: str) -> Iterator[None]: +def update_env(**new_env: str | Omit) -> Iterator[None]: old = os.environ.copy() try: - os.environ.update(new_env) + for name, value in new_env.items(): + if isinstance(value, Omit): + os.environ.pop(name, None) + else: + os.environ[name] = value yield None finally: From c8cbc6a1e48e42b15e42ebf40cdfd2f8fc0bc7ab Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:29:38 +0000 Subject: [PATCH 05/18] chore(internal): bump ruff version (#53) --- pyproject.toml | 12 ++++--- requirements-dev.lock | 2 +- src/onebusaway/_base_client.py | 63 +++++++++++---------------------- src/onebusaway/_compat.py | 24 +++++-------- src/onebusaway/_files.py | 12 +++---- src/onebusaway/_response.py | 12 +++---- src/onebusaway/_types.py | 9 ++--- src/onebusaway/_utils/_proxy.py | 3 +- src/onebusaway/_utils/_utils.py | 18 ++++------ tests/test_deepcopy.py | 3 +- tests/test_response.py | 12 +++---- tests/test_utils/test_typing.py | 15 +++----- 12 files changed, 65 insertions(+), 120 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c33aaf0..97bfdb1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,8 +77,8 @@ format = { chain = [ "check:ruff", "typecheck", ]} -"check:ruff" = "ruff ." -"fix:ruff" = "ruff --fix ." +"check:ruff" = "ruff check ." +"fix:ruff" = "ruff check --fix ." typecheck = { chain = [ "typecheck:pyright", @@ -162,6 +162,11 @@ reportPrivateUsage = false line-length = 120 output-format = "grouped" target-version = "py37" + +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.lint] select = [ # isort "I", @@ -192,9 +197,6 @@ unfixable = [ ] ignore-init-module-imports = true -[tool.ruff.format] -docstring-code-format = true - [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" diff --git a/requirements-dev.lock b/requirements-dev.lock index ca77645..2acdbb2 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -81,7 +81,7 @@ pytz==2023.3.post1 # via dirty-equals respx==0.20.2 rich==13.7.1 -ruff==0.1.9 +ruff==0.5.6 setuptools==68.2.2 # via nodeenv six==1.16.0 diff --git a/src/onebusaway/_base_client.py b/src/onebusaway/_base_client.py index a38363f..28c4797 100644 --- a/src/onebusaway/_base_client.py +++ b/src/onebusaway/_base_client.py @@ -124,16 +124,14 @@ def __init__( self, *, url: URL, - ) -> None: - ... + ) -> None: ... @overload def __init__( self, *, params: Query, - ) -> None: - ... + ) -> None: ... def __init__( self, @@ -166,8 +164,7 @@ def has_next_page(self) -> bool: return False return self.next_page_info() is not None - def next_page_info(self) -> Optional[PageInfo]: - ... + def next_page_info(self) -> Optional[PageInfo]: ... def _get_page_items(self) -> Iterable[_T]: # type: ignore[empty-body] ... @@ -903,8 +900,7 @@ def request( *, stream: Literal[True], stream_cls: Type[_StreamT], - ) -> _StreamT: - ... + ) -> _StreamT: ... @overload def request( @@ -914,8 +910,7 @@ def request( remaining_retries: Optional[int] = None, *, stream: Literal[False] = False, - ) -> ResponseT: - ... + ) -> ResponseT: ... @overload def request( @@ -926,8 +921,7 @@ def request( *, stream: bool = False, stream_cls: Type[_StreamT] | None = None, - ) -> ResponseT | _StreamT: - ... + ) -> ResponseT | _StreamT: ... def request( self, @@ -1156,8 +1150,7 @@ def get( cast_to: Type[ResponseT], options: RequestOptions = {}, stream: Literal[False] = False, - ) -> ResponseT: - ... + ) -> ResponseT: ... @overload def get( @@ -1168,8 +1161,7 @@ def get( options: RequestOptions = {}, stream: Literal[True], stream_cls: type[_StreamT], - ) -> _StreamT: - ... + ) -> _StreamT: ... @overload def get( @@ -1180,8 +1172,7 @@ def get( options: RequestOptions = {}, stream: bool, stream_cls: type[_StreamT] | None = None, - ) -> ResponseT | _StreamT: - ... + ) -> ResponseT | _StreamT: ... def get( self, @@ -1207,8 +1198,7 @@ def post( options: RequestOptions = {}, files: RequestFiles | None = None, stream: Literal[False] = False, - ) -> ResponseT: - ... + ) -> ResponseT: ... @overload def post( @@ -1221,8 +1211,7 @@ def post( files: RequestFiles | None = None, stream: Literal[True], stream_cls: type[_StreamT], - ) -> _StreamT: - ... + ) -> _StreamT: ... @overload def post( @@ -1235,8 +1224,7 @@ def post( files: RequestFiles | None = None, stream: bool, stream_cls: type[_StreamT] | None = None, - ) -> ResponseT | _StreamT: - ... + ) -> ResponseT | _StreamT: ... def post( self, @@ -1469,8 +1457,7 @@ async def request( *, stream: Literal[False] = False, remaining_retries: Optional[int] = None, - ) -> ResponseT: - ... + ) -> ResponseT: ... @overload async def request( @@ -1481,8 +1468,7 @@ async def request( stream: Literal[True], stream_cls: type[_AsyncStreamT], remaining_retries: Optional[int] = None, - ) -> _AsyncStreamT: - ... + ) -> _AsyncStreamT: ... @overload async def request( @@ -1493,8 +1479,7 @@ async def request( stream: bool, stream_cls: type[_AsyncStreamT] | None = None, remaining_retries: Optional[int] = None, - ) -> ResponseT | _AsyncStreamT: - ... + ) -> ResponseT | _AsyncStreamT: ... async def request( self, @@ -1709,8 +1694,7 @@ async def get( cast_to: Type[ResponseT], options: RequestOptions = {}, stream: Literal[False] = False, - ) -> ResponseT: - ... + ) -> ResponseT: ... @overload async def get( @@ -1721,8 +1705,7 @@ async def get( options: RequestOptions = {}, stream: Literal[True], stream_cls: type[_AsyncStreamT], - ) -> _AsyncStreamT: - ... + ) -> _AsyncStreamT: ... @overload async def get( @@ -1733,8 +1716,7 @@ async def get( options: RequestOptions = {}, stream: bool, stream_cls: type[_AsyncStreamT] | None = None, - ) -> ResponseT | _AsyncStreamT: - ... + ) -> ResponseT | _AsyncStreamT: ... async def get( self, @@ -1758,8 +1740,7 @@ async def post( files: RequestFiles | None = None, options: RequestOptions = {}, stream: Literal[False] = False, - ) -> ResponseT: - ... + ) -> ResponseT: ... @overload async def post( @@ -1772,8 +1753,7 @@ async def post( options: RequestOptions = {}, stream: Literal[True], stream_cls: type[_AsyncStreamT], - ) -> _AsyncStreamT: - ... + ) -> _AsyncStreamT: ... @overload async def post( @@ -1786,8 +1766,7 @@ async def post( options: RequestOptions = {}, stream: bool, stream_cls: type[_AsyncStreamT] | None = None, - ) -> ResponseT | _AsyncStreamT: - ... + ) -> ResponseT | _AsyncStreamT: ... async def post( self, diff --git a/src/onebusaway/_compat.py b/src/onebusaway/_compat.py index c919b5a..7c6f91a 100644 --- a/src/onebusaway/_compat.py +++ b/src/onebusaway/_compat.py @@ -159,22 +159,19 @@ def model_parse(model: type[_ModelT], data: Any) -> _ModelT: # generic models if TYPE_CHECKING: - class GenericModel(pydantic.BaseModel): - ... + class GenericModel(pydantic.BaseModel): ... else: if PYDANTIC_V2: # there no longer needs to be a distinction in v2 but # we still have to create our own subclass to avoid # inconsistent MRO ordering errors - class GenericModel(pydantic.BaseModel): - ... + class GenericModel(pydantic.BaseModel): ... else: import pydantic.generics - class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): - ... + class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ... # cached properties @@ -193,26 +190,21 @@ class typed_cached_property(Generic[_T]): func: Callable[[Any], _T] attrname: str | None - def __init__(self, func: Callable[[Any], _T]) -> None: - ... + def __init__(self, func: Callable[[Any], _T]) -> None: ... @overload - def __get__(self, instance: None, owner: type[Any] | None = None) -> Self: - ... + def __get__(self, instance: None, owner: type[Any] | None = None) -> Self: ... @overload - def __get__(self, instance: object, owner: type[Any] | None = None) -> _T: - ... + def __get__(self, instance: object, owner: type[Any] | None = None) -> _T: ... def __get__(self, instance: object, owner: type[Any] | None = None) -> _T | Self: raise NotImplementedError() - def __set_name__(self, owner: type[Any], name: str) -> None: - ... + def __set_name__(self, owner: type[Any], name: str) -> None: ... # __set__ is not defined at runtime, but @cached_property is designed to be settable - def __set__(self, instance: object, value: _T) -> None: - ... + def __set__(self, instance: object, value: _T) -> None: ... else: try: from functools import cached_property as cached_property diff --git a/src/onebusaway/_files.py b/src/onebusaway/_files.py index 0d2022a..715cc20 100644 --- a/src/onebusaway/_files.py +++ b/src/onebusaway/_files.py @@ -39,13 +39,11 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: @overload -def to_httpx_files(files: None) -> None: - ... +def to_httpx_files(files: None) -> None: ... @overload -def to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: - ... +def to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: ... def to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: @@ -83,13 +81,11 @@ def _read_file_content(file: FileContent) -> HttpxFileContent: @overload -async def async_to_httpx_files(files: None) -> None: - ... +async def async_to_httpx_files(files: None) -> None: ... @overload -async def async_to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: - ... +async def async_to_httpx_files(files: RequestFiles) -> HttpxRequestFiles: ... async def async_to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None: diff --git a/src/onebusaway/_response.py b/src/onebusaway/_response.py index c0ca840..1191a35 100644 --- a/src/onebusaway/_response.py +++ b/src/onebusaway/_response.py @@ -262,12 +262,10 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: class APIResponse(BaseAPIResponse[R]): @overload - def parse(self, *, to: type[_T]) -> _T: - ... + def parse(self, *, to: type[_T]) -> _T: ... @overload - def parse(self) -> R: - ... + def parse(self) -> R: ... def parse(self, *, to: type[_T] | None = None) -> R | _T: """Returns the rich python representation of this response's data. @@ -366,12 +364,10 @@ def iter_lines(self) -> Iterator[str]: class AsyncAPIResponse(BaseAPIResponse[R]): @overload - async def parse(self, *, to: type[_T]) -> _T: - ... + async def parse(self, *, to: type[_T]) -> _T: ... @overload - async def parse(self) -> R: - ... + async def parse(self) -> R: ... async def parse(self, *, to: type[_T] | None = None) -> R | _T: """Returns the rich python representation of this response's data. diff --git a/src/onebusaway/_types.py b/src/onebusaway/_types.py index 66ec7fc..f554261 100644 --- a/src/onebusaway/_types.py +++ b/src/onebusaway/_types.py @@ -111,8 +111,7 @@ class NotGiven: For example: ```py - def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: - ... + def get(timeout: Union[int, NotGiven, None] = NotGiven()) -> Response: ... get(timeout=1) # 1s timeout @@ -162,16 +161,14 @@ def build( *, response: Response, data: object, - ) -> _T: - ... + ) -> _T: ... Headers = Mapping[str, Union[str, Omit]] class HeadersLikeProtocol(Protocol): - def get(self, __key: str) -> str | None: - ... + def get(self, __key: str) -> str | None: ... HeadersLike = Union[Headers, HeadersLikeProtocol] diff --git a/src/onebusaway/_utils/_proxy.py b/src/onebusaway/_utils/_proxy.py index c46a62a..ffd883e 100644 --- a/src/onebusaway/_utils/_proxy.py +++ b/src/onebusaway/_utils/_proxy.py @@ -59,5 +59,4 @@ def __as_proxied__(self) -> T: return cast(T, self) @abstractmethod - def __load__(self) -> T: - ... + def __load__(self) -> T: ... diff --git a/src/onebusaway/_utils/_utils.py b/src/onebusaway/_utils/_utils.py index 34797c2..2fc5a1c 100644 --- a/src/onebusaway/_utils/_utils.py +++ b/src/onebusaway/_utils/_utils.py @@ -211,20 +211,17 @@ def required_args(*variants: Sequence[str]) -> Callable[[CallableT], CallableT]: Example usage: ```py @overload - def foo(*, a: str) -> str: - ... + def foo(*, a: str) -> str: ... @overload - def foo(*, b: bool) -> str: - ... + def foo(*, b: bool) -> str: ... # This enforces the same constraints that a static type checker would # i.e. that either a or b must be passed to the function @required_args(["a"], ["b"]) - def foo(*, a: str | None = None, b: bool | None = None) -> str: - ... + def foo(*, a: str | None = None, b: bool | None = None) -> str: ... ``` """ @@ -286,18 +283,15 @@ def wrapper(*args: object, **kwargs: object) -> object: @overload -def strip_not_given(obj: None) -> None: - ... +def strip_not_given(obj: None) -> None: ... @overload -def strip_not_given(obj: Mapping[_K, _V | NotGiven]) -> dict[_K, _V]: - ... +def strip_not_given(obj: Mapping[_K, _V | NotGiven]) -> dict[_K, _V]: ... @overload -def strip_not_given(obj: object) -> object: - ... +def strip_not_given(obj: object) -> object: ... def strip_not_given(obj: object | None) -> object: diff --git a/tests/test_deepcopy.py b/tests/test_deepcopy.py index 519c9b1..5da235a 100644 --- a/tests/test_deepcopy.py +++ b/tests/test_deepcopy.py @@ -41,8 +41,7 @@ def test_nested_list() -> None: assert_different_identities(obj1[1], obj2[1]) -class MyObject: - ... +class MyObject: ... def test_ignores_other_types() -> None: diff --git a/tests/test_response.py b/tests/test_response.py index 9e02d05..df94f16 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -19,16 +19,13 @@ from onebusaway._base_client import FinalRequestOptions -class ConcreteBaseAPIResponse(APIResponse[bytes]): - ... +class ConcreteBaseAPIResponse(APIResponse[bytes]): ... -class ConcreteAPIResponse(APIResponse[List[str]]): - ... +class ConcreteAPIResponse(APIResponse[List[str]]): ... -class ConcreteAsyncAPIResponse(APIResponse[httpx.Response]): - ... +class ConcreteAsyncAPIResponse(APIResponse[httpx.Response]): ... def test_extract_response_type_direct_classes() -> None: @@ -56,8 +53,7 @@ def test_extract_response_type_binary_response() -> None: assert extract_response_type(AsyncBinaryAPIResponse) == bytes -class PydanticModel(pydantic.BaseModel): - ... +class PydanticModel(pydantic.BaseModel): ... def test_response_parse_mismatched_basemodel(client: OnebusawaySDK) -> None: diff --git a/tests/test_utils/test_typing.py b/tests/test_utils/test_typing.py index c6438ff..1f6e80a 100644 --- a/tests/test_utils/test_typing.py +++ b/tests/test_utils/test_typing.py @@ -9,24 +9,19 @@ _T3 = TypeVar("_T3") -class BaseGeneric(Generic[_T]): - ... +class BaseGeneric(Generic[_T]): ... -class SubclassGeneric(BaseGeneric[_T]): - ... +class SubclassGeneric(BaseGeneric[_T]): ... -class BaseGenericMultipleTypeArgs(Generic[_T, _T2, _T3]): - ... +class BaseGenericMultipleTypeArgs(Generic[_T, _T2, _T3]): ... -class SubclassGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T, _T2, _T3]): - ... +class SubclassGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T, _T2, _T3]): ... -class SubclassDifferentOrderGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T2, _T, _T3]): - ... +class SubclassDifferentOrderGenericMultipleTypeArgs(BaseGenericMultipleTypeArgs[_T2, _T, _T3]): ... def test_extract_type_var() -> None: From 1f501f0592c92e86c4c027f652a49ff11a068715 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:30:29 +0000 Subject: [PATCH 06/18] chore(internal): update pydantic compat helper function (#54) --- src/onebusaway/_compat.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/onebusaway/_compat.py b/src/onebusaway/_compat.py index 7c6f91a..21fe694 100644 --- a/src/onebusaway/_compat.py +++ b/src/onebusaway/_compat.py @@ -7,7 +7,7 @@ import pydantic from pydantic.fields import FieldInfo -from ._types import StrBytesIntFloat +from ._types import IncEx, StrBytesIntFloat _T = TypeVar("_T") _ModelT = TypeVar("_ModelT", bound=pydantic.BaseModel) @@ -133,17 +133,20 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: def model_dump( model: pydantic.BaseModel, *, + exclude: IncEx = None, exclude_unset: bool = False, exclude_defaults: bool = False, ) -> dict[str, Any]: if PYDANTIC_V2: return model.model_dump( + exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, ) return cast( "dict[str, Any]", model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast] + exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, ), From 9adae4de96b8ea11ff8e2d7c251183580f86cf8a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 09:04:09 +0000 Subject: [PATCH 07/18] feat(api): OpenAPI spec update via Stainless API (#55) --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index f38736f..b17a6c5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-745fc14b503259d6b0d29d50d4277b86cada74faf6f831bb19710d2e7ead8a7c.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-6579f942268e5d39432a6348fbf1eb5850e71235e72797ed78894a3329fbb25e.yml From 1882cdc8a4da9705c853ed6f5d5e8d73a4b9276c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 09:48:06 +0000 Subject: [PATCH 08/18] feat(api): OpenAPI spec update via Stainless API (#56) --- .stats.yml | 4 +- api.md | 12 ++ src/onebusaway/_client.py | 8 + src/onebusaway/resources/__init__.py | 14 ++ src/onebusaway/resources/routes_for_agency.py | 141 ++++++++++++++++++ src/onebusaway/types/__init__.py | 1 + .../types/routes_for_agency_list_response.py | 45 ++++++ tests/api_resources/test_routes_for_agency.py | 98 ++++++++++++ 8 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 src/onebusaway/resources/routes_for_agency.py create mode 100644 src/onebusaway/types/routes_for_agency_list_response.py create mode 100644 tests/api_resources/test_routes_for_agency.py diff --git a/.stats.yml b/.stats.yml index b17a6c5..2f8fb74 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 18 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-6579f942268e5d39432a6348fbf1eb5850e71235e72797ed78894a3329fbb25e.yml +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-321de3032fb9e1dd70c112bc3f172d12a36692f8fcfa2e8aec47ab6a85ca37e2.yml diff --git a/api.md b/api.md index 1aa1c4c..ff6371d 100644 --- a/api.md +++ b/api.md @@ -148,6 +148,18 @@ Methods: - client.route_ids_for_agency.list(agency_id) -> RouteIDsForAgencyListResponse +# RoutesForAgency + +Types: + +```python +from onebusaway.types import RoutesForAgencyListResponse +``` + +Methods: + +- client.routes_for_agency.list(agency_id) -> RoutesForAgencyListResponse + # ArrivalAndDeparture Types: diff --git a/src/onebusaway/_client.py b/src/onebusaway/_client.py index 12680ce..0103aaa 100644 --- a/src/onebusaway/_client.py +++ b/src/onebusaway/_client.py @@ -58,6 +58,7 @@ class OnebusawaySDK(SyncAPIClient): schedule_for_stop: resources.ScheduleForStopResource route: resources.RouteResource route_ids_for_agency: resources.RouteIDsForAgencyResource + routes_for_agency: resources.RoutesForAgencyResource arrival_and_departure: resources.ArrivalAndDepartureResource trip: resources.TripResource trips_for_location: resources.TripsForLocationResource @@ -132,6 +133,7 @@ def __init__( self.schedule_for_stop = resources.ScheduleForStopResource(self) self.route = resources.RouteResource(self) self.route_ids_for_agency = resources.RouteIDsForAgencyResource(self) + self.routes_for_agency = resources.RoutesForAgencyResource(self) self.arrival_and_departure = resources.ArrivalAndDepartureResource(self) self.trip = resources.TripResource(self) self.trips_for_location = resources.TripsForLocationResource(self) @@ -266,6 +268,7 @@ class AsyncOnebusawaySDK(AsyncAPIClient): schedule_for_stop: resources.AsyncScheduleForStopResource route: resources.AsyncRouteResource route_ids_for_agency: resources.AsyncRouteIDsForAgencyResource + routes_for_agency: resources.AsyncRoutesForAgencyResource arrival_and_departure: resources.AsyncArrivalAndDepartureResource trip: resources.AsyncTripResource trips_for_location: resources.AsyncTripsForLocationResource @@ -340,6 +343,7 @@ def __init__( self.schedule_for_stop = resources.AsyncScheduleForStopResource(self) self.route = resources.AsyncRouteResource(self) self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResource(self) + self.routes_for_agency = resources.AsyncRoutesForAgencyResource(self) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResource(self) self.trip = resources.AsyncTripResource(self) self.trips_for_location = resources.AsyncTripsForLocationResource(self) @@ -477,6 +481,7 @@ def __init__(self, client: OnebusawaySDK) -> None: self.schedule_for_stop = resources.ScheduleForStopResourceWithRawResponse(client.schedule_for_stop) self.route = resources.RouteResourceWithRawResponse(client.route) self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) + self.routes_for_agency = resources.RoutesForAgencyResourceWithRawResponse(client.routes_for_agency) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithRawResponse(client.arrival_and_departure) self.trip = resources.TripResourceWithRawResponse(client.trip) self.trips_for_location = resources.TripsForLocationResourceWithRawResponse(client.trips_for_location) @@ -500,6 +505,7 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: self.schedule_for_stop = resources.AsyncScheduleForStopResourceWithRawResponse(client.schedule_for_stop) self.route = resources.AsyncRouteResourceWithRawResponse(client.route) self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) + self.routes_for_agency = resources.AsyncRoutesForAgencyResourceWithRawResponse(client.routes_for_agency) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithRawResponse( client.arrival_and_departure ) @@ -527,6 +533,7 @@ def __init__(self, client: OnebusawaySDK) -> None: self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithStreamingResponse( client.route_ids_for_agency ) + self.routes_for_agency = resources.RoutesForAgencyResourceWithStreamingResponse(client.routes_for_agency) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithStreamingResponse( client.arrival_and_departure ) @@ -560,6 +567,7 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithStreamingResponse( client.route_ids_for_agency ) + self.routes_for_agency = resources.AsyncRoutesForAgencyResourceWithStreamingResponse(client.routes_for_agency) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithStreamingResponse( client.arrival_and_departure ) diff --git a/src/onebusaway/resources/__init__.py b/src/onebusaway/resources/__init__.py index 53d412c..944a791 100644 --- a/src/onebusaway/resources/__init__.py +++ b/src/onebusaway/resources/__init__.py @@ -72,6 +72,14 @@ TripForVehicleResourceWithStreamingResponse, AsyncTripForVehicleResourceWithStreamingResponse, ) +from .routes_for_agency import ( + RoutesForAgencyResource, + AsyncRoutesForAgencyResource, + RoutesForAgencyResourceWithRawResponse, + AsyncRoutesForAgencyResourceWithRawResponse, + RoutesForAgencyResourceWithStreamingResponse, + AsyncRoutesForAgencyResourceWithStreamingResponse, +) from .schedule_for_stop import ( ScheduleForStopResource, AsyncScheduleForStopResource, @@ -210,6 +218,12 @@ "AsyncRouteIDsForAgencyResourceWithRawResponse", "RouteIDsForAgencyResourceWithStreamingResponse", "AsyncRouteIDsForAgencyResourceWithStreamingResponse", + "RoutesForAgencyResource", + "AsyncRoutesForAgencyResource", + "RoutesForAgencyResourceWithRawResponse", + "AsyncRoutesForAgencyResourceWithRawResponse", + "RoutesForAgencyResourceWithStreamingResponse", + "AsyncRoutesForAgencyResourceWithStreamingResponse", "ArrivalAndDepartureResource", "AsyncArrivalAndDepartureResource", "ArrivalAndDepartureResourceWithRawResponse", diff --git a/src/onebusaway/resources/routes_for_agency.py b/src/onebusaway/resources/routes_for_agency.py new file mode 100644 index 0000000..637eefe --- /dev/null +++ b/src/onebusaway/resources/routes_for_agency.py @@ -0,0 +1,141 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.routes_for_agency_list_response import RoutesForAgencyListResponse + +__all__ = ["RoutesForAgencyResource", "AsyncRoutesForAgencyResource"] + + +class RoutesForAgencyResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> RoutesForAgencyResourceWithRawResponse: + return RoutesForAgencyResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> RoutesForAgencyResourceWithStreamingResponse: + return RoutesForAgencyResourceWithStreamingResponse(self) + + def list( + self, + agency_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> RoutesForAgencyListResponse: + """ + Retrieve the list of all routes for a particular agency by id + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agency_id: + raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") + return self._get( + f"/api/where/routes-for-agency/agencyID.json", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RoutesForAgencyListResponse, + ) + + +class AsyncRoutesForAgencyResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncRoutesForAgencyResourceWithRawResponse: + return AsyncRoutesForAgencyResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncRoutesForAgencyResourceWithStreamingResponse: + return AsyncRoutesForAgencyResourceWithStreamingResponse(self) + + async def list( + self, + agency_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> RoutesForAgencyListResponse: + """ + Retrieve the list of all routes for a particular agency by id + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agency_id: + raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") + return await self._get( + f"/api/where/routes-for-agency/agencyID.json", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=RoutesForAgencyListResponse, + ) + + +class RoutesForAgencyResourceWithRawResponse: + def __init__(self, routes_for_agency: RoutesForAgencyResource) -> None: + self._routes_for_agency = routes_for_agency + + self.list = to_raw_response_wrapper( + routes_for_agency.list, + ) + + +class AsyncRoutesForAgencyResourceWithRawResponse: + def __init__(self, routes_for_agency: AsyncRoutesForAgencyResource) -> None: + self._routes_for_agency = routes_for_agency + + self.list = async_to_raw_response_wrapper( + routes_for_agency.list, + ) + + +class RoutesForAgencyResourceWithStreamingResponse: + def __init__(self, routes_for_agency: RoutesForAgencyResource) -> None: + self._routes_for_agency = routes_for_agency + + self.list = to_streamed_response_wrapper( + routes_for_agency.list, + ) + + +class AsyncRoutesForAgencyResourceWithStreamingResponse: + def __init__(self, routes_for_agency: AsyncRoutesForAgencyResource) -> None: + self._routes_for_agency = routes_for_agency + + self.list = async_to_streamed_response_wrapper( + routes_for_agency.list, + ) diff --git a/src/onebusaway/types/__init__.py b/src/onebusaway/types/__init__.py index a8bf612..85cef90 100644 --- a/src/onebusaway/types/__init__.py +++ b/src/onebusaway/types/__init__.py @@ -13,6 +13,7 @@ from .stops_for_route_list_response import StopsForRouteListResponse as StopsForRouteListResponse from .trip_detail_retrieve_response import TripDetailRetrieveResponse as TripDetailRetrieveResponse from .current_time_retrieve_response import CurrentTimeRetrieveResponse as CurrentTimeRetrieveResponse +from .routes_for_agency_list_response import RoutesForAgencyListResponse as RoutesForAgencyListResponse from .vehicles_for_agency_list_params import VehiclesForAgencyListParams as VehiclesForAgencyListParams from .trip_for_vehicle_retrieve_params import TripForVehicleRetrieveParams as TripForVehicleRetrieveParams from .arrival_and_departure_list_params import ArrivalAndDepartureListParams as ArrivalAndDepartureListParams diff --git a/src/onebusaway/types/routes_for_agency_list_response.py b/src/onebusaway/types/routes_for_agency_list_response.py new file mode 100644 index 0000000..5ff3242 --- /dev/null +++ b/src/onebusaway/types/routes_for_agency_list_response.py @@ -0,0 +1,45 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .shared.references import References +from .shared.response_wrapper import ResponseWrapper + +__all__ = ["RoutesForAgencyListResponse", "RoutesForAgencyListResponseData", "RoutesForAgencyListResponseDataList"] + + +class RoutesForAgencyListResponseDataList(BaseModel): + id: Optional[str] = None + + agency_id: Optional[str] = FieldInfo(alias="agencyId", default=None) + + color: Optional[str] = None + + description: Optional[str] = None + + long_name: Optional[str] = FieldInfo(alias="longName", default=None) + + null_safe_short_name: Optional[str] = FieldInfo(alias="nullSafeShortName", default=None) + + short_name: Optional[str] = FieldInfo(alias="shortName", default=None) + + text_color: Optional[str] = FieldInfo(alias="textColor", default=None) + + type: Optional[int] = None + + url: Optional[str] = None + + +class RoutesForAgencyListResponseData(BaseModel): + limit_exceeded: bool = FieldInfo(alias="limitExceeded") + + list: List[RoutesForAgencyListResponseDataList] + + references: References + + +class RoutesForAgencyListResponse(ResponseWrapper): + data: RoutesForAgencyListResponseData diff --git a/tests/api_resources/test_routes_for_agency.py b/tests/api_resources/test_routes_for_agency.py new file mode 100644 index 0000000..1fe2d56 --- /dev/null +++ b/tests/api_resources/test_routes_for_agency.py @@ -0,0 +1,98 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from onebusaway import OnebusawaySDK, AsyncOnebusawaySDK +from tests.utils import assert_matches_type +from onebusaway.types import RoutesForAgencyListResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestRoutesForAgency: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_list(self, client: OnebusawaySDK) -> None: + routes_for_agency = client.routes_for_agency.list( + "agencyID", + ) + assert_matches_type(RoutesForAgencyListResponse, routes_for_agency, path=["response"]) + + @parametrize + def test_raw_response_list(self, client: OnebusawaySDK) -> None: + response = client.routes_for_agency.with_raw_response.list( + "agencyID", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + routes_for_agency = response.parse() + assert_matches_type(RoutesForAgencyListResponse, routes_for_agency, path=["response"]) + + @parametrize + def test_streaming_response_list(self, client: OnebusawaySDK) -> None: + with client.routes_for_agency.with_streaming_response.list( + "agencyID", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + routes_for_agency = response.parse() + assert_matches_type(RoutesForAgencyListResponse, routes_for_agency, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_list(self, client: OnebusawaySDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agency_id` but received ''"): + client.routes_for_agency.with_raw_response.list( + "", + ) + + +class TestAsyncRoutesForAgency: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_list(self, async_client: AsyncOnebusawaySDK) -> None: + routes_for_agency = await async_client.routes_for_agency.list( + "agencyID", + ) + assert_matches_type(RoutesForAgencyListResponse, routes_for_agency, path=["response"]) + + @parametrize + async def test_raw_response_list(self, async_client: AsyncOnebusawaySDK) -> None: + response = await async_client.routes_for_agency.with_raw_response.list( + "agencyID", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + routes_for_agency = await response.parse() + assert_matches_type(RoutesForAgencyListResponse, routes_for_agency, path=["response"]) + + @parametrize + async def test_streaming_response_list(self, async_client: AsyncOnebusawaySDK) -> None: + async with async_client.routes_for_agency.with_streaming_response.list( + "agencyID", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + routes_for_agency = await response.parse() + assert_matches_type(RoutesForAgencyListResponse, routes_for_agency, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_list(self, async_client: AsyncOnebusawaySDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agency_id` but received ''"): + await async_client.routes_for_agency.with_raw_response.list( + "", + ) From 5c8a7ee00dcd4ab6a3a9b6800fe10f7447d79c61 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:29:25 +0000 Subject: [PATCH 09/18] feat(api): OpenAPI spec update via Stainless API (#57) --- .stats.yml | 4 +- api.md | 12 ++ src/onebusaway/_client.py | 10 ++ src/onebusaway/resources/__init__.py | 14 ++ .../resources/schedule_for_route.py | 166 ++++++++++++++++++ src/onebusaway/types/__init__.py | 2 + .../schedule_for_route_retrieve_params.py | 15 ++ .../schedule_for_route_retrieve_response.py | 131 ++++++++++++++ .../api_resources/test_schedule_for_route.py | 114 ++++++++++++ 9 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 src/onebusaway/resources/schedule_for_route.py create mode 100644 src/onebusaway/types/schedule_for_route_retrieve_params.py create mode 100644 src/onebusaway/types/schedule_for_route_retrieve_response.py create mode 100644 tests/api_resources/test_schedule_for_route.py diff --git a/.stats.yml b/.stats.yml index 2f8fb74..1da4201 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-321de3032fb9e1dd70c112bc3f172d12a36692f8fcfa2e8aec47ab6a85ca37e2.yml +configured_endpoints: 20 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-681949f64ed7ba8d43a08daba3e5dfcee447cecc48a0a03fcf2aedef3b656641.yml diff --git a/api.md b/api.md index ff6371d..40f0d90 100644 --- a/api.md +++ b/api.md @@ -160,6 +160,18 @@ Methods: - client.routes_for_agency.list(agency_id) -> RoutesForAgencyListResponse +# ScheduleForRoute + +Types: + +```python +from onebusaway.types import ScheduleForRouteRetrieveResponse +``` + +Methods: + +- client.schedule_for_route.retrieve(route_id, \*\*params) -> ScheduleForRouteRetrieveResponse + # ArrivalAndDeparture Types: diff --git a/src/onebusaway/_client.py b/src/onebusaway/_client.py index 0103aaa..166e73c 100644 --- a/src/onebusaway/_client.py +++ b/src/onebusaway/_client.py @@ -59,6 +59,7 @@ class OnebusawaySDK(SyncAPIClient): route: resources.RouteResource route_ids_for_agency: resources.RouteIDsForAgencyResource routes_for_agency: resources.RoutesForAgencyResource + schedule_for_route: resources.ScheduleForRouteResource arrival_and_departure: resources.ArrivalAndDepartureResource trip: resources.TripResource trips_for_location: resources.TripsForLocationResource @@ -134,6 +135,7 @@ def __init__( self.route = resources.RouteResource(self) self.route_ids_for_agency = resources.RouteIDsForAgencyResource(self) self.routes_for_agency = resources.RoutesForAgencyResource(self) + self.schedule_for_route = resources.ScheduleForRouteResource(self) self.arrival_and_departure = resources.ArrivalAndDepartureResource(self) self.trip = resources.TripResource(self) self.trips_for_location = resources.TripsForLocationResource(self) @@ -269,6 +271,7 @@ class AsyncOnebusawaySDK(AsyncAPIClient): route: resources.AsyncRouteResource route_ids_for_agency: resources.AsyncRouteIDsForAgencyResource routes_for_agency: resources.AsyncRoutesForAgencyResource + schedule_for_route: resources.AsyncScheduleForRouteResource arrival_and_departure: resources.AsyncArrivalAndDepartureResource trip: resources.AsyncTripResource trips_for_location: resources.AsyncTripsForLocationResource @@ -344,6 +347,7 @@ def __init__( self.route = resources.AsyncRouteResource(self) self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResource(self) self.routes_for_agency = resources.AsyncRoutesForAgencyResource(self) + self.schedule_for_route = resources.AsyncScheduleForRouteResource(self) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResource(self) self.trip = resources.AsyncTripResource(self) self.trips_for_location = resources.AsyncTripsForLocationResource(self) @@ -482,6 +486,7 @@ def __init__(self, client: OnebusawaySDK) -> None: self.route = resources.RouteResourceWithRawResponse(client.route) self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) self.routes_for_agency = resources.RoutesForAgencyResourceWithRawResponse(client.routes_for_agency) + self.schedule_for_route = resources.ScheduleForRouteResourceWithRawResponse(client.schedule_for_route) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithRawResponse(client.arrival_and_departure) self.trip = resources.TripResourceWithRawResponse(client.trip) self.trips_for_location = resources.TripsForLocationResourceWithRawResponse(client.trips_for_location) @@ -506,6 +511,7 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: self.route = resources.AsyncRouteResourceWithRawResponse(client.route) self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) self.routes_for_agency = resources.AsyncRoutesForAgencyResourceWithRawResponse(client.routes_for_agency) + self.schedule_for_route = resources.AsyncScheduleForRouteResourceWithRawResponse(client.schedule_for_route) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithRawResponse( client.arrival_and_departure ) @@ -534,6 +540,7 @@ def __init__(self, client: OnebusawaySDK) -> None: client.route_ids_for_agency ) self.routes_for_agency = resources.RoutesForAgencyResourceWithStreamingResponse(client.routes_for_agency) + self.schedule_for_route = resources.ScheduleForRouteResourceWithStreamingResponse(client.schedule_for_route) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithStreamingResponse( client.arrival_and_departure ) @@ -568,6 +575,9 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: client.route_ids_for_agency ) self.routes_for_agency = resources.AsyncRoutesForAgencyResourceWithStreamingResponse(client.routes_for_agency) + self.schedule_for_route = resources.AsyncScheduleForRouteResourceWithStreamingResponse( + client.schedule_for_route + ) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithStreamingResponse( client.arrival_and_departure ) diff --git a/src/onebusaway/resources/__init__.py b/src/onebusaway/resources/__init__.py index 944a791..b7e6b33 100644 --- a/src/onebusaway/resources/__init__.py +++ b/src/onebusaway/resources/__init__.py @@ -88,6 +88,14 @@ ScheduleForStopResourceWithStreamingResponse, AsyncScheduleForStopResourceWithStreamingResponse, ) +from .schedule_for_route import ( + ScheduleForRouteResource, + AsyncScheduleForRouteResource, + ScheduleForRouteResourceWithRawResponse, + AsyncScheduleForRouteResourceWithRawResponse, + ScheduleForRouteResourceWithStreamingResponse, + AsyncScheduleForRouteResourceWithStreamingResponse, +) from .stops_for_location import ( StopsForLocationResource, AsyncStopsForLocationResource, @@ -224,6 +232,12 @@ "AsyncRoutesForAgencyResourceWithRawResponse", "RoutesForAgencyResourceWithStreamingResponse", "AsyncRoutesForAgencyResourceWithStreamingResponse", + "ScheduleForRouteResource", + "AsyncScheduleForRouteResource", + "ScheduleForRouteResourceWithRawResponse", + "AsyncScheduleForRouteResourceWithRawResponse", + "ScheduleForRouteResourceWithStreamingResponse", + "AsyncScheduleForRouteResourceWithStreamingResponse", "ArrivalAndDepartureResource", "AsyncArrivalAndDepartureResource", "ArrivalAndDepartureResourceWithRawResponse", diff --git a/src/onebusaway/resources/schedule_for_route.py b/src/onebusaway/resources/schedule_for_route.py new file mode 100644 index 0000000..74516bb --- /dev/null +++ b/src/onebusaway/resources/schedule_for_route.py @@ -0,0 +1,166 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import schedule_for_route_retrieve_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import ( + maybe_transform, + async_maybe_transform, +) +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.schedule_for_route_retrieve_response import ScheduleForRouteRetrieveResponse + +__all__ = ["ScheduleForRouteResource", "AsyncScheduleForRouteResource"] + + +class ScheduleForRouteResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ScheduleForRouteResourceWithRawResponse: + return ScheduleForRouteResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ScheduleForRouteResourceWithStreamingResponse: + return ScheduleForRouteResourceWithStreamingResponse(self) + + def retrieve( + self, + route_id: str, + *, + date: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ScheduleForRouteRetrieveResponse: + """ + Retrieve the full schedule for a route on a particular day + + Args: + date: The date for which you want to request a schedule in the format YYYY-MM-DD + (optional, defaults to current date) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not route_id: + raise ValueError(f"Expected a non-empty value for `route_id` but received {route_id!r}") + return self._get( + f"/api/where/schedule-for-route/routeID.json", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"date": date}, schedule_for_route_retrieve_params.ScheduleForRouteRetrieveParams + ), + ), + cast_to=ScheduleForRouteRetrieveResponse, + ) + + +class AsyncScheduleForRouteResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncScheduleForRouteResourceWithRawResponse: + return AsyncScheduleForRouteResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncScheduleForRouteResourceWithStreamingResponse: + return AsyncScheduleForRouteResourceWithStreamingResponse(self) + + async def retrieve( + self, + route_id: str, + *, + date: str | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> ScheduleForRouteRetrieveResponse: + """ + Retrieve the full schedule for a route on a particular day + + Args: + date: The date for which you want to request a schedule in the format YYYY-MM-DD + (optional, defaults to current date) + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not route_id: + raise ValueError(f"Expected a non-empty value for `route_id` but received {route_id!r}") + return await self._get( + f"/api/where/schedule-for-route/routeID.json", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"date": date}, schedule_for_route_retrieve_params.ScheduleForRouteRetrieveParams + ), + ), + cast_to=ScheduleForRouteRetrieveResponse, + ) + + +class ScheduleForRouteResourceWithRawResponse: + def __init__(self, schedule_for_route: ScheduleForRouteResource) -> None: + self._schedule_for_route = schedule_for_route + + self.retrieve = to_raw_response_wrapper( + schedule_for_route.retrieve, + ) + + +class AsyncScheduleForRouteResourceWithRawResponse: + def __init__(self, schedule_for_route: AsyncScheduleForRouteResource) -> None: + self._schedule_for_route = schedule_for_route + + self.retrieve = async_to_raw_response_wrapper( + schedule_for_route.retrieve, + ) + + +class ScheduleForRouteResourceWithStreamingResponse: + def __init__(self, schedule_for_route: ScheduleForRouteResource) -> None: + self._schedule_for_route = schedule_for_route + + self.retrieve = to_streamed_response_wrapper( + schedule_for_route.retrieve, + ) + + +class AsyncScheduleForRouteResourceWithStreamingResponse: + def __init__(self, schedule_for_route: AsyncScheduleForRouteResource) -> None: + self._schedule_for_route = schedule_for_route + + self.retrieve = async_to_streamed_response_wrapper( + schedule_for_route.retrieve, + ) diff --git a/src/onebusaway/types/__init__.py b/src/onebusaway/types/__init__.py index 85cef90..939c0fb 100644 --- a/src/onebusaway/types/__init__.py +++ b/src/onebusaway/types/__init__.py @@ -21,11 +21,13 @@ from .stop_ids_for_agency_list_response import StopIDsForAgencyListResponse as StopIDsForAgencyListResponse from .vehicles_for_agency_list_response import VehiclesForAgencyListResponse as VehiclesForAgencyListResponse from .route_ids_for_agency_list_response import RouteIDsForAgencyListResponse as RouteIDsForAgencyListResponse +from .schedule_for_route_retrieve_params import ScheduleForRouteRetrieveParams as ScheduleForRouteRetrieveParams from .stops_for_location_retrieve_params import StopsForLocationRetrieveParams as StopsForLocationRetrieveParams from .trip_for_vehicle_retrieve_response import TripForVehicleRetrieveResponse as TripForVehicleRetrieveResponse from .trips_for_location_retrieve_params import TripsForLocationRetrieveParams as TripsForLocationRetrieveParams from .arrival_and_departure_list_response import ArrivalAndDepartureListResponse as ArrivalAndDepartureListResponse from .schedule_for_stop_retrieve_response import ScheduleForStopRetrieveResponse as ScheduleForStopRetrieveResponse +from .schedule_for_route_retrieve_response import ScheduleForRouteRetrieveResponse as ScheduleForRouteRetrieveResponse from .stops_for_location_retrieve_response import StopsForLocationRetrieveResponse as StopsForLocationRetrieveResponse from .trips_for_location_retrieve_response import TripsForLocationRetrieveResponse as TripsForLocationRetrieveResponse from .arrival_and_departure_retrieve_params import ( diff --git a/src/onebusaway/types/schedule_for_route_retrieve_params.py b/src/onebusaway/types/schedule_for_route_retrieve_params.py new file mode 100644 index 0000000..0ba5bcf --- /dev/null +++ b/src/onebusaway/types/schedule_for_route_retrieve_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ScheduleForRouteRetrieveParams"] + + +class ScheduleForRouteRetrieveParams(TypedDict, total=False): + date: str + """ + The date for which you want to request a schedule in the format YYYY-MM-DD + (optional, defaults to current date) + """ diff --git a/src/onebusaway/types/schedule_for_route_retrieve_response.py b/src/onebusaway/types/schedule_for_route_retrieve_response.py new file mode 100644 index 0000000..1c68056 --- /dev/null +++ b/src/onebusaway/types/schedule_for_route_retrieve_response.py @@ -0,0 +1,131 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .shared.response_wrapper import ResponseWrapper + +__all__ = [ + "ScheduleForRouteRetrieveResponse", + "ScheduleForRouteRetrieveResponseData", + "ScheduleForRouteRetrieveResponseDataEntry", + "ScheduleForRouteRetrieveResponseDataEntryStop", + "ScheduleForRouteRetrieveResponseDataEntryStopTripGrouping", + "ScheduleForRouteRetrieveResponseDataEntryStopTripGroupingTripsWithStopTime", + "ScheduleForRouteRetrieveResponseDataEntryStopTripGroupingTripsWithStopTimeStopTime", + "ScheduleForRouteRetrieveResponseDataEntryTrip", +] + + +class ScheduleForRouteRetrieveResponseDataEntryStop(BaseModel): + id: str + + code: str + + lat: float + + lon: float + + name: str + + direction: Optional[str] = None + + location_type: Optional[int] = FieldInfo(alias="locationType", default=None) + + parent: Optional[str] = None + + route_ids: Optional[List[str]] = FieldInfo(alias="routeIds", default=None) + + static_route_ids: Optional[List[str]] = FieldInfo(alias="staticRouteIds", default=None) + + wheelchair_boarding: Optional[str] = FieldInfo(alias="wheelchairBoarding", default=None) + + +class ScheduleForRouteRetrieveResponseDataEntryStopTripGroupingTripsWithStopTimeStopTime(BaseModel): + arrival_enabled: bool = FieldInfo(alias="arrivalEnabled") + + arrival_time: int = FieldInfo(alias="arrivalTime") + + departure_enabled: bool = FieldInfo(alias="departureEnabled") + + departure_time: int = FieldInfo(alias="departureTime") + + stop_id: str = FieldInfo(alias="stopId") + + trip_id: str = FieldInfo(alias="tripId") + + service_id: Optional[str] = FieldInfo(alias="serviceId", default=None) + + stop_headsign: Optional[str] = FieldInfo(alias="stopHeadsign", default=None) + + +class ScheduleForRouteRetrieveResponseDataEntryStopTripGroupingTripsWithStopTime(BaseModel): + stop_times: List[ScheduleForRouteRetrieveResponseDataEntryStopTripGroupingTripsWithStopTimeStopTime] = FieldInfo( + alias="stopTimes" + ) + + trip_id: str = FieldInfo(alias="tripId") + + +class ScheduleForRouteRetrieveResponseDataEntryStopTripGrouping(BaseModel): + direction_id: str = FieldInfo(alias="directionId") + + stop_ids: List[str] = FieldInfo(alias="stopIds") + + trip_headsigns: List[str] = FieldInfo(alias="tripHeadsigns") + + trip_ids: List[str] = FieldInfo(alias="tripIds") + + trips_with_stop_times: Optional[ + List[ScheduleForRouteRetrieveResponseDataEntryStopTripGroupingTripsWithStopTime] + ] = FieldInfo(alias="tripsWithStopTimes", default=None) + + +class ScheduleForRouteRetrieveResponseDataEntryTrip(BaseModel): + id: str + + route_id: str = FieldInfo(alias="routeId") + + block_id: Optional[str] = FieldInfo(alias="blockId", default=None) + + direction_id: Optional[str] = FieldInfo(alias="directionId", default=None) + + peak_offpeak: Optional[int] = FieldInfo(alias="peakOffpeak", default=None) + + route_short_name: Optional[str] = FieldInfo(alias="routeShortName", default=None) + + service_id: Optional[str] = FieldInfo(alias="serviceId", default=None) + + shape_id: Optional[str] = FieldInfo(alias="shapeId", default=None) + + time_zone: Optional[str] = FieldInfo(alias="timeZone", default=None) + + trip_headsign: Optional[str] = FieldInfo(alias="tripHeadsign", default=None) + + trip_short_name: Optional[str] = FieldInfo(alias="tripShortName", default=None) + + +class ScheduleForRouteRetrieveResponseDataEntry(BaseModel): + route_id: str = FieldInfo(alias="routeId") + + schedule_date: int = FieldInfo(alias="scheduleDate") + + service_ids: List[str] = FieldInfo(alias="serviceIds") + + stops: List[ScheduleForRouteRetrieveResponseDataEntryStop] + + stop_trip_groupings: List[ScheduleForRouteRetrieveResponseDataEntryStopTripGrouping] = FieldInfo( + alias="stopTripGroupings" + ) + + trips: List[ScheduleForRouteRetrieveResponseDataEntryTrip] + + +class ScheduleForRouteRetrieveResponseData(BaseModel): + entry: ScheduleForRouteRetrieveResponseDataEntry + + +class ScheduleForRouteRetrieveResponse(ResponseWrapper): + data: ScheduleForRouteRetrieveResponseData diff --git a/tests/api_resources/test_schedule_for_route.py b/tests/api_resources/test_schedule_for_route.py new file mode 100644 index 0000000..a7ff884 --- /dev/null +++ b/tests/api_resources/test_schedule_for_route.py @@ -0,0 +1,114 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from onebusaway import OnebusawaySDK, AsyncOnebusawaySDK +from tests.utils import assert_matches_type +from onebusaway.types import ScheduleForRouteRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestScheduleForRoute: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: OnebusawaySDK) -> None: + schedule_for_route = client.schedule_for_route.retrieve( + route_id="1_100223", + ) + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + @parametrize + def test_method_retrieve_with_all_params(self, client: OnebusawaySDK) -> None: + schedule_for_route = client.schedule_for_route.retrieve( + route_id="1_100223", + date="date", + ) + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: OnebusawaySDK) -> None: + response = client.schedule_for_route.with_raw_response.retrieve( + route_id="1_100223", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule_for_route = response.parse() + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: OnebusawaySDK) -> None: + with client.schedule_for_route.with_streaming_response.retrieve( + route_id="1_100223", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule_for_route = response.parse() + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_retrieve(self, client: OnebusawaySDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `route_id` but received ''"): + client.schedule_for_route.with_raw_response.retrieve( + route_id="", + ) + + +class TestAsyncScheduleForRoute: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + schedule_for_route = await async_client.schedule_for_route.retrieve( + route_id="1_100223", + ) + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncOnebusawaySDK) -> None: + schedule_for_route = await async_client.schedule_for_route.retrieve( + route_id="1_100223", + date="date", + ) + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + response = await async_client.schedule_for_route.with_raw_response.retrieve( + route_id="1_100223", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule_for_route = await response.parse() + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + async with async_client.schedule_for_route.with_streaming_response.retrieve( + route_id="1_100223", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule_for_route = await response.parse() + assert_matches_type(ScheduleForRouteRetrieveResponse, schedule_for_route, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `route_id` but received ''"): + await async_client.schedule_for_route.with_raw_response.retrieve( + route_id="", + ) From 29edb45798ad111a1a4f6ce5bbbbadfe3e9099d8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:44:56 +0000 Subject: [PATCH 10/18] feat(api): OpenAPI spec update via Stainless API (#58) --- .stats.yml | 2 +- api.md | 12 ++ src/onebusaway/_client.py | 10 + src/onebusaway/resources/__init__.py | 14 ++ .../resources/routes_for_location.py | 180 ++++++++++++++++++ src/onebusaway/types/__init__.py | 4 + .../routes_for_location_retrieve_params.py | 23 +++ .../routes_for_location_retrieve_response.py | 51 +++++ .../api_resources/test_routes_for_location.py | 114 +++++++++++ 9 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 src/onebusaway/resources/routes_for_location.py create mode 100644 src/onebusaway/types/routes_for_location_retrieve_params.py create mode 100644 src/onebusaway/types/routes_for_location_retrieve_response.py create mode 100644 tests/api_resources/test_routes_for_location.py diff --git a/.stats.yml b/.stats.yml index 1da4201..c249e96 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 20 +configured_endpoints: 21 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-681949f64ed7ba8d43a08daba3e5dfcee447cecc48a0a03fcf2aedef3b656641.yml diff --git a/api.md b/api.md index 40f0d90..67780d0 100644 --- a/api.md +++ b/api.md @@ -148,6 +148,18 @@ Methods: - client.route_ids_for_agency.list(agency_id) -> RouteIDsForAgencyListResponse +# RoutesForLocation + +Types: + +```python +from onebusaway.types import RoutesForLocationRetrieveResponse +``` + +Methods: + +- client.routes_for_location.retrieve(\*\*params) -> RoutesForLocationRetrieveResponse + # RoutesForAgency Types: diff --git a/src/onebusaway/_client.py b/src/onebusaway/_client.py index 166e73c..89929e6 100644 --- a/src/onebusaway/_client.py +++ b/src/onebusaway/_client.py @@ -58,6 +58,7 @@ class OnebusawaySDK(SyncAPIClient): schedule_for_stop: resources.ScheduleForStopResource route: resources.RouteResource route_ids_for_agency: resources.RouteIDsForAgencyResource + routes_for_location: resources.RoutesForLocationResource routes_for_agency: resources.RoutesForAgencyResource schedule_for_route: resources.ScheduleForRouteResource arrival_and_departure: resources.ArrivalAndDepartureResource @@ -134,6 +135,7 @@ def __init__( self.schedule_for_stop = resources.ScheduleForStopResource(self) self.route = resources.RouteResource(self) self.route_ids_for_agency = resources.RouteIDsForAgencyResource(self) + self.routes_for_location = resources.RoutesForLocationResource(self) self.routes_for_agency = resources.RoutesForAgencyResource(self) self.schedule_for_route = resources.ScheduleForRouteResource(self) self.arrival_and_departure = resources.ArrivalAndDepartureResource(self) @@ -270,6 +272,7 @@ class AsyncOnebusawaySDK(AsyncAPIClient): schedule_for_stop: resources.AsyncScheduleForStopResource route: resources.AsyncRouteResource route_ids_for_agency: resources.AsyncRouteIDsForAgencyResource + routes_for_location: resources.AsyncRoutesForLocationResource routes_for_agency: resources.AsyncRoutesForAgencyResource schedule_for_route: resources.AsyncScheduleForRouteResource arrival_and_departure: resources.AsyncArrivalAndDepartureResource @@ -346,6 +349,7 @@ def __init__( self.schedule_for_stop = resources.AsyncScheduleForStopResource(self) self.route = resources.AsyncRouteResource(self) self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResource(self) + self.routes_for_location = resources.AsyncRoutesForLocationResource(self) self.routes_for_agency = resources.AsyncRoutesForAgencyResource(self) self.schedule_for_route = resources.AsyncScheduleForRouteResource(self) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResource(self) @@ -485,6 +489,7 @@ def __init__(self, client: OnebusawaySDK) -> None: self.schedule_for_stop = resources.ScheduleForStopResourceWithRawResponse(client.schedule_for_stop) self.route = resources.RouteResourceWithRawResponse(client.route) self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) + self.routes_for_location = resources.RoutesForLocationResourceWithRawResponse(client.routes_for_location) self.routes_for_agency = resources.RoutesForAgencyResourceWithRawResponse(client.routes_for_agency) self.schedule_for_route = resources.ScheduleForRouteResourceWithRawResponse(client.schedule_for_route) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithRawResponse(client.arrival_and_departure) @@ -510,6 +515,7 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: self.schedule_for_stop = resources.AsyncScheduleForStopResourceWithRawResponse(client.schedule_for_stop) self.route = resources.AsyncRouteResourceWithRawResponse(client.route) self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithRawResponse(client.route_ids_for_agency) + self.routes_for_location = resources.AsyncRoutesForLocationResourceWithRawResponse(client.routes_for_location) self.routes_for_agency = resources.AsyncRoutesForAgencyResourceWithRawResponse(client.routes_for_agency) self.schedule_for_route = resources.AsyncScheduleForRouteResourceWithRawResponse(client.schedule_for_route) self.arrival_and_departure = resources.AsyncArrivalAndDepartureResourceWithRawResponse( @@ -539,6 +545,7 @@ def __init__(self, client: OnebusawaySDK) -> None: self.route_ids_for_agency = resources.RouteIDsForAgencyResourceWithStreamingResponse( client.route_ids_for_agency ) + self.routes_for_location = resources.RoutesForLocationResourceWithStreamingResponse(client.routes_for_location) self.routes_for_agency = resources.RoutesForAgencyResourceWithStreamingResponse(client.routes_for_agency) self.schedule_for_route = resources.ScheduleForRouteResourceWithStreamingResponse(client.schedule_for_route) self.arrival_and_departure = resources.ArrivalAndDepartureResourceWithStreamingResponse( @@ -574,6 +581,9 @@ def __init__(self, client: AsyncOnebusawaySDK) -> None: self.route_ids_for_agency = resources.AsyncRouteIDsForAgencyResourceWithStreamingResponse( client.route_ids_for_agency ) + self.routes_for_location = resources.AsyncRoutesForLocationResourceWithStreamingResponse( + client.routes_for_location + ) self.routes_for_agency = resources.AsyncRoutesForAgencyResourceWithStreamingResponse(client.routes_for_agency) self.schedule_for_route = resources.AsyncScheduleForRouteResourceWithStreamingResponse( client.schedule_for_route diff --git a/src/onebusaway/resources/__init__.py b/src/onebusaway/resources/__init__.py index b7e6b33..a394a29 100644 --- a/src/onebusaway/resources/__init__.py +++ b/src/onebusaway/resources/__init__.py @@ -112,6 +112,14 @@ TripsForLocationResourceWithStreamingResponse, AsyncTripsForLocationResourceWithStreamingResponse, ) +from .routes_for_location import ( + RoutesForLocationResource, + AsyncRoutesForLocationResource, + RoutesForLocationResourceWithRawResponse, + AsyncRoutesForLocationResourceWithRawResponse, + RoutesForLocationResourceWithStreamingResponse, + AsyncRoutesForLocationResourceWithStreamingResponse, +) from .stop_ids_for_agency import ( StopIDsForAgencyResource, AsyncStopIDsForAgencyResource, @@ -226,6 +234,12 @@ "AsyncRouteIDsForAgencyResourceWithRawResponse", "RouteIDsForAgencyResourceWithStreamingResponse", "AsyncRouteIDsForAgencyResourceWithStreamingResponse", + "RoutesForLocationResource", + "AsyncRoutesForLocationResource", + "RoutesForLocationResourceWithRawResponse", + "AsyncRoutesForLocationResourceWithRawResponse", + "RoutesForLocationResourceWithStreamingResponse", + "AsyncRoutesForLocationResourceWithStreamingResponse", "RoutesForAgencyResource", "AsyncRoutesForAgencyResource", "RoutesForAgencyResourceWithRawResponse", diff --git a/src/onebusaway/resources/routes_for_location.py b/src/onebusaway/resources/routes_for_location.py new file mode 100644 index 0000000..2c4d4e9 --- /dev/null +++ b/src/onebusaway/resources/routes_for_location.py @@ -0,0 +1,180 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import routes_for_location_retrieve_params +from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven +from .._utils import ( + maybe_transform, + async_maybe_transform, +) +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.routes_for_location_retrieve_response import RoutesForLocationRetrieveResponse + +__all__ = ["RoutesForLocationResource", "AsyncRoutesForLocationResource"] + + +class RoutesForLocationResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> RoutesForLocationResourceWithRawResponse: + return RoutesForLocationResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> RoutesForLocationResourceWithStreamingResponse: + return RoutesForLocationResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + lat: float, + lon: float, + lat_span: float | NotGiven = NOT_GIVEN, + lon_span: float | NotGiven = NOT_GIVEN, + query: str | NotGiven = NOT_GIVEN, + radius: float | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> RoutesForLocationRetrieveResponse: + """ + routes-for-location + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/api/where/routes-for-location.json", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "lat": lat, + "lon": lon, + "lat_span": lat_span, + "lon_span": lon_span, + "query": query, + "radius": radius, + }, + routes_for_location_retrieve_params.RoutesForLocationRetrieveParams, + ), + ), + cast_to=RoutesForLocationRetrieveResponse, + ) + + +class AsyncRoutesForLocationResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncRoutesForLocationResourceWithRawResponse: + return AsyncRoutesForLocationResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncRoutesForLocationResourceWithStreamingResponse: + return AsyncRoutesForLocationResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + lat: float, + lon: float, + lat_span: float | NotGiven = NOT_GIVEN, + lon_span: float | NotGiven = NOT_GIVEN, + query: str | NotGiven = NOT_GIVEN, + radius: float | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> RoutesForLocationRetrieveResponse: + """ + routes-for-location + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/api/where/routes-for-location.json", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "lat": lat, + "lon": lon, + "lat_span": lat_span, + "lon_span": lon_span, + "query": query, + "radius": radius, + }, + routes_for_location_retrieve_params.RoutesForLocationRetrieveParams, + ), + ), + cast_to=RoutesForLocationRetrieveResponse, + ) + + +class RoutesForLocationResourceWithRawResponse: + def __init__(self, routes_for_location: RoutesForLocationResource) -> None: + self._routes_for_location = routes_for_location + + self.retrieve = to_raw_response_wrapper( + routes_for_location.retrieve, + ) + + +class AsyncRoutesForLocationResourceWithRawResponse: + def __init__(self, routes_for_location: AsyncRoutesForLocationResource) -> None: + self._routes_for_location = routes_for_location + + self.retrieve = async_to_raw_response_wrapper( + routes_for_location.retrieve, + ) + + +class RoutesForLocationResourceWithStreamingResponse: + def __init__(self, routes_for_location: RoutesForLocationResource) -> None: + self._routes_for_location = routes_for_location + + self.retrieve = to_streamed_response_wrapper( + routes_for_location.retrieve, + ) + + +class AsyncRoutesForLocationResourceWithStreamingResponse: + def __init__(self, routes_for_location: AsyncRoutesForLocationResource) -> None: + self._routes_for_location = routes_for_location + + self.retrieve = async_to_streamed_response_wrapper( + routes_for_location.retrieve, + ) diff --git a/src/onebusaway/types/__init__.py b/src/onebusaway/types/__init__.py index 939c0fb..7cad009 100644 --- a/src/onebusaway/types/__init__.py +++ b/src/onebusaway/types/__init__.py @@ -26,6 +26,7 @@ from .trip_for_vehicle_retrieve_response import TripForVehicleRetrieveResponse as TripForVehicleRetrieveResponse from .trips_for_location_retrieve_params import TripsForLocationRetrieveParams as TripsForLocationRetrieveParams from .arrival_and_departure_list_response import ArrivalAndDepartureListResponse as ArrivalAndDepartureListResponse +from .routes_for_location_retrieve_params import RoutesForLocationRetrieveParams as RoutesForLocationRetrieveParams from .schedule_for_stop_retrieve_response import ScheduleForStopRetrieveResponse as ScheduleForStopRetrieveResponse from .schedule_for_route_retrieve_response import ScheduleForRouteRetrieveResponse as ScheduleForRouteRetrieveResponse from .stops_for_location_retrieve_response import StopsForLocationRetrieveResponse as StopsForLocationRetrieveResponse @@ -33,6 +34,9 @@ from .arrival_and_departure_retrieve_params import ( ArrivalAndDepartureRetrieveParams as ArrivalAndDepartureRetrieveParams, ) +from .routes_for_location_retrieve_response import ( + RoutesForLocationRetrieveResponse as RoutesForLocationRetrieveResponse, +) from .arrival_and_departure_retrieve_response import ( ArrivalAndDepartureRetrieveResponse as ArrivalAndDepartureRetrieveResponse, ) diff --git a/src/onebusaway/types/routes_for_location_retrieve_params.py b/src/onebusaway/types/routes_for_location_retrieve_params.py new file mode 100644 index 0000000..9acd9ce --- /dev/null +++ b/src/onebusaway/types/routes_for_location_retrieve_params.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["RoutesForLocationRetrieveParams"] + + +class RoutesForLocationRetrieveParams(TypedDict, total=False): + lat: Required[float] + + lon: Required[float] + + lat_span: Annotated[float, PropertyInfo(alias="latSpan")] + + lon_span: Annotated[float, PropertyInfo(alias="lonSpan")] + + query: str + + radius: float diff --git a/src/onebusaway/types/routes_for_location_retrieve_response.py b/src/onebusaway/types/routes_for_location_retrieve_response.py new file mode 100644 index 0000000..a01a271 --- /dev/null +++ b/src/onebusaway/types/routes_for_location_retrieve_response.py @@ -0,0 +1,51 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel +from .shared.references import References +from .shared.response_wrapper import ResponseWrapper + +__all__ = [ + "RoutesForLocationRetrieveResponse", + "RoutesForLocationRetrieveResponseData", + "RoutesForLocationRetrieveResponseDataList", +] + + +class RoutesForLocationRetrieveResponseDataList(BaseModel): + id: Optional[str] = None + + agency_id: Optional[str] = FieldInfo(alias="agencyId", default=None) + + color: Optional[str] = None + + description: Optional[str] = None + + long_name: Optional[str] = FieldInfo(alias="longName", default=None) + + null_safe_short_name: Optional[str] = FieldInfo(alias="nullSafeShortName", default=None) + + short_name: Optional[str] = FieldInfo(alias="shortName", default=None) + + text_color: Optional[str] = FieldInfo(alias="textColor", default=None) + + type: Optional[int] = None + + url: Optional[str] = None + + +class RoutesForLocationRetrieveResponseData(BaseModel): + limit_exceeded: bool = FieldInfo(alias="limitExceeded") + + list: List[RoutesForLocationRetrieveResponseDataList] + + out_of_range: bool = FieldInfo(alias="outOfRange") + + references: References + + +class RoutesForLocationRetrieveResponse(ResponseWrapper): + data: RoutesForLocationRetrieveResponseData diff --git a/tests/api_resources/test_routes_for_location.py b/tests/api_resources/test_routes_for_location.py new file mode 100644 index 0000000..2e091e6 --- /dev/null +++ b/tests/api_resources/test_routes_for_location.py @@ -0,0 +1,114 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from onebusaway import OnebusawaySDK, AsyncOnebusawaySDK +from tests.utils import assert_matches_type +from onebusaway.types import RoutesForLocationRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestRoutesForLocation: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: OnebusawaySDK) -> None: + routes_for_location = client.routes_for_location.retrieve( + lat=0, + lon=0, + ) + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + @parametrize + def test_method_retrieve_with_all_params(self, client: OnebusawaySDK) -> None: + routes_for_location = client.routes_for_location.retrieve( + lat=0, + lon=0, + lat_span=0, + lon_span=0, + query="query", + radius=0, + ) + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: OnebusawaySDK) -> None: + response = client.routes_for_location.with_raw_response.retrieve( + lat=0, + lon=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + routes_for_location = response.parse() + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: OnebusawaySDK) -> None: + with client.routes_for_location.with_streaming_response.retrieve( + lat=0, + lon=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + routes_for_location = response.parse() + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncRoutesForLocation: + parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + routes_for_location = await async_client.routes_for_location.retrieve( + lat=0, + lon=0, + ) + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncOnebusawaySDK) -> None: + routes_for_location = await async_client.routes_for_location.retrieve( + lat=0, + lon=0, + lat_span=0, + lon_span=0, + query="query", + radius=0, + ) + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + response = await async_client.routes_for_location.with_raw_response.retrieve( + lat=0, + lon=0, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + routes_for_location = await response.parse() + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncOnebusawaySDK) -> None: + async with async_client.routes_for_location.with_streaming_response.retrieve( + lat=0, + lon=0, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + routes_for_location = await response.parse() + assert_matches_type(RoutesForLocationRetrieveResponse, routes_for_location, path=["response"]) + + assert cast(Any, response.is_closed) is True From a6413af808c1ea04d05a46fa0a5d54ec888999bf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 13:52:53 +0000 Subject: [PATCH 11/18] chore(internal): remove deprecated ruff config (#59) --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 97bfdb1..94b8843 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -195,7 +195,6 @@ unfixable = [ "T201", "T203", ] -ignore-init-module-imports = true [tool.ruff.lint.flake8-tidy-imports.banned-api] "functools.lru_cache".msg = "This function does not retain type information for the wrapped function's arguments; The `lru_cache` function from `_utils` should be used instead" @@ -207,7 +206,7 @@ combine-as-imports = true extra-standard-library = ["typing_extensions"] known-first-party = ["onebusaway", "tests"] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "bin/**.py" = ["T201", "T203"] "scripts/**.py" = ["T201", "T203"] "tests/**.py" = ["T201", "T203"] From 0bf59511bd3cdd575b2f7d5c4cf911c6492cb7bb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 13:53:11 +0000 Subject: [PATCH 12/18] release: 0.1.0-alpha.12 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ pyproject.toml | 2 +- src/onebusaway/_version.py | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9377f8f..09356f9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.11" + ".": "0.1.0-alpha.12" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 568a3ed..52b2803 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.1.0-alpha.12 (2024-08-08) + +Full Changelog: [v0.1.0-alpha.11...v0.1.0-alpha.12](https://github.com/OneBusAway/python-sdk/compare/v0.1.0-alpha.11...v0.1.0-alpha.12) + +### Features + +* **api:** OpenAPI spec update via Stainless API ([#48](https://github.com/OneBusAway/python-sdk/issues/48)) ([a5c305c](https://github.com/OneBusAway/python-sdk/commit/a5c305c7a5614588dd3fb14607dd2489aab8b3c6)) +* **api:** OpenAPI spec update via Stainless API ([#55](https://github.com/OneBusAway/python-sdk/issues/55)) ([9adae4d](https://github.com/OneBusAway/python-sdk/commit/9adae4de96b8ea11ff8e2d7c251183580f86cf8a)) +* **api:** OpenAPI spec update via Stainless API ([#56](https://github.com/OneBusAway/python-sdk/issues/56)) ([1882cdc](https://github.com/OneBusAway/python-sdk/commit/1882cdc8a4da9705c853ed6f5d5e8d73a4b9276c)) +* **api:** OpenAPI spec update via Stainless API ([#57](https://github.com/OneBusAway/python-sdk/issues/57)) ([5c8a7ee](https://github.com/OneBusAway/python-sdk/commit/5c8a7ee00dcd4ab6a3a9b6800fe10f7447d79c61)) +* **api:** OpenAPI spec update via Stainless API ([#58](https://github.com/OneBusAway/python-sdk/issues/58)) ([29edb45](https://github.com/OneBusAway/python-sdk/commit/29edb45798ad111a1a4f6ce5bbbbadfe3e9099d8)) +* **client:** add `retry_count` to raw response class ([#51](https://github.com/OneBusAway/python-sdk/issues/51)) ([97156e5](https://github.com/OneBusAway/python-sdk/commit/97156e5dff5d743d04ecc0dbe73ec7c690dfb4fe)) + + +### Chores + +* **internal:** bump pyright ([#50](https://github.com/OneBusAway/python-sdk/issues/50)) ([6d1fdf7](https://github.com/OneBusAway/python-sdk/commit/6d1fdf78cf6d63079bf037b88ac0540e619f9ae7)) +* **internal:** bump ruff version ([#53](https://github.com/OneBusAway/python-sdk/issues/53)) ([c8cbc6a](https://github.com/OneBusAway/python-sdk/commit/c8cbc6a1e48e42b15e42ebf40cdfd2f8fc0bc7ab)) +* **internal:** remove deprecated ruff config ([#59](https://github.com/OneBusAway/python-sdk/issues/59)) ([a6413af](https://github.com/OneBusAway/python-sdk/commit/a6413af808c1ea04d05a46fa0a5d54ec888999bf)) +* **internal:** test updates ([#52](https://github.com/OneBusAway/python-sdk/issues/52)) ([f3b7cb0](https://github.com/OneBusAway/python-sdk/commit/f3b7cb00c4302b0ac1b8497835f2db0d3f9e7949)) +* **internal:** update pydantic compat helper function ([#54](https://github.com/OneBusAway/python-sdk/issues/54)) ([1f501f0](https://github.com/OneBusAway/python-sdk/commit/1f501f0592c92e86c4c027f652a49ff11a068715)) + ## 0.1.0-alpha.11 (2024-08-01) Full Changelog: [v0.1.0-alpha.10...v0.1.0-alpha.11](https://github.com/OneBusAway/python-sdk/compare/v0.1.0-alpha.10...v0.1.0-alpha.11) diff --git a/pyproject.toml b/pyproject.toml index 94b8843..121f816 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "onebusaway" -version = "0.1.0-alpha.11" +version = "0.1.0-alpha.12" description = "The official Python library for the onebusaway-sdk API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/onebusaway/_version.py b/src/onebusaway/_version.py index 9189dbc..342cc03 100644 --- a/src/onebusaway/_version.py +++ b/src/onebusaway/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "onebusaway" -__version__ = "0.1.0-alpha.11" # x-release-please-version +__version__ = "0.1.0-alpha.12" # x-release-please-version From 95c7c8c3f2908490f2b3859dbca786ee3a5d74d9 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Thu, 8 Aug 2024 14:36:05 +0000 Subject: [PATCH 13/18] feat: Add routes_for_agency.py example --- examples/routes_for_agency.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 examples/routes_for_agency.py diff --git a/examples/routes_for_agency.py b/examples/routes_for_agency.py new file mode 100644 index 0000000..960f0fd --- /dev/null +++ b/examples/routes_for_agency.py @@ -0,0 +1,24 @@ +from pprint import pprint + +from helpers.load_env import load_settings + +from onebusaway import OnebusawaySDK + +# Load settings from .env file, if it exists. If not, we'll use the +# Puget Sound server URL (which is also the default in the SDK) and +# the 'TEST' API key. +settings = load_settings( + { + "api_key": "TEST", + "base_url": "https://api.pugetsound.onebusaway.org/", + } +) + +# Create a new instance of the OneBusAway SDK with the settings we loaded. +oba = OnebusawaySDK(**settings) + +agency_id = "40" +response = oba.routes_for_agency.list(agency_id) + +if response and response.data: + pprint(response.data) From 68e0128a24acbabf95ddbffe6c764d80dd4540d0 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Thu, 8 Aug 2024 14:36:13 +0000 Subject: [PATCH 14/18] feat: Add routes_ids_for_agency.py example --- examples/routes_ids_for_agency.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 examples/routes_ids_for_agency.py diff --git a/examples/routes_ids_for_agency.py b/examples/routes_ids_for_agency.py new file mode 100644 index 0000000..c5f6547 --- /dev/null +++ b/examples/routes_ids_for_agency.py @@ -0,0 +1,23 @@ +from helpers.load_env import load_settings + +from onebusaway import OnebusawaySDK + +# Load settings from .env file, if it exists. If not, we'll use the +# Puget Sound server URL (which is also the default in the SDK) and +# the 'TEST' API key. +settings = load_settings( + { + "api_key": "TEST", + "base_url": "https://api.pugetsound.onebusaway.org/", + } +) + +# Create a new instance of the OneBusAway SDK with the settings we loaded. +oba = OnebusawaySDK(**settings) + +agency_id = "40" # Link Light Rail in the Seattle area. + +route_ids = oba.route_ids_for_agency.list(agency_id) +if route_ids.data and route_ids.data.list: + for route_id in route_ids.data.list: + print(route_id) From 83251e2f295de6f0b416c6f202fff943caebe2e1 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Thu, 8 Aug 2024 14:36:17 +0000 Subject: [PATCH 15/18] feat: Add schedule_for_route.py example --- examples/schedule_for_route.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 examples/schedule_for_route.py diff --git a/examples/schedule_for_route.py b/examples/schedule_for_route.py new file mode 100644 index 0000000..530a3ca --- /dev/null +++ b/examples/schedule_for_route.py @@ -0,0 +1,21 @@ +from helpers.load_env import load_settings + +from onebusaway import OnebusawaySDK + +# Load settings from .env file, if it exists. If not, we'll use the +# Puget Sound server URL (which is also the default in the SDK) and +# the 'TEST' API key. +settings = load_settings( + { + "api_key": "TEST", + "base_url": "https://api.pugetsound.onebusaway.org/", + } +) + +# Create a new instance of the OneBusAway SDK with the settings we loaded. +oba = OnebusawaySDK(**settings) + +route_id = "1_100224" +response = oba.schedule_for_route.retrieve(route_id) +if response and response.data: + print(response.data.entry.stop_trip_groupings[0]) From 2d390e4ed6d35fa08041080e800da638d60f50d4 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Thu, 8 Aug 2024 14:36:23 +0000 Subject: [PATCH 16/18] refactor: Update route_ids_for_agency.py to use agency_id parameter in API endpoint --- src/onebusaway/resources/route_ids_for_agency.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/onebusaway/resources/route_ids_for_agency.py b/src/onebusaway/resources/route_ids_for_agency.py index cf5ab88..acf0a16 100644 --- a/src/onebusaway/resources/route_ids_for_agency.py +++ b/src/onebusaway/resources/route_ids_for_agency.py @@ -54,7 +54,7 @@ def list( if not agency_id: raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") return self._get( - f"/api/where/route-ids-for-agency/agencyID.json", + f"/api/where/route-ids-for-agency/{agency_id}.json", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -97,7 +97,7 @@ async def list( if not agency_id: raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") return await self._get( - f"/api/where/route-ids-for-agency/agencyID.json", + f"/api/where/route-ids-for-agency/{agency_id}.json", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), From e6e7c1eda4eead5d32809c9f6b5a51d0862205f4 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Thu, 8 Aug 2024 14:36:29 +0000 Subject: [PATCH 17/18] refactor: Update route_ids_for_agency.py to use agency_id parameter in API endpoint --- src/onebusaway/resources/routes_for_agency.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/onebusaway/resources/routes_for_agency.py b/src/onebusaway/resources/routes_for_agency.py index 637eefe..4364fd6 100644 --- a/src/onebusaway/resources/routes_for_agency.py +++ b/src/onebusaway/resources/routes_for_agency.py @@ -54,7 +54,7 @@ def list( if not agency_id: raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") return self._get( - f"/api/where/routes-for-agency/agencyID.json", + f"/api/where/routes-for-agency/{agency_id}.json", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -97,7 +97,7 @@ async def list( if not agency_id: raise ValueError(f"Expected a non-empty value for `agency_id` but received {agency_id!r}") return await self._get( - f"/api/where/routes-for-agency/agencyID.json", + f"/api/where/routes-for-agency/{agency_id}.json", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), From 0340bdb360d6236d978a1775d12c067c3ad59f89 Mon Sep 17 00:00:00 2001 From: Ahmedhossamdev Date: Thu, 8 Aug 2024 14:36:34 +0000 Subject: [PATCH 18/18] feat: Update schedule_for_route.py to use route_id parameter in API endpoint --- src/onebusaway/resources/schedule_for_route.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/onebusaway/resources/schedule_for_route.py b/src/onebusaway/resources/schedule_for_route.py index 74516bb..b43134a 100644 --- a/src/onebusaway/resources/schedule_for_route.py +++ b/src/onebusaway/resources/schedule_for_route.py @@ -63,7 +63,7 @@ def retrieve( if not route_id: raise ValueError(f"Expected a non-empty value for `route_id` but received {route_id!r}") return self._get( - f"/api/where/schedule-for-route/routeID.json", + f"/api/where/schedule-for-route/{route_id}.json", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -116,7 +116,7 @@ async def retrieve( if not route_id: raise ValueError(f"Expected a non-empty value for `route_id` but received {route_id!r}") return await self._get( - f"/api/where/schedule-for-route/routeID.json", + f"/api/where/schedule-for-route/{route_id}.json", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query,