Skip to content

Commit 126444e

Browse files
feat(api): api update (#9)
1 parent abe66f1 commit 126444e

File tree

8 files changed

+67
-18
lines changed

8 files changed

+67
-18
lines changed

.stats.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
configured_endpoints: 3
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beats-ai-beatsfoundation%2Fbeats-foundation-a9c1eafa5562186e8548b92140925552d512f52e1b9cedd337bef8544e437c15.yml
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beats-ai-beatsfoundation%2Fbeats-foundation-9e8f99d19503143b44d679b3743fc6791e0f6ece45048c58926ed10376d78af5.yml

README.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@ pip install --pre beats_foundation
2323
The full API of this library can be found in [api.md](api.md).
2424

2525
```python
26+
import os
2627
from beats_foundation import Beatsfoundation
2728

28-
client = Beatsfoundation()
29+
client = Beatsfoundation(
30+
bearer_token=os.environ.get(
31+
"BEATSFOUNDATION_BEARER_TOKEN"
32+
), # This is the default and can be omitted
33+
)
2934

3035
song = client.songs.retrieve(
3136
"REPLACE_ME",
@@ -43,10 +48,15 @@ so that your Bearer Token is not stored in source control.
4348
Simply import `AsyncBeatsfoundation` instead of `Beatsfoundation` and use `await` with each API call:
4449

4550
```python
51+
import os
4652
import asyncio
4753
from beats_foundation import AsyncBeatsfoundation
4854

49-
client = AsyncBeatsfoundation()
55+
client = AsyncBeatsfoundation(
56+
bearer_token=os.environ.get(
57+
"BEATSFOUNDATION_BEARER_TOKEN"
58+
), # This is the default and can be omitted
59+
)
5060

5161

5262
async def main() -> None:

api.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ from beats_foundation.types import Song, SongCreateResponse, SongListResponse
88

99
Methods:
1010

11-
- <code title="post /api/songs">client.songs.<a href="./src/beats_foundation/resources/songs.py">create</a>(\*\*<a href="src/beats_foundation/types/song_create_params.py">params</a>) -> <a href="./src/beats_foundation/types/song_create_response.py">object</a></code>
11+
- <code title="post /api/songs">client.songs.<a href="./src/beats_foundation/resources/songs.py">create</a>(\*\*<a href="src/beats_foundation/types/song_create_params.py">params</a>) -> <a href="./src/beats_foundation/types/song_create_response.py">SongCreateResponse</a></code>
1212
- <code title="get /api/songs/{id}">client.songs.<a href="./src/beats_foundation/resources/songs.py">retrieve</a>(id) -> <a href="./src/beats_foundation/types/song.py">Song</a></code>
1313
- <code title="get /api/songs">client.songs.<a href="./src/beats_foundation/resources/songs.py">list</a>(\*\*<a href="src/beats_foundation/types/song_list_params.py">params</a>) -> <a href="./src/beats_foundation/types/song_list_response.py">SongListResponse</a></code>

src/beats_foundation/resources/songs.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from ..types.song import Song
2222
from .._base_client import make_request_options
2323
from ..types.song_list_response import SongListResponse
24+
from ..types.song_create_response import SongCreateResponse
2425

2526
__all__ = ["SongsResource", "AsyncSongsResource"]
2627

@@ -59,7 +60,7 @@ def create(
5960
extra_query: Query | None = None,
6061
extra_body: Body | None = None,
6162
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
62-
) -> object:
63+
) -> SongCreateResponse:
6364
"""Generate a new AI song based on provided parameters.
6465
6566
Rate limited to 2 calls per
@@ -101,7 +102,7 @@ def create(
101102
options=make_request_options(
102103
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
103104
),
104-
cast_to=object,
105+
cast_to=SongCreateResponse,
105106
)
106107

107108
def retrieve(
@@ -218,7 +219,7 @@ async def create(
218219
extra_query: Query | None = None,
219220
extra_body: Body | None = None,
220221
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
221-
) -> object:
222+
) -> SongCreateResponse:
222223
"""Generate a new AI song based on provided parameters.
223224
224225
Rate limited to 2 calls per
@@ -260,7 +261,7 @@ async def create(
260261
options=make_request_options(
261262
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
262263
),
263-
cast_to=object,
264+
cast_to=SongCreateResponse,
264265
)
265266

266267
async def retrieve(

src/beats_foundation/types/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
from .song_list_params import SongListParams as SongListParams
77
from .song_create_params import SongCreateParams as SongCreateParams
88
from .song_list_response import SongListResponse as SongListResponse
9+
from .song_create_response import SongCreateResponse as SongCreateResponse
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing import Optional
4+
5+
from .song import Song
6+
from .._models import BaseModel
7+
8+
__all__ = ["SongCreateResponse"]
9+
10+
11+
class SongCreateResponse(BaseModel):
12+
song: Optional[Song] = None

tests/api_resources/test_songs.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from tests.utils import assert_matches_type
1111
from beats_foundation import Beatsfoundation, AsyncBeatsfoundation
12-
from beats_foundation.types import Song, SongListResponse
12+
from beats_foundation.types import Song, SongListResponse, SongCreateResponse
1313

1414
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
1515

@@ -22,7 +22,7 @@ def test_method_create(self, client: Beatsfoundation) -> None:
2222
song = client.songs.create(
2323
prompt="prompt",
2424
)
25-
assert_matches_type(object, song, path=["response"])
25+
assert_matches_type(SongCreateResponse, song, path=["response"])
2626

2727
@parametrize
2828
def test_method_create_with_all_params(self, client: Beatsfoundation) -> None:
@@ -33,7 +33,7 @@ def test_method_create_with_all_params(self, client: Beatsfoundation) -> None:
3333
lyrics="lyrics",
3434
mood="mood",
3535
)
36-
assert_matches_type(object, song, path=["response"])
36+
assert_matches_type(SongCreateResponse, song, path=["response"])
3737

3838
@parametrize
3939
def test_raw_response_create(self, client: Beatsfoundation) -> None:
@@ -44,7 +44,7 @@ def test_raw_response_create(self, client: Beatsfoundation) -> None:
4444
assert response.is_closed is True
4545
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
4646
song = response.parse()
47-
assert_matches_type(object, song, path=["response"])
47+
assert_matches_type(SongCreateResponse, song, path=["response"])
4848

4949
@parametrize
5050
def test_streaming_response_create(self, client: Beatsfoundation) -> None:
@@ -55,7 +55,7 @@ def test_streaming_response_create(self, client: Beatsfoundation) -> None:
5555
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
5656

5757
song = response.parse()
58-
assert_matches_type(object, song, path=["response"])
58+
assert_matches_type(SongCreateResponse, song, path=["response"])
5959

6060
assert cast(Any, response.is_closed) is True
6161

@@ -139,7 +139,7 @@ async def test_method_create(self, async_client: AsyncBeatsfoundation) -> None:
139139
song = await async_client.songs.create(
140140
prompt="prompt",
141141
)
142-
assert_matches_type(object, song, path=["response"])
142+
assert_matches_type(SongCreateResponse, song, path=["response"])
143143

144144
@parametrize
145145
async def test_method_create_with_all_params(self, async_client: AsyncBeatsfoundation) -> None:
@@ -150,7 +150,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncBeatsfound
150150
lyrics="lyrics",
151151
mood="mood",
152152
)
153-
assert_matches_type(object, song, path=["response"])
153+
assert_matches_type(SongCreateResponse, song, path=["response"])
154154

155155
@parametrize
156156
async def test_raw_response_create(self, async_client: AsyncBeatsfoundation) -> None:
@@ -161,7 +161,7 @@ async def test_raw_response_create(self, async_client: AsyncBeatsfoundation) ->
161161
assert response.is_closed is True
162162
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
163163
song = await response.parse()
164-
assert_matches_type(object, song, path=["response"])
164+
assert_matches_type(SongCreateResponse, song, path=["response"])
165165

166166
@parametrize
167167
async def test_streaming_response_create(self, async_client: AsyncBeatsfoundation) -> None:
@@ -172,7 +172,7 @@ async def test_streaming_response_create(self, async_client: AsyncBeatsfoundatio
172172
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
173173

174174
song = await response.parse()
175-
assert_matches_type(object, song, path=["response"])
175+
assert_matches_type(SongCreateResponse, song, path=["response"])
176176

177177
assert cast(Any, response.is_closed) is True
178178

tests/test_client.py

+26-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@
2424
from beats_foundation._types import Omit
2525
from beats_foundation._models import BaseModel, FinalRequestOptions
2626
from beats_foundation._constants import RAW_RESPONSE_HEADER
27-
from beats_foundation._exceptions import APIStatusError, APITimeoutError, APIResponseValidationError
27+
from beats_foundation._exceptions import (
28+
APIStatusError,
29+
APITimeoutError,
30+
BeatsfoundationError,
31+
APIResponseValidationError,
32+
)
2833
from beats_foundation._base_client import (
2934
DEFAULT_TIMEOUT,
3035
HTTPX_DEFAULT_TIMEOUT,
@@ -339,6 +344,16 @@ def test_default_headers_option(self) -> None:
339344
assert request.headers.get("x-foo") == "stainless"
340345
assert request.headers.get("x-stainless-lang") == "my-overriding-header"
341346

347+
def test_validate_headers(self) -> None:
348+
client = Beatsfoundation(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True)
349+
request = client._build_request(FinalRequestOptions(method="get", url="/foo"))
350+
assert request.headers.get("Authorization") == f"Bearer {bearer_token}"
351+
352+
with pytest.raises(BeatsfoundationError):
353+
with update_env(**{"BEATSFOUNDATION_BEARER_TOKEN": Omit()}):
354+
client2 = Beatsfoundation(base_url=base_url, bearer_token=None, _strict_response_validation=True)
355+
_ = client2
356+
342357
def test_default_query_option(self) -> None:
343358
client = Beatsfoundation(
344359
base_url=base_url,
@@ -1113,6 +1128,16 @@ def test_default_headers_option(self) -> None:
11131128
assert request.headers.get("x-foo") == "stainless"
11141129
assert request.headers.get("x-stainless-lang") == "my-overriding-header"
11151130

1131+
def test_validate_headers(self) -> None:
1132+
client = AsyncBeatsfoundation(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True)
1133+
request = client._build_request(FinalRequestOptions(method="get", url="/foo"))
1134+
assert request.headers.get("Authorization") == f"Bearer {bearer_token}"
1135+
1136+
with pytest.raises(BeatsfoundationError):
1137+
with update_env(**{"BEATSFOUNDATION_BEARER_TOKEN": Omit()}):
1138+
client2 = AsyncBeatsfoundation(base_url=base_url, bearer_token=None, _strict_response_validation=True)
1139+
_ = client2
1140+
11161141
def test_default_query_option(self) -> None:
11171142
client = AsyncBeatsfoundation(
11181143
base_url=base_url,

0 commit comments

Comments
 (0)