From 9817f3b0ecddd33fa73c4f47bcb68fa72e703ad4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 13 Oct 2024 22:04:19 +0000 Subject: [PATCH] feat(api): api update (#5) --- README.md | 52 ++++++++++++++++++++++++--------- tests/test_client.py | 68 ++++++++++++++++++++++++++++---------------- 2 files changed, 83 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 5809fda..120c745 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,13 @@ The REST API documentation can be found on [arcade-ai.com](https://arcade-ai.com ## Installation ```sh -# install from PyPI -pip install --pre arcade-py +# install from the production repo +pip install git+ssh://git@github.com/ArcadeAI/arcade-py.git ``` +> [!NOTE] +> Once this package is [published to PyPI](https://app.stainlessapi.com/docs/guides/publish), this will become: `pip install --pre arcade-py` + ## Usage The full API of this library can be found in [api.md](api.md). @@ -28,8 +31,11 @@ from arcade_engine import ArcadeEngine client = ArcadeEngine() -chat_response = client.chat.completions() -print(chat_response.id) +authorization_response = client.auth.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", +) +print(authorization_response.authorization_id) ``` While you can provide an `api_key` keyword argument, @@ -49,8 +55,11 @@ client = AsyncArcadeEngine() async def main() -> None: - chat_response = await client.chat.completions() - print(chat_response.id) + authorization_response = await client.auth.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", + ) + print(authorization_response.authorization_id) asyncio.run(main()) @@ -83,7 +92,10 @@ from arcade_engine import ArcadeEngine client = ArcadeEngine() try: - client.chat.completions() + client.auth.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", + ) except arcade_engine.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. @@ -126,7 +138,10 @@ client = ArcadeEngine( ) # Or, configure per-request: -client.with_options(max_retries=5).chat.completions() +client.with_options(max_retries=5).auth.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", +) ``` ### Timeouts @@ -149,7 +164,10 @@ client = ArcadeEngine( ) # Override per-request: -client.with_options(timeout=5.0).chat.completions() +client.with_options(timeout=5.0).auth.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", +) ``` On timeout, an `APITimeoutError` is thrown. @@ -188,11 +206,16 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to from arcade_engine import ArcadeEngine client = ArcadeEngine() -response = client.chat.with_raw_response.completions() +response = client.auth.with_raw_response.authorization( + auth_requirement={ + "provider": "provider" + }, + user_id="user_id", +) print(response.headers.get('X-My-Header')) -chat = response.parse() # get the object that `chat.completions()` would have returned -print(chat.id) +auth = response.parse() # get the object that `auth.authorization()` would have returned +print(auth.authorization_id) ``` These methods return an [`APIResponse`](https://github.com/ArcadeAI/arcade-py/tree/main/src/arcade_engine/_response.py) object. @@ -206,7 +229,10 @@ The above interface eagerly reads the full response body when you make the reque To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. ```python -with client.chat.with_streaming_response.completions() as response: +with client.auth.with_streaming_response.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", +) as response: print(response.headers.get("X-My-Header")) for line in response.iter_lines(): diff --git a/tests/test_client.py b/tests/test_client.py index e7679a4..fc971dc 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -707,12 +707,12 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str @mock.patch("arcade_engine._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/chat/completions").mock(side_effect=httpx.TimeoutException("Test timeout error")) + respx_mock.post("/v1/auth/authorize").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): self.client.post( - "/v1/chat/completions", - body=cast(object, dict()), + "/v1/auth/authorize", + body=cast(object, dict(auth_requirement={"provider": "provider"}, user_id="user_id")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -722,12 +722,12 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> No @mock.patch("arcade_engine._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/chat/completions").mock(return_value=httpx.Response(500)) + respx_mock.post("/v1/auth/authorize").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): self.client.post( - "/v1/chat/completions", - body=cast(object, dict()), + "/v1/auth/authorize", + body=cast(object, dict(auth_requirement={"provider": "provider"}, user_id="user_id")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -749,9 +749,11 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) + respx_mock.post("/v1/auth/authorize").mock(side_effect=retry_handler) - response = client.chat.with_raw_response.completions() + response = client.auth.with_raw_response.authorization( + auth_requirement={"provider": "provider"}, user_id="user_id" + ) assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -773,9 +775,13 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) + respx_mock.post("/v1/auth/authorize").mock(side_effect=retry_handler) - response = client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": Omit()}) + response = client.auth.with_raw_response.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", + extra_headers={"x-stainless-retry-count": Omit()}, + ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -796,9 +802,13 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) + respx_mock.post("/v1/auth/authorize").mock(side_effect=retry_handler) - response = client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": "42"}) + response = client.auth.with_raw_response.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", + extra_headers={"x-stainless-retry-count": "42"}, + ) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1464,12 +1474,12 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte @mock.patch("arcade_engine._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/chat/completions").mock(side_effect=httpx.TimeoutException("Test timeout error")) + respx_mock.post("/v1/auth/authorize").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): await self.client.post( - "/v1/chat/completions", - body=cast(object, dict()), + "/v1/auth/authorize", + body=cast(object, dict(auth_requirement={"provider": "provider"}, user_id="user_id")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1479,12 +1489,12 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) @mock.patch("arcade_engine._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/chat/completions").mock(return_value=httpx.Response(500)) + respx_mock.post("/v1/auth/authorize").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): await self.client.post( - "/v1/chat/completions", - body=cast(object, dict()), + "/v1/auth/authorize", + body=cast(object, dict(auth_requirement={"provider": "provider"}, user_id="user_id")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1509,9 +1519,11 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) + respx_mock.post("/v1/auth/authorize").mock(side_effect=retry_handler) - response = await client.chat.with_raw_response.completions() + response = await client.auth.with_raw_response.authorization( + auth_requirement={"provider": "provider"}, user_id="user_id" + ) assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1534,9 +1546,13 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) + respx_mock.post("/v1/auth/authorize").mock(side_effect=retry_handler) - response = await client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": Omit()}) + response = await client.auth.with_raw_response.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", + extra_headers={"x-stainless-retry-count": Omit()}, + ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1558,8 +1574,12 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/chat/completions").mock(side_effect=retry_handler) + respx_mock.post("/v1/auth/authorize").mock(side_effect=retry_handler) - response = await client.chat.with_raw_response.completions(extra_headers={"x-stainless-retry-count": "42"}) + response = await client.auth.with_raw_response.authorization( + auth_requirement={"provider": "provider"}, + user_id="user_id", + extra_headers={"x-stainless-retry-count": "42"}, + ) assert response.http_request.headers.get("x-stainless-retry-count") == "42"