openai/openai-python

Public

mirrored from https://github.com/openai/openai-pythonAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
803331f684ccddccab3d20dbda478adad6ecb3a1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

tests/lib/test_bedrock.py

1160lines · modecode

1from __future__ import annotations
2
3import json
4from typing import Any, Union, Protocol, cast
5from pathlib import Path
6
7import httpx
8import pytest
9from httpx import URL
10from respx import MockRouter
11
12import openai.lib._bedrock_auth as bedrock_auth_module
13from openai import OpenAIError, NotFoundError
14from tests.utils import update_env
15from openai._types import Omit
16from openai.lib.bedrock import BedrockOpenAI, AsyncBedrockOpenAI
17
18Client = Union[BedrockOpenAI, AsyncBedrockOpenAI]
19
20RESPONSE_BODY: dict[str, Any] = {
21 "id": "resp_123",
22 "object": "response",
23 "created_at": 0,
24 "status": "completed",
25 "background": False,
26 "error": None,
27 "incomplete_details": None,
28 "instructions": None,
29 "max_output_tokens": None,
30 "max_tool_calls": None,
31 "model": "gpt-4o",
32 "output": [],
33 "parallel_tool_calls": True,
34 "previous_response_id": None,
35 "prompt_cache_key": None,
36 "reasoning": {"effort": None, "summary": None},
37 "safety_identifier": None,
38 "service_tier": "default",
39 "store": True,
40 "temperature": 1.0,
41 "text": {"format": {"type": "text"}, "verbosity": "medium"},
42 "tool_choice": "auto",
43 "tools": [],
44 "top_logprobs": 0,
45 "top_p": 1.0,
46 "truncation": "disabled",
47 "usage": {
48 "input_tokens": 0,
49 "input_tokens_details": {"cached_tokens": 0},
50 "output_tokens": 0,
51 "output_tokens_details": {"reasoning_tokens": 0},
52 "total_tokens": 0,
53 },
54 "user": None,
55 "metadata": {},
56}
57COMPACTED_RESPONSE_BODY: dict[str, Any] = {
58 "id": "resp_123",
59 "created_at": 0,
60 "object": "response.compaction",
61 "output": [],
62 "usage": RESPONSE_BODY["usage"],
63}
64INPUT_ITEMS_BODY: dict[str, Any] = {
65 "object": "list",
66 "data": [],
67 "first_id": "item_123",
68 "last_id": "item_123",
69 "has_more": False,
70}
71INPUT_TOKENS_BODY: dict[str, Any] = {
72 "object": "response.input_tokens",
73 "input_tokens": 1,
74}
75
76
77class MockRequestCall(Protocol):
78 request: httpx.Request
79
80
81class MockAwsCredentials:
82 def __init__(self, access_key: str, secret_key: str, token: str | None = None) -> None:
83 self.access_key = access_key
84 self.secret_key = secret_key
85 self.token = token
86
87
88def make_sync_client(**kwargs: Any) -> BedrockOpenAI:
89 return BedrockOpenAI(http_client=httpx.Client(trust_env=False), **kwargs)
90
91
92def make_async_client(**kwargs: Any) -> AsyncBedrockOpenAI:
93 return AsyncBedrockOpenAI(http_client=httpx.AsyncClient(trust_env=False), **kwargs)
94
95
96def response_created_sse() -> str:
97 event: dict[str, Any] = {"type": "response.created", "sequence_number": 0, "response": RESPONSE_BODY}
98 return f"event: response.created\ndata: {json.dumps(event)}\n\n"
99
100
101@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
102def test_region_derived_base_url(client_cls: type[Client]) -> None:
103 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION="us-east-1", AWS_DEFAULT_REGION=Omit()):
104 client = (
105 make_sync_client(api_key="token") if client_cls is BedrockOpenAI else make_async_client(api_key="token")
106 )
107
108 assert client.base_url == URL("https://bedrock-mantle.us-east-1.api.aws/openai/v1/")
109
110
111@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
112def test_bedrock_config_precedence(client_cls: type[Client]) -> None:
113 with update_env(
114 AWS_BEDROCK_BASE_URL="https://env.example.com/openai/v1",
115 AWS_BEARER_TOKEN_BEDROCK="env token",
116 AWS_REGION="us-east-1",
117 AWS_DEFAULT_REGION="us-west-2",
118 ):
119 client = (
120 make_sync_client(
121 base_url="https://explicit.example.com/openai/v1/responses",
122 api_key="explicit token",
123 )
124 if client_cls is BedrockOpenAI
125 else make_async_client(
126 base_url="https://explicit.example.com/openai/v1/responses",
127 api_key="explicit token",
128 )
129 )
130
131 assert client.base_url == URL("https://explicit.example.com/openai/v1/")
132 assert client.api_key == "explicit token"
133
134
135@pytest.mark.respx()
136def test_env_bearer_does_not_require_botocore(monkeypatch: pytest.MonkeyPatch, respx_mock: MockRouter) -> None:
137 real_import_module = bedrock_auth_module.importlib.import_module
138
139 def import_module(name: str) -> Any:
140 if name.startswith("botocore"):
141 raise ImportError(name)
142 return real_import_module(name)
143
144 monkeypatch.setattr(bedrock_auth_module.importlib, "import_module", import_module)
145 respx_mock.post("https://example.com/openai/v1/responses").mock(
146 return_value=httpx.Response(200, json=RESPONSE_BODY)
147 )
148 with update_env(
149 AWS_BEDROCK_BASE_URL="https://example.com/openai/v1",
150 AWS_BEARER_TOKEN_BEDROCK="env token",
151 ):
152 client = make_sync_client()
153
154 client.responses.create(model="gpt-4o", input="hello")
155
156 request = cast("list[MockRequestCall]", respx_mock.calls)[0].request
157 assert request.headers["Authorization"] == "Bearer env token"
158
159
160def test_empty_env_bearer_without_botocore_uses_aws_credentials(monkeypatch: pytest.MonkeyPatch) -> None:
161 real_import_module = bedrock_auth_module.importlib.import_module
162
163 def import_module(name: str) -> Any:
164 if name.startswith("botocore"):
165 raise ImportError(name)
166 return real_import_module(name)
167
168 monkeypatch.setattr(bedrock_auth_module.importlib, "import_module", import_module)
169 with update_env(AWS_BEARER_TOKEN_BEDROCK="", AWS_REGION="us-east-1"):
170 client = make_sync_client()
171 with pytest.raises(OpenAIError, match="requires optional AWS dependencies"):
172 client.get("/models", cast_to=httpx.Response)
173
174
175@pytest.mark.respx()
176def test_env_bearer_does_not_use_botocore_bearer_auth(monkeypatch: pytest.MonkeyPatch, respx_mock: MockRouter) -> None:
177 auth_module = bedrock_auth_module.importlib.import_module("botocore.auth")
178 calls = 0
179 real_add_auth = auth_module.BearerAuth.add_auth
180
181 def add_auth(auth: object, request: object) -> None:
182 nonlocal calls
183 calls += 1
184 real_add_auth(auth, request)
185
186 monkeypatch.setattr(auth_module.BearerAuth, "add_auth", add_auth)
187 respx_mock.post("https://example.com/openai/v1/responses").mock(
188 return_value=httpx.Response(200, json=RESPONSE_BODY)
189 )
190 with update_env(AWS_BEARER_TOKEN_BEDROCK="env token"):
191 client = make_sync_client(base_url="https://example.com/openai/v1")
192
193 client.responses.create(model="gpt-4o", input="hello")
194
195 request = cast("list[MockRequestCall]", respx_mock.calls)[0].request
196 assert request.headers["Authorization"] == "Bearer env token"
197 assert calls == 0
198
199
200@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
201def test_empty_env_bearer_falls_back_to_aws_credentials(client_cls: type[Client]) -> None:
202 with update_env(AWS_BEARER_TOKEN_BEDROCK="", AWS_REGION="us-east-1"):
203 client = make_sync_client() if client_cls is BedrockOpenAI else make_async_client()
204
205 assert client.api_key == ""
206 assert client._uses_aws_auth()
207
208
209@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
210def test_bedrock_region_precedence(client_cls: type[Client]) -> None:
211 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION="us-east-1", AWS_DEFAULT_REGION="us-west-2"):
212 explicit_region_client = (
213 make_sync_client(aws_region="eu-west-1", api_key="token")
214 if client_cls is BedrockOpenAI
215 else make_async_client(aws_region="eu-west-1", api_key="token")
216 )
217 aws_region_client = (
218 make_sync_client(api_key="token") if client_cls is BedrockOpenAI else make_async_client(api_key="token")
219 )
220
221 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION="us-west-2"):
222 default_region_client = (
223 make_sync_client(api_key="token") if client_cls is BedrockOpenAI else make_async_client(api_key="token")
224 )
225
226 assert explicit_region_client.base_url == URL("https://bedrock-mantle.eu-west-1.api.aws/openai/v1/")
227 assert aws_region_client.base_url == URL("https://bedrock-mantle.us-east-1.api.aws/openai/v1/")
228 assert default_region_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
229
230
231@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
232def test_aws_profile_supplies_region(client_cls: type[Client], tmp_path: Path) -> None:
233 config_path = tmp_path / "config"
234 config_path.write_text("[profile production]\nregion = eu-central-1\n")
235 with update_env(
236 AWS_CONFIG_FILE=str(config_path),
237 AWS_BEDROCK_BASE_URL=Omit(),
238 AWS_REGION=Omit(),
239 AWS_DEFAULT_REGION=Omit(),
240 ):
241 client = (
242 make_sync_client(aws_profile="production")
243 if client_cls is BedrockOpenAI
244 else make_async_client(aws_profile="production")
245 )
246
247 assert client.aws_region == "eu-central-1"
248 assert client.base_url == URL("https://bedrock-mantle.eu-central-1.api.aws/openai/v1/")
249
250
251@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
252def test_normalizes_responses_url(client_cls: type[Client]) -> None:
253 client = (
254 make_sync_client(base_url="https://example.com/openai/v1/responses", api_key="token")
255 if client_cls is BedrockOpenAI
256 else make_async_client(base_url="https://example.com/openai/v1/responses", api_key="token")
257 )
258
259 assert client.base_url == URL("https://example.com/openai/v1/")
260
261
262@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
263def test_requires_endpoint_configuration(client_cls: type[Client]) -> None:
264 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
265 with pytest.raises(OpenAIError, match="Bedrock requires an AWS region"):
266 client_cls(api_key="token")
267
268
269@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
270def test_does_not_use_openai_api_key(client_cls: type[Client]) -> None:
271 with update_env(
272 OPENAI_API_KEY="openai token",
273 AWS_BEARER_TOKEN_BEDROCK=Omit(),
274 AWS_BEDROCK_BASE_URL="https://example.com/openai/v1",
275 AWS_REGION="us-east-1",
276 ):
277 client = make_sync_client() if client_cls is BedrockOpenAI else make_async_client()
278
279 assert client.api_key == ""
280 assert client._uses_aws_auth()
281
282
283@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
284def test_rejects_static_token_and_provider(client_cls: type[Client]) -> None:
285 with pytest.raises(OpenAIError, match="authentication is ambiguous"):
286 client_cls(
287 base_url="https://example.com/openai/v1",
288 api_key="token",
289 bedrock_token_provider=lambda: "provider token",
290 )
291
292
293@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
294def test_rejects_empty_explicit_bearer_token(client_cls: type[Client]) -> None:
295 with pytest.raises(OpenAIError, match="must not be empty"):
296 client_cls(base_url="https://example.com/openai/v1", api_key="")
297
298
299@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
300def test_rejects_bearer_and_aws_credentials(client_cls: type[Client]) -> None:
301 with pytest.raises(OpenAIError, match="authentication is ambiguous"):
302 client_cls(
303 base_url="https://example.com/openai/v1",
304 api_key="token",
305 aws_access_key_id="access key",
306 aws_secret_access_key="secret key",
307 )
308
309
310@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
311def test_rejects_partial_explicit_aws_credentials(client_cls: type[Client]) -> None:
312 with pytest.raises(OpenAIError, match="require both"):
313 client_cls(
314 base_url="https://example.com/openai/v1",
315 aws_region="us-east-1",
316 aws_access_key_id="access key",
317 )
318
319
320@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
321def test_requires_refreshable_tokens_to_use_provider_option(client_cls: type[Client]) -> None:
322 with pytest.raises(OpenAIError, match="bedrock_token_provider"):
323 client_cls(
324 base_url="https://example.com/openai/v1",
325 api_key=lambda: "provider token", # type: ignore[arg-type]
326 )
327
328
329@pytest.mark.respx()
330def test_token_provider_refresh_sync(respx_mock: MockRouter) -> None:
331 respx_mock.post("https://example.com/openai/v1/responses").mock(
332 side_effect=[
333 httpx.Response(500, json={"error": "server error"}),
334 httpx.Response(200, json=RESPONSE_BODY),
335 ]
336 )
337 tokens = iter(["first", "second"])
338 client = BedrockOpenAI(
339 base_url="https://example.com/openai/v1",
340 bedrock_token_provider=lambda: next(tokens),
341 http_client=httpx.Client(trust_env=False),
342 max_retries=1,
343 )
344
345 client.responses.create(model="gpt-4o", input="hello")
346
347 calls = cast("list[MockRequestCall]", respx_mock.calls)
348 assert calls[0].request.headers["Authorization"] == "Bearer first"
349 assert calls[1].request.headers["Authorization"] == "Bearer second"
350
351
352@pytest.mark.asyncio
353@pytest.mark.respx()
354async def test_token_provider_refresh_async(respx_mock: MockRouter) -> None:
355 respx_mock.post("https://example.com/openai/v1/responses").mock(
356 side_effect=[
357 httpx.Response(500, json={"error": "server error"}),
358 httpx.Response(200, json=RESPONSE_BODY),
359 ]
360 )
361 tokens = iter(["first", "second"])
362 client = AsyncBedrockOpenAI(
363 base_url="https://example.com/openai/v1",
364 bedrock_token_provider=lambda: next(tokens),
365 http_client=httpx.AsyncClient(trust_env=False),
366 max_retries=1,
367 )
368
369 await client.responses.create(model="gpt-4o", input="hello")
370
371 calls = cast("list[MockRequestCall]", respx_mock.calls)
372 assert calls[0].request.headers["Authorization"] == "Bearer first"
373 assert calls[1].request.headers["Authorization"] == "Bearer second"
374
375
376@pytest.mark.respx()
377def test_explicit_aws_credentials_override_ambient_bearer(respx_mock: MockRouter) -> None:
378 respx_mock.post("https://example.com/openai/v1/responses").mock(
379 return_value=httpx.Response(200, json=RESPONSE_BODY)
380 )
381 with update_env(AWS_BEARER_TOKEN_BEDROCK="ambient token"):
382 client = BedrockOpenAI(
383 base_url="https://example.com/openai/v1",
384 aws_region="us-east-1",
385 aws_access_key_id="access key",
386 aws_secret_access_key="secret key",
387 aws_session_token="session token",
388 http_client=httpx.Client(trust_env=False),
389 )
390
391 client.responses.create(model="gpt-4o", input="hello")
392
393 request = cast("list[MockRequestCall]", respx_mock.calls)[0].request
394 assert request.headers["Authorization"].startswith("AWS4-HMAC-SHA256 Credential=access key/")
395 assert request.headers["X-Amz-Security-Token"] == "session token"
396
397
398@pytest.mark.respx()
399def test_aws_credentials_provider_refreshes_before_retries(respx_mock: MockRouter) -> None:
400 respx_mock.post("https://example.com/openai/v1/responses").mock(
401 side_effect=[
402 httpx.Response(500, json={"error": "server error"}),
403 httpx.Response(200, json=RESPONSE_BODY),
404 ]
405 )
406 credentials = iter(
407 [
408 MockAwsCredentials("first access key", "first secret", "first session token"),
409 MockAwsCredentials("second access key", "second secret", "second session token"),
410 ]
411 )
412 client = BedrockOpenAI(
413 base_url="https://example.com/openai/v1",
414 aws_region="us-east-1",
415 aws_credentials_provider=lambda: next(credentials),
416 http_client=httpx.Client(trust_env=False),
417 max_retries=1,
418 )
419
420 client.responses.create(model="gpt-4o", input="hello")
421
422 calls = cast("list[MockRequestCall]", respx_mock.calls)
423 assert "Credential=first access key/" in calls[0].request.headers["Authorization"]
424 assert calls[0].request.headers["X-Amz-Security-Token"] == "first session token"
425 assert "Credential=second access key/" in calls[1].request.headers["Authorization"]
426 assert calls[1].request.headers["X-Amz-Security-Token"] == "second session token"
427
428
429def test_preserves_token_provider_across_with_options() -> None:
430 client = BedrockOpenAI(
431 base_url="https://example.com/openai/v1",
432 bedrock_token_provider=lambda: "provider token",
433 http_client=httpx.Client(trust_env=False),
434 )
435
436 copied_client = client.with_options(timeout=1)
437
438 assert copied_client._refresh_api_key() == "provider token"
439
440
441def test_preserves_environment_bearer_across_with_options() -> None:
442 requests: list[httpx.Request] = []
443
444 def handler(request: httpx.Request) -> httpx.Response:
445 requests.append(request)
446 return httpx.Response(200, request=request, json={})
447
448 with update_env(AWS_BEARER_TOKEN_BEDROCK="first token"):
449 client = BedrockOpenAI(
450 base_url="https://example.com/openai/v1",
451 http_client=httpx.Client(transport=httpx.MockTransport(handler), trust_env=False),
452 )
453
454 with update_env(AWS_BEARER_TOKEN_BEDROCK="second token"):
455 copied_client = client.with_options(timeout=1)
456 copied_client.get("/models", cast_to=httpx.Response)
457
458 assert copied_client.api_key == "first token"
459 assert requests[0].headers["Authorization"] == "Bearer first token"
460
461
462def test_environment_bearer_routing_copy_remains_mutable() -> None:
463 requests: list[httpx.Request] = []
464
465 def handler(request: httpx.Request) -> httpx.Response:
466 requests.append(request)
467 return httpx.Response(200, request=request, json={})
468
469 with update_env(AWS_BEARER_TOKEN_BEDROCK="first token"):
470 client = BedrockOpenAI(
471 aws_region="us-east-1",
472 http_client=httpx.Client(transport=httpx.MockTransport(handler), trust_env=False),
473 )
474 copied_client = client.with_options(aws_region="us-west-2")
475 copied_client.api_key = "second token"
476 copied_client.get("/models", cast_to=httpx.Response)
477
478 assert copied_client.api_key == "second token"
479 assert requests[0].headers["Authorization"] == "Bearer second token"
480
481
482def test_legacy_api_key_mutation_updates_requests_and_copies() -> None:
483 requests: list[httpx.Request] = []
484
485 def handler(request: httpx.Request) -> httpx.Response:
486 requests.append(request)
487 return httpx.Response(200, request=request, json={})
488
489 client = BedrockOpenAI(
490 base_url="https://example.com/openai/v1",
491 api_key="first token",
492 http_client=httpx.Client(transport=httpx.MockTransport(handler), trust_env=False),
493 )
494 client.api_key = "second token"
495 client.get("/models", cast_to=httpx.Response)
496 copied_client = client.with_options(timeout=1)
497 copied_client.get("/models", cast_to=httpx.Response)
498 client.api_key = "first token"
499 reverted_client = client.with_options(timeout=2)
500 reverted_client.get("/models", cast_to=httpx.Response)
501
502 assert copied_client.api_key == "second token"
503 assert reverted_client.api_key == "first token"
504 assert [request.headers["Authorization"] for request in requests] == [
505 "Bearer second token",
506 "Bearer second token",
507 "Bearer first token",
508 ]
509
510
511def test_legacy_api_key_mutation_switches_aws_client_to_bearer() -> None:
512 requests: list[httpx.Request] = []
513
514 def handler(request: httpx.Request) -> httpx.Response:
515 requests.append(request)
516 return httpx.Response(200, request=request, json={})
517
518 client = BedrockOpenAI(
519 base_url="https://example.com/openai/v1",
520 aws_region="us-east-1",
521 aws_access_key_id="access key",
522 aws_secret_access_key="secret key",
523 http_client=httpx.Client(transport=httpx.MockTransport(handler), trust_env=False),
524 )
525 client.api_key = "bearer token"
526 client.get("/models", cast_to=httpx.Response, options={"follow_redirects": True})
527
528 assert requests[0].headers["Authorization"] == "Bearer bearer token"
529
530
531def test_explicit_aws_copy_override_wins_over_mutated_api_key() -> None:
532 client = BedrockOpenAI(
533 base_url="https://example.com/openai/v1",
534 api_key="first token",
535 http_client=httpx.Client(trust_env=False),
536 )
537 client.api_key = "second token"
538
539 copied_client = client.with_options(
540 aws_region="us-east-1",
541 aws_access_key_id="access key",
542 aws_secret_access_key="secret key",
543 )
544
545 assert copied_client._uses_aws_auth()
546 assert copied_client.api_key == ""
547
548
549def test_clearing_legacy_bearer_does_not_switch_to_aws_authentication() -> None:
550 network_calls = 0
551
552 def handler(request: httpx.Request) -> httpx.Response:
553 nonlocal network_calls
554 network_calls += 1
555 return httpx.Response(200, request=request)
556
557 with update_env(AWS_ACCESS_KEY_ID="access key", AWS_SECRET_ACCESS_KEY="secret key"):
558 client = BedrockOpenAI(
559 base_url="https://example.com/openai/v1",
560 api_key="bearer token",
561 http_client=httpx.Client(transport=httpx.MockTransport(handler), trust_env=False),
562 )
563 client.api_key = None # type: ignore[assignment]
564 with pytest.raises(OpenAIError, match="bearer credential must not be empty"):
565 client.get("/models", cast_to=httpx.Response)
566
567 assert network_calls == 0
568
569
570def test_legacy_state_repr_does_not_expose_credentials() -> None:
571 client = BedrockOpenAI(
572 base_url="https://example.com/openai/v1",
573 aws_region="us-east-1",
574 aws_access_key_id="secret access key id",
575 aws_secret_access_key="secret access key",
576 aws_session_token="secret session token",
577 http_client=httpx.Client(trust_env=False),
578 )
579
580 assert "secret" not in repr(client._bedrock_state)
581
582 bearer_client = BedrockOpenAI(
583 base_url="https://example.com/openai/v1",
584 api_key="secret bearer token",
585 http_client=httpx.Client(trust_env=False),
586 )
587 assert "secret bearer token" not in repr(bearer_client._bedrock_runtime_signature)
588
589
590@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
591def test_direct_routing_mutations_survive_clone(client_cls: type[Client]) -> None:
592 client = (
593 make_sync_client(base_url="https://first.example/openai/v1", aws_region="us-east-1", api_key="token")
594 if client_cls is BedrockOpenAI
595 else make_async_client(
596 base_url="https://first.example/openai/v1",
597 aws_region="us-east-1",
598 api_key="token",
599 )
600 )
601 client.base_url = "https://second.example/openai/v1"
602 client.aws_region = "us-west-2"
603
604 copied_client = client.with_options(timeout=1)
605
606 assert copied_client.base_url == URL("https://second.example/openai/v1/")
607 assert copied_client.aws_region == "us-west-2"
608 assert not copied_client._bedrock_state.uses_region_derived_base_url
609
610
611@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
612def test_direct_region_mutation_survives_clone(client_cls: type[Client]) -> None:
613 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
614 client = (
615 make_sync_client(aws_region="us-east-1", api_key="token")
616 if client_cls is BedrockOpenAI
617 else make_async_client(aws_region="us-east-1", api_key="token")
618 )
619 client.aws_region = "us-west-2"
620 copied_client = client.with_options(timeout=1)
621
622 assert copied_client.aws_region == "us-west-2"
623 assert copied_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
624
625
626@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
627def test_direct_base_url_mutation_survives_auth_override(client_cls: type[Client]) -> None:
628 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
629 client = (
630 make_sync_client(
631 aws_region="us-east-1",
632 aws_access_key_id="access key",
633 aws_secret_access_key="secret key",
634 )
635 if client_cls is BedrockOpenAI
636 else make_async_client(
637 aws_region="us-east-1",
638 aws_access_key_id="access key",
639 aws_secret_access_key="secret key",
640 )
641 )
642 client.base_url = "https://custom.example/openai/v1"
643 copied_client = client.with_options(api_key="bearer token")
644
645 assert copied_client.base_url == URL("https://custom.example/openai/v1/")
646 assert not copied_client._uses_aws_auth()
647
648
649def test_preserves_aws_credentials_across_with_options() -> None:
650 client = BedrockOpenAI(
651 base_url="https://example.com/openai/v1",
652 aws_region="us-east-1",
653 aws_access_key_id="access key",
654 aws_secret_access_key="secret key",
655 http_client=httpx.Client(trust_env=False),
656 )
657
658 copied_client = client.with_options(timeout=1)
659
660 assert copied_client._uses_aws_auth()
661 assert copied_client._bedrock_state.aws_access_key_id == "access key"
662
663
664@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
665def test_preserves_default_chain_mode_across_with_options(client_cls: type[Client]) -> None:
666 with update_env(AWS_BEARER_TOKEN_BEDROCK=Omit(), AWS_REGION="us-east-1"):
667 client = make_sync_client() if client_cls is BedrockOpenAI else make_async_client()
668
669 with update_env(AWS_BEARER_TOKEN_BEDROCK="late bearer", AWS_REGION="us-east-1"):
670 copied_client = client.with_options(timeout=1)
671
672 assert copied_client._uses_aws_auth()
673 assert copied_client._bedrock_state.aws_profile is None
674 assert copied_client._bedrock_state.aws_access_key_id is None
675 assert copied_client._bedrock_state.aws_credentials_provider is None
676 assert copied_client.api_key == ""
677
678
679@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
680def test_preserves_region_derived_url_provenance_across_multiple_copies(client_cls: type[Client]) -> None:
681 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
682 client = (
683 make_sync_client(aws_region="us-east-1", api_key="token")
684 if client_cls is BedrockOpenAI
685 else make_async_client(aws_region="us-east-1", api_key="token")
686 )
687 copied_client = client.with_options(timeout=1).with_options(aws_region="eu-west-1")
688
689 assert copied_client.base_url == URL("https://bedrock-mantle.eu-west-1.api.aws/openai/v1/")
690
691
692@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
693def test_preserves_region_derived_url_after_auth_override(client_cls: type[Client]) -> None:
694 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
695 client = (
696 make_sync_client(aws_region="us-east-1", api_key="token")
697 if client_cls is BedrockOpenAI
698 else make_async_client(aws_region="us-east-1", api_key="token")
699 )
700 copied_client = client.with_options(
701 aws_access_key_id="access key",
702 aws_secret_access_key="secret key",
703 ).with_options(aws_region="us-west-2")
704
705 assert copied_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
706
707
708@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
709def test_blank_base_url_restores_region_derived_url_provenance(client_cls: type[Client]) -> None:
710 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
711 client = (
712 make_sync_client(aws_region="us-east-1", api_key="token")
713 if client_cls is BedrockOpenAI
714 else make_async_client(aws_region="us-east-1", api_key="token")
715 )
716 copied_client = client.with_options(base_url="").with_options(aws_region="eu-west-1")
717
718 assert copied_client.base_url == URL("https://bedrock-mantle.eu-west-1.api.aws/openai/v1/")
719
720
721@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
722def test_with_options_replaces_the_aws_credential_source(client_cls: type[Client], tmp_path: Path) -> None:
723 config_path = tmp_path / "config"
724 config_path.write_text("[profile other-profile]\nregion = us-east-1\n")
725 explicit_credentials_client = (
726 make_sync_client(
727 base_url="https://example.com/openai/v1",
728 aws_region="us-east-1",
729 aws_access_key_id="access key",
730 aws_secret_access_key="secret key",
731 )
732 if client_cls is BedrockOpenAI
733 else make_async_client(
734 base_url="https://example.com/openai/v1",
735 aws_region="us-east-1",
736 aws_access_key_id="access key",
737 aws_secret_access_key="secret key",
738 )
739 )
740 with update_env(AWS_CONFIG_FILE=str(config_path)):
741 profile_client = explicit_credentials_client.with_options(aws_profile="other-profile")
742
743 assert profile_client._bedrock_state.aws_profile == "other-profile"
744 assert profile_client._bedrock_state.aws_access_key_id is None
745 assert profile_client._bedrock_state.aws_secret_access_key is None
746
747 explicit_credentials_client = profile_client.with_options(
748 aws_access_key_id="replacement access key",
749 aws_secret_access_key="replacement secret key",
750 )
751
752 assert explicit_credentials_client._bedrock_state.aws_profile is None
753 assert explicit_credentials_client._bedrock_state.aws_access_key_id == "replacement access key"
754 assert explicit_credentials_client._bedrock_state.aws_secret_access_key == "replacement secret key"
755
756
757@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
758def test_with_options_replacing_profile_re_resolves_profile_region(client_cls: type[Client], tmp_path: Path) -> None:
759 config_path = tmp_path / "config"
760 config_path.write_text("[profile east]\nregion = us-east-1\n[profile west]\nregion = us-west-2\n")
761
762 with update_env(
763 AWS_CONFIG_FILE=str(config_path),
764 AWS_BEARER_TOKEN_BEDROCK=Omit(),
765 AWS_BEDROCK_BASE_URL=Omit(),
766 AWS_REGION=Omit(),
767 AWS_DEFAULT_REGION=Omit(),
768 ):
769 client = (
770 make_sync_client(aws_profile="east")
771 if client_cls is BedrockOpenAI
772 else make_async_client(aws_profile="east")
773 )
774
775 with update_env(
776 AWS_CONFIG_FILE=str(config_path),
777 AWS_BEARER_TOKEN_BEDROCK=Omit(),
778 AWS_BEDROCK_BASE_URL="https://late-environment.example.com/v1",
779 AWS_REGION=Omit(),
780 AWS_DEFAULT_REGION=Omit(),
781 ):
782 copied_client = client.with_options(aws_profile="west")
783
784 assert copied_client.aws_region == "us-west-2"
785 assert copied_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
786 assert copied_client._bedrock_state.aws_profile == "west"
787
788
789@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
790@pytest.mark.parametrize(
791 ("copy_kwargs", "uses_aws_auth"),
792 [
793 ({"api_key": "bearer token"}, False),
794 (
795 {
796 "aws_access_key_id": "access key",
797 "aws_secret_access_key": "secret key",
798 },
799 True,
800 ),
801 ],
802)
803def test_profile_derived_region_survives_auth_override(
804 client_cls: type[Client],
805 copy_kwargs: dict[str, Any],
806 uses_aws_auth: bool,
807 tmp_path: Path,
808) -> None:
809 config_path = tmp_path / "config"
810 config_path.write_text("[profile west]\nregion = us-west-2\n")
811
812 with update_env(
813 AWS_CONFIG_FILE=str(config_path),
814 AWS_BEARER_TOKEN_BEDROCK=Omit(),
815 AWS_BEDROCK_BASE_URL=Omit(),
816 AWS_REGION=Omit(),
817 AWS_DEFAULT_REGION=Omit(),
818 ):
819 client = (
820 make_sync_client(aws_profile="west")
821 if client_cls is BedrockOpenAI
822 else make_async_client(aws_profile="west")
823 )
824 copied_client = client.with_options(**copy_kwargs)
825
826 assert copied_client.aws_region == "us-west-2"
827 assert copied_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
828 assert copied_client._uses_aws_auth() is uses_aws_auth
829
830
831@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
832def test_with_options_switching_from_bearer_to_profile_re_resolves_environment_region(
833 client_cls: type[Client], tmp_path: Path
834) -> None:
835 config_path = tmp_path / "config"
836 config_path.write_text("[profile west]\nregion = us-west-2\n")
837
838 with update_env(
839 AWS_CONFIG_FILE=str(config_path),
840 AWS_BEDROCK_BASE_URL=Omit(),
841 AWS_REGION="us-east-1",
842 AWS_DEFAULT_REGION=Omit(),
843 ):
844 client = (
845 make_sync_client(api_key="token") if client_cls is BedrockOpenAI else make_async_client(api_key="token")
846 )
847
848 with update_env(
849 AWS_CONFIG_FILE=str(config_path),
850 AWS_BEARER_TOKEN_BEDROCK=Omit(),
851 AWS_BEDROCK_BASE_URL=Omit(),
852 AWS_REGION=Omit(),
853 AWS_DEFAULT_REGION=Omit(),
854 ):
855 copied_client = client.with_options(aws_profile="west")
856
857 assert copied_client.aws_region == "us-west-2"
858 assert copied_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
859
860
861def test_with_options_supports_subclasses_with_the_previous_constructor_signature() -> None:
862 class LegacyBedrockOpenAI(BedrockOpenAI):
863 def __init__(
864 self,
865 *,
866 api_key: str | None = None,
867 bedrock_token_provider: Any = None,
868 aws_region: str | None = None,
869 organization: str | None = None,
870 project: str | None = None,
871 webhook_secret: str | None = None,
872 base_url: str | httpx.URL | None = None,
873 websocket_base_url: str | httpx.URL | None = None,
874 timeout: Any = None,
875 max_retries: int = 2,
876 default_headers: Any = None,
877 default_query: Any = None,
878 http_client: httpx.Client | None = None,
879 _enforce_credentials: bool = True,
880 ) -> None:
881 super().__init__(
882 api_key=api_key,
883 bedrock_token_provider=bedrock_token_provider,
884 aws_region=aws_region,
885 organization=organization,
886 project=project,
887 webhook_secret=webhook_secret,
888 base_url=base_url,
889 websocket_base_url=websocket_base_url,
890 timeout=timeout,
891 max_retries=max_retries,
892 default_headers=default_headers,
893 default_query=default_query,
894 http_client=http_client,
895 _enforce_credentials=_enforce_credentials,
896 )
897
898 client = LegacyBedrockOpenAI(
899 api_key="token",
900 aws_region="us-east-1",
901 http_client=httpx.Client(trust_env=False),
902 )
903
904 copied_client = client.with_options(timeout=1).with_options(aws_region="us-west-2")
905
906 assert isinstance(copied_client, LegacyBedrockOpenAI)
907 assert copied_client.api_key == "token"
908 assert copied_client.base_url == URL("https://bedrock-mantle.us-west-2.api.aws/openai/v1/")
909
910
911@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
912def test_with_options_api_key_replaces_token_provider(client_cls: type[Client]) -> None:
913 client = (
914 make_sync_client(
915 base_url="https://example.com/openai/v1",
916 bedrock_token_provider=lambda: "provider token",
917 )
918 if client_cls is BedrockOpenAI
919 else make_async_client(
920 base_url="https://example.com/openai/v1",
921 bedrock_token_provider=lambda: "provider token",
922 )
923 )
924
925 copied_client = client.with_options(api_key="static token")
926
927 assert copied_client.api_key == "static token"
928 assert copied_client._bedrock_token_provider is None
929
930
931@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
932def test_with_options_rejects_explicit_bearer_provider_and_aws_credentials(client_cls: type[Client]) -> None:
933 client = (
934 make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
935 if client_cls is BedrockOpenAI
936 else make_async_client(base_url="https://example.com/openai/v1", api_key="token")
937 )
938
939 with pytest.raises(OpenAIError, match="authentication is ambiguous"):
940 client.with_options(
941 bedrock_token_provider=lambda: "provider token",
942 aws_access_key_id="access key",
943 aws_secret_access_key="secret key",
944 )
945
946
947@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
948def test_with_options_aws_region_recomputes_region_derived_base_url(client_cls: type[Client]) -> None:
949 with update_env(AWS_BEDROCK_BASE_URL=Omit(), AWS_REGION=Omit(), AWS_DEFAULT_REGION=Omit()):
950 client = (
951 make_sync_client(aws_region="us-east-1", api_key="token")
952 if client_cls is BedrockOpenAI
953 else make_async_client(aws_region="us-east-1", api_key="token")
954 )
955
956 copied_client = client.with_options(aws_region="eu-west-1")
957
958 assert copied_client.aws_region == "eu-west-1"
959 assert copied_client.base_url == URL("https://bedrock-mantle.eu-west-1.api.aws/openai/v1/")
960
961
962@pytest.mark.parametrize("client_cls", [BedrockOpenAI, AsyncBedrockOpenAI])
963def test_with_options_aws_region_keeps_explicit_base_url(client_cls: type[Client]) -> None:
964 client = (
965 make_sync_client(base_url="https://example.com/openai/v1", aws_region="us-east-1", api_key="token")
966 if client_cls is BedrockOpenAI
967 else make_async_client(base_url="https://example.com/openai/v1", aws_region="us-east-1", api_key="token")
968 )
969
970 copied_client = client.with_options(aws_region="eu-west-1")
971
972 assert copied_client.aws_region == "eu-west-1"
973 assert copied_client.base_url == URL("https://example.com/openai/v1/")
974
975
976@pytest.mark.parametrize(
977 "copy_kwargs",
978 [
979 {"admin_api_key": "admin token"},
980 {"workload_identity": cast(Any, {})},
981 ],
982)
983def test_rejects_non_bedrock_copy_auth(copy_kwargs: dict[str, Any]) -> None:
984 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
985
986 with pytest.raises(OpenAIError, match="only supports Bedrock bearer token or AWS credential authentication"):
987 client.with_options(**copy_kwargs)
988
989
990@pytest.mark.respx()
991def test_passes_non_responses_resources_through(respx_mock: MockRouter) -> None:
992 respx_mock.post("https://example.com/openai/v1/chat/completions").mock(
993 return_value=httpx.Response(
994 404,
995 json={"error": {"message": "AWS does not support chat completions here"}},
996 headers={"x-request-id": "req_chat"},
997 )
998 )
999 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
1000
1001 with pytest.raises(NotFoundError, match="AWS does not support chat completions here") as exc:
1002 client.chat.completions.create(model="gpt-4o", messages=[])
1003
1004 assert exc.value.request_id == "req_chat"
1005 calls = cast("list[MockRequestCall]", respx_mock.calls)
1006 assert calls[0].request.url == URL("https://example.com/openai/v1/chat/completions")
1007
1008
1009@pytest.mark.asyncio
1010@pytest.mark.respx()
1011async def test_passes_non_responses_resources_through_async(respx_mock: MockRouter) -> None:
1012 respx_mock.post("https://example.com/openai/v1/chat/completions").mock(
1013 return_value=httpx.Response(
1014 404,
1015 json={"error": {"message": "AWS does not support chat completions here"}},
1016 headers={"x-request-id": "req_chat"},
1017 )
1018 )
1019 client = make_async_client(base_url="https://example.com/openai/v1", api_key="token")
1020
1021 with pytest.raises(NotFoundError, match="AWS does not support chat completions here") as exc:
1022 await client.chat.completions.create(model="gpt-4o", messages=[])
1023
1024 assert exc.value.request_id == "req_chat"
1025 calls = cast("list[MockRequestCall]", respx_mock.calls)
1026 assert calls[0].request.url == URL("https://example.com/openai/v1/chat/completions")
1027
1028
1029@pytest.mark.respx()
1030def test_passes_responses_features_through(respx_mock: MockRouter) -> None:
1031 respx_mock.post("https://example.com/openai/v1/responses").mock(
1032 return_value=httpx.Response(200, json=RESPONSE_BODY)
1033 )
1034 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
1035
1036 response = client.responses.create(
1037 model="gpt-4o",
1038 input="hello",
1039 tools=[{"type": "web_search_preview"}], # type: ignore[list-item]
1040 )
1041
1042 assert response.id == "resp_123"
1043 calls = cast("list[MockRequestCall]", respx_mock.calls)
1044 assert json.loads(calls[0].request.content)["tools"] == [{"type": "web_search_preview"}]
1045
1046
1047@pytest.mark.respx()
1048def test_passes_admin_security_routes_through(respx_mock: MockRouter) -> None:
1049 respx_mock.get("https://example.com/openai/v1/organization/invites").mock(
1050 return_value=httpx.Response(
1051 404,
1052 json={"error": {"message": "AWS does not support organization invites here"}},
1053 headers={"x-request-id": "req_admin"},
1054 )
1055 )
1056 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
1057
1058 with pytest.raises(NotFoundError, match="AWS does not support organization invites here"):
1059 list(client.admin.organization.invites.list())
1060
1061 calls = cast("list[MockRequestCall]", respx_mock.calls)
1062 assert calls[0].request.headers["Authorization"] == "Bearer token"
1063
1064
1065@pytest.mark.respx()
1066def test_refreshes_token_provider_for_admin_security_routes(respx_mock: MockRouter) -> None:
1067 respx_mock.get("https://example.com/openai/v1/organization/invites").mock(
1068 side_effect=[
1069 httpx.Response(500, json={"error": "server error"}),
1070 httpx.Response(
1071 404,
1072 json={"error": {"message": "AWS does not support organization invites here"}},
1073 headers={"x-request-id": "req_admin"},
1074 ),
1075 ]
1076 )
1077 tokens = iter(["first", "second"])
1078 client = BedrockOpenAI(
1079 base_url="https://example.com/openai/v1",
1080 bedrock_token_provider=lambda: next(tokens),
1081 http_client=httpx.Client(trust_env=False),
1082 max_retries=1,
1083 )
1084
1085 with pytest.raises(NotFoundError, match="AWS does not support organization invites here"):
1086 list(client.admin.organization.invites.list())
1087
1088 calls = cast("list[MockRequestCall]", respx_mock.calls)
1089 assert calls[0].request.headers["Authorization"] == "Bearer first"
1090 assert calls[1].request.headers["Authorization"] == "Bearer second"
1091
1092
1093@pytest.mark.respx()
1094def test_allows_responses_http_methods(respx_mock: MockRouter) -> None:
1095 respx_mock.post("https://example.com/openai/v1/responses").mock(
1096 return_value=httpx.Response(200, json=RESPONSE_BODY)
1097 )
1098 respx_mock.get("https://example.com/openai/v1/responses/resp_123?starting_after=1&stream=true").mock(
1099 return_value=httpx.Response(200, text=response_created_sse(), headers={"Content-Type": "text/event-stream"})
1100 )
1101 respx_mock.get("https://example.com/openai/v1/responses/resp_123?stream=true").mock(
1102 return_value=httpx.Response(200, text=response_created_sse(), headers={"Content-Type": "text/event-stream"})
1103 )
1104 respx_mock.get("https://example.com/openai/v1/responses/resp_123").mock(
1105 return_value=httpx.Response(200, json=RESPONSE_BODY)
1106 )
1107 respx_mock.post("https://example.com/openai/v1/responses/resp_123/cancel").mock(
1108 return_value=httpx.Response(200, json=RESPONSE_BODY)
1109 )
1110 respx_mock.post("https://example.com/openai/v1/responses/compact").mock(
1111 return_value=httpx.Response(200, json=COMPACTED_RESPONSE_BODY)
1112 )
1113 respx_mock.get("https://example.com/openai/v1/responses/resp_123/input_items").mock(
1114 return_value=httpx.Response(200, json=INPUT_ITEMS_BODY)
1115 )
1116 respx_mock.post("https://example.com/openai/v1/responses/input_tokens").mock(
1117 return_value=httpx.Response(200, json=INPUT_TOKENS_BODY)
1118 )
1119 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
1120
1121 assert client.responses.create(model="gpt-4o", input="hello", background=True).id == "resp_123"
1122 assert client.responses.retrieve("resp_123").id == "resp_123"
1123 assert [event.type for event in client.responses.retrieve("resp_123", starting_after=1, stream=True)] == [
1124 "response.created"
1125 ]
1126 assert [event.type for event in client.responses.retrieve("resp_123", stream=True)] == ["response.created"]
1127 assert client.responses.cancel("resp_123").id == "resp_123"
1128 assert client.responses.compact(model="gpt-4o").object == "response.compaction"
1129 assert list(client.responses.input_items.list("resp_123")) == []
1130 assert client.responses.input_tokens.count(model="gpt-4o", input="hello").input_tokens == 1
1131
1132 calls = cast("list[MockRequestCall]", respx_mock.calls)
1133 assert {call.request.headers["Authorization"] for call in calls} == {"Bearer token"}
1134
1135
1136@pytest.mark.respx()
1137def test_allows_sse_and_response_wrappers(respx_mock: MockRouter) -> None:
1138 respx_mock.post("https://example.com/openai/v1/responses").mock(
1139 side_effect=[
1140 httpx.Response(200, text=response_created_sse(), headers={"Content-Type": "text/event-stream"}),
1141 httpx.Response(200, json=RESPONSE_BODY),
1142 httpx.Response(200, json=RESPONSE_BODY),
1143 ]
1144 )
1145 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
1146
1147 events = list(client.responses.create(model="gpt-4o", input="hello", stream=True))
1148 assert [event.type for event in events] == ["response.created"]
1149
1150 raw_response = client.responses.with_raw_response.create(model="gpt-4o", input="hello")
1151 assert raw_response.parse().id == "resp_123"
1152
1153 with client.responses.with_streaming_response.create(model="gpt-4o", input="hello") as response:
1154 assert response.parse().id == "resp_123"
1155
1156
1157def test_does_not_guard_responses_connect() -> None:
1158 client = make_sync_client(base_url="https://example.com/openai/v1", api_key="token")
1159
1160 assert client.responses.connect() is not None
1161