anthropic 0.75.0__py3-none-any.whl → 0.77.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- anthropic/_base_client.py +145 -13
- anthropic/_client.py +4 -12
- anthropic/_compat.py +3 -3
- anthropic/_models.py +16 -1
- anthropic/_streaming.py +78 -76
- anthropic/_types.py +12 -2
- anthropic/_utils/_json.py +35 -0
- anthropic/_version.py +1 -1
- anthropic/lib/_parse/_response.py +29 -1
- anthropic/lib/streaming/__init__.py +3 -0
- anthropic/lib/streaming/_messages.py +74 -40
- anthropic/lib/streaming/_types.py +42 -2
- anthropic/lib/tools/_beta_compaction_control.py +2 -2
- anthropic/lib/tools/_beta_runner.py +17 -0
- anthropic/resources/beta/messages/messages.py +229 -83
- anthropic/resources/messages/messages.py +409 -5
- anthropic/types/__init__.py +7 -0
- anthropic/types/beta/beta_code_execution_tool_20250522_param.py +1 -0
- anthropic/types/beta/beta_code_execution_tool_20250825_param.py +1 -0
- anthropic/types/beta/beta_container.py +4 -0
- anthropic/types/beta/beta_container_params.py +2 -0
- anthropic/types/beta/beta_container_upload_block.py +2 -0
- anthropic/types/beta/beta_container_upload_block_param.py +5 -0
- anthropic/types/beta/beta_direct_caller.py +2 -0
- anthropic/types/beta/beta_direct_caller_param.py +2 -0
- anthropic/types/beta/beta_mcp_tool_config_param.py +2 -0
- anthropic/types/beta/beta_mcp_tool_default_config_param.py +2 -0
- anthropic/types/beta/beta_mcp_toolset_param.py +6 -0
- anthropic/types/beta/beta_memory_tool_20250818_param.py +1 -0
- anthropic/types/beta/beta_output_config_param.py +15 -1
- anthropic/types/beta/beta_server_tool_caller.py +2 -0
- anthropic/types/beta/beta_server_tool_caller_param.py +2 -0
- anthropic/types/beta/beta_server_tool_use_block.py +4 -4
- anthropic/types/beta/beta_skill.py +2 -0
- anthropic/types/beta/beta_skill_params.py +2 -0
- anthropic/types/beta/beta_tool_bash_20241022_param.py +1 -0
- anthropic/types/beta/beta_tool_bash_20250124_param.py +1 -0
- anthropic/types/beta/beta_tool_choice_any_param.py +2 -0
- anthropic/types/beta/beta_tool_choice_auto_param.py +2 -0
- anthropic/types/beta/beta_tool_choice_none_param.py +2 -0
- anthropic/types/beta/beta_tool_choice_tool_param.py +2 -0
- anthropic/types/beta/beta_tool_computer_use_20241022_param.py +1 -0
- anthropic/types/beta/beta_tool_computer_use_20250124_param.py +1 -0
- anthropic/types/beta/beta_tool_computer_use_20251124_param.py +1 -0
- anthropic/types/beta/beta_tool_param.py +6 -0
- anthropic/types/beta/beta_tool_reference_block_param.py +2 -0
- anthropic/types/beta/beta_tool_search_tool_bm25_20251119_param.py +1 -0
- anthropic/types/beta/beta_tool_search_tool_regex_20251119_param.py +1 -0
- anthropic/types/beta/beta_tool_text_editor_20241022_param.py +1 -0
- anthropic/types/beta/beta_tool_text_editor_20250124_param.py +1 -0
- anthropic/types/beta/beta_tool_text_editor_20250429_param.py +1 -0
- anthropic/types/beta/beta_tool_text_editor_20250728_param.py +1 -0
- anthropic/types/beta/beta_web_fetch_tool_20250910_param.py +1 -0
- anthropic/types/beta/beta_web_search_tool_20250305_param.py +6 -0
- anthropic/types/beta/beta_web_search_tool_result_error_code.py +1 -1
- anthropic/types/beta/message_count_tokens_params.py +9 -5
- anthropic/types/beta/message_create_params.py +9 -5
- anthropic/types/beta/messages/batch_create_params.py +2 -9
- anthropic/types/beta/messages/beta_message_batch_individual_response.py +4 -0
- anthropic/types/json_output_format_param.py +15 -0
- anthropic/types/message_count_tokens_params.py +4 -0
- anthropic/types/message_create_params.py +4 -0
- anthropic/types/messages/message_batch_individual_response.py +4 -0
- anthropic/types/output_config_param.py +19 -0
- anthropic/types/parsed_message.py +56 -0
- anthropic/types/tool_bash_20250124_param.py +3 -0
- anthropic/types/tool_choice_any_param.py +2 -0
- anthropic/types/tool_choice_auto_param.py +2 -0
- anthropic/types/tool_choice_none_param.py +2 -0
- anthropic/types/tool_choice_tool_param.py +2 -0
- anthropic/types/tool_param.py +8 -0
- anthropic/types/tool_text_editor_20250124_param.py +3 -0
- anthropic/types/tool_text_editor_20250429_param.py +3 -0
- anthropic/types/tool_text_editor_20250728_param.py +3 -0
- anthropic/types/web_search_tool_20250305_param.py +8 -0
- anthropic/types/web_search_tool_request_error_param.py +8 -1
- anthropic/types/web_search_tool_result_error.py +8 -1
- {anthropic-0.75.0.dist-info → anthropic-0.77.0.dist-info}/METADATA +4 -2
- {anthropic-0.75.0.dist-info → anthropic-0.77.0.dist-info}/RECORD +81 -77
- {anthropic-0.75.0.dist-info → anthropic-0.77.0.dist-info}/WHEEL +0 -0
- {anthropic-0.75.0.dist-info → anthropic-0.77.0.dist-info}/licenses/LICENSE +0 -0
anthropic/_base_client.py
CHANGED
|
@@ -10,6 +10,7 @@ import asyncio
|
|
|
10
10
|
import inspect
|
|
11
11
|
import logging
|
|
12
12
|
import platform
|
|
13
|
+
import warnings
|
|
13
14
|
import email.utils
|
|
14
15
|
from types import TracebackType
|
|
15
16
|
from random import random
|
|
@@ -54,9 +55,11 @@ from ._types import (
|
|
|
54
55
|
ResponseT,
|
|
55
56
|
AnyMapping,
|
|
56
57
|
PostParser,
|
|
58
|
+
BinaryTypes,
|
|
57
59
|
RequestFiles,
|
|
58
60
|
HttpxSendArgs,
|
|
59
61
|
RequestOptions,
|
|
62
|
+
AsyncBinaryTypes,
|
|
60
63
|
HttpxRequestFiles,
|
|
61
64
|
ModelBuilderProtocol,
|
|
62
65
|
not_given,
|
|
@@ -86,6 +89,7 @@ from ._exceptions import (
|
|
|
86
89
|
APIConnectionError,
|
|
87
90
|
APIResponseValidationError,
|
|
88
91
|
)
|
|
92
|
+
from ._utils._json import openapi_dumps
|
|
89
93
|
from ._utils._httpx import get_environment_proxies
|
|
90
94
|
from ._legacy_response import LegacyAPIResponse
|
|
91
95
|
|
|
@@ -490,8 +494,19 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
|
|
|
490
494
|
retries_taken: int = 0,
|
|
491
495
|
) -> httpx.Request:
|
|
492
496
|
if log.isEnabledFor(logging.DEBUG):
|
|
493
|
-
log.debug(
|
|
494
|
-
|
|
497
|
+
log.debug(
|
|
498
|
+
"Request options: %s",
|
|
499
|
+
model_dump(
|
|
500
|
+
options,
|
|
501
|
+
exclude_unset=True,
|
|
502
|
+
# Pydantic v1 can't dump every type we support in content, so we exclude it for now.
|
|
503
|
+
exclude={
|
|
504
|
+
"content",
|
|
505
|
+
}
|
|
506
|
+
if PYDANTIC_V1
|
|
507
|
+
else {},
|
|
508
|
+
),
|
|
509
|
+
)
|
|
495
510
|
kwargs: dict[str, Any] = {}
|
|
496
511
|
|
|
497
512
|
json_data = options.json_data
|
|
@@ -545,10 +560,18 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
|
|
|
545
560
|
is_body_allowed = options.method.lower() != "get"
|
|
546
561
|
|
|
547
562
|
if is_body_allowed:
|
|
548
|
-
if
|
|
563
|
+
if options.content is not None and json_data is not None:
|
|
564
|
+
raise TypeError("Passing both `content` and `json_data` is not supported")
|
|
565
|
+
if options.content is not None and files is not None:
|
|
566
|
+
raise TypeError("Passing both `content` and `files` is not supported")
|
|
567
|
+
if options.content is not None:
|
|
568
|
+
kwargs["content"] = options.content
|
|
569
|
+
elif isinstance(json_data, bytes):
|
|
549
570
|
kwargs["content"] = json_data
|
|
550
|
-
|
|
551
|
-
|
|
571
|
+
elif not files:
|
|
572
|
+
# Don't set content when JSON is sent as multipart/form-data,
|
|
573
|
+
# since httpx's content param overrides other body arguments
|
|
574
|
+
kwargs["content"] = openapi_dumps(json_data) if is_given(json_data) and json_data is not None else None
|
|
552
575
|
kwargs["files"] = files
|
|
553
576
|
else:
|
|
554
577
|
headers.pop("Content-Type", None)
|
|
@@ -1278,6 +1301,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1278
1301
|
*,
|
|
1279
1302
|
cast_to: Type[ResponseT],
|
|
1280
1303
|
body: Body | None = None,
|
|
1304
|
+
content: BinaryTypes | None = None,
|
|
1281
1305
|
options: RequestOptions = {},
|
|
1282
1306
|
files: RequestFiles | None = None,
|
|
1283
1307
|
stream: Literal[False] = False,
|
|
@@ -1290,6 +1314,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1290
1314
|
*,
|
|
1291
1315
|
cast_to: Type[ResponseT],
|
|
1292
1316
|
body: Body | None = None,
|
|
1317
|
+
content: BinaryTypes | None = None,
|
|
1293
1318
|
options: RequestOptions = {},
|
|
1294
1319
|
files: RequestFiles | None = None,
|
|
1295
1320
|
stream: Literal[True],
|
|
@@ -1303,6 +1328,7 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1303
1328
|
*,
|
|
1304
1329
|
cast_to: Type[ResponseT],
|
|
1305
1330
|
body: Body | None = None,
|
|
1331
|
+
content: BinaryTypes | None = None,
|
|
1306
1332
|
options: RequestOptions = {},
|
|
1307
1333
|
files: RequestFiles | None = None,
|
|
1308
1334
|
stream: bool,
|
|
@@ -1315,13 +1341,25 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1315
1341
|
*,
|
|
1316
1342
|
cast_to: Type[ResponseT],
|
|
1317
1343
|
body: Body | None = None,
|
|
1344
|
+
content: BinaryTypes | None = None,
|
|
1318
1345
|
options: RequestOptions = {},
|
|
1319
1346
|
files: RequestFiles | None = None,
|
|
1320
1347
|
stream: bool = False,
|
|
1321
1348
|
stream_cls: type[_StreamT] | None = None,
|
|
1322
1349
|
) -> ResponseT | _StreamT:
|
|
1350
|
+
if body is not None and content is not None:
|
|
1351
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
1352
|
+
if files is not None and content is not None:
|
|
1353
|
+
raise TypeError("Passing both `files` and `content` is not supported")
|
|
1354
|
+
if isinstance(body, bytes):
|
|
1355
|
+
warnings.warn(
|
|
1356
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
1357
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
1358
|
+
DeprecationWarning,
|
|
1359
|
+
stacklevel=2,
|
|
1360
|
+
)
|
|
1323
1361
|
opts = FinalRequestOptions.construct(
|
|
1324
|
-
method="post", url=path, json_data=body, files=to_httpx_files(files), **options
|
|
1362
|
+
method="post", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
|
|
1325
1363
|
)
|
|
1326
1364
|
return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))
|
|
1327
1365
|
|
|
@@ -1331,9 +1369,24 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1331
1369
|
*,
|
|
1332
1370
|
cast_to: Type[ResponseT],
|
|
1333
1371
|
body: Body | None = None,
|
|
1372
|
+
content: BinaryTypes | None = None,
|
|
1373
|
+
files: RequestFiles | None = None,
|
|
1334
1374
|
options: RequestOptions = {},
|
|
1335
1375
|
) -> ResponseT:
|
|
1336
|
-
|
|
1376
|
+
if body is not None and content is not None:
|
|
1377
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
1378
|
+
if files is not None and content is not None:
|
|
1379
|
+
raise TypeError("Passing both `files` and `content` is not supported")
|
|
1380
|
+
if isinstance(body, bytes):
|
|
1381
|
+
warnings.warn(
|
|
1382
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
1383
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
1384
|
+
DeprecationWarning,
|
|
1385
|
+
stacklevel=2,
|
|
1386
|
+
)
|
|
1387
|
+
opts = FinalRequestOptions.construct(
|
|
1388
|
+
method="patch", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
|
|
1389
|
+
)
|
|
1337
1390
|
return self.request(cast_to, opts)
|
|
1338
1391
|
|
|
1339
1392
|
def put(
|
|
@@ -1342,11 +1395,23 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1342
1395
|
*,
|
|
1343
1396
|
cast_to: Type[ResponseT],
|
|
1344
1397
|
body: Body | None = None,
|
|
1398
|
+
content: BinaryTypes | None = None,
|
|
1345
1399
|
files: RequestFiles | None = None,
|
|
1346
1400
|
options: RequestOptions = {},
|
|
1347
1401
|
) -> ResponseT:
|
|
1402
|
+
if body is not None and content is not None:
|
|
1403
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
1404
|
+
if files is not None and content is not None:
|
|
1405
|
+
raise TypeError("Passing both `files` and `content` is not supported")
|
|
1406
|
+
if isinstance(body, bytes):
|
|
1407
|
+
warnings.warn(
|
|
1408
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
1409
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
1410
|
+
DeprecationWarning,
|
|
1411
|
+
stacklevel=2,
|
|
1412
|
+
)
|
|
1348
1413
|
opts = FinalRequestOptions.construct(
|
|
1349
|
-
method="put", url=path, json_data=body, files=to_httpx_files(files), **options
|
|
1414
|
+
method="put", url=path, json_data=body, content=content, files=to_httpx_files(files), **options
|
|
1350
1415
|
)
|
|
1351
1416
|
return self.request(cast_to, opts)
|
|
1352
1417
|
|
|
@@ -1356,9 +1421,19 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
|
|
|
1356
1421
|
*,
|
|
1357
1422
|
cast_to: Type[ResponseT],
|
|
1358
1423
|
body: Body | None = None,
|
|
1424
|
+
content: BinaryTypes | None = None,
|
|
1359
1425
|
options: RequestOptions = {},
|
|
1360
1426
|
) -> ResponseT:
|
|
1361
|
-
|
|
1427
|
+
if body is not None and content is not None:
|
|
1428
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
1429
|
+
if isinstance(body, bytes):
|
|
1430
|
+
warnings.warn(
|
|
1431
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
1432
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
1433
|
+
DeprecationWarning,
|
|
1434
|
+
stacklevel=2,
|
|
1435
|
+
)
|
|
1436
|
+
opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options)
|
|
1362
1437
|
return self.request(cast_to, opts)
|
|
1363
1438
|
|
|
1364
1439
|
def get_api_list(
|
|
@@ -1854,6 +1929,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1854
1929
|
*,
|
|
1855
1930
|
cast_to: Type[ResponseT],
|
|
1856
1931
|
body: Body | None = None,
|
|
1932
|
+
content: AsyncBinaryTypes | None = None,
|
|
1857
1933
|
files: RequestFiles | None = None,
|
|
1858
1934
|
options: RequestOptions = {},
|
|
1859
1935
|
stream: Literal[False] = False,
|
|
@@ -1866,6 +1942,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1866
1942
|
*,
|
|
1867
1943
|
cast_to: Type[ResponseT],
|
|
1868
1944
|
body: Body | None = None,
|
|
1945
|
+
content: AsyncBinaryTypes | None = None,
|
|
1869
1946
|
files: RequestFiles | None = None,
|
|
1870
1947
|
options: RequestOptions = {},
|
|
1871
1948
|
stream: Literal[True],
|
|
@@ -1879,6 +1956,7 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1879
1956
|
*,
|
|
1880
1957
|
cast_to: Type[ResponseT],
|
|
1881
1958
|
body: Body | None = None,
|
|
1959
|
+
content: AsyncBinaryTypes | None = None,
|
|
1882
1960
|
files: RequestFiles | None = None,
|
|
1883
1961
|
options: RequestOptions = {},
|
|
1884
1962
|
stream: bool,
|
|
@@ -1891,13 +1969,25 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1891
1969
|
*,
|
|
1892
1970
|
cast_to: Type[ResponseT],
|
|
1893
1971
|
body: Body | None = None,
|
|
1972
|
+
content: AsyncBinaryTypes | None = None,
|
|
1894
1973
|
files: RequestFiles | None = None,
|
|
1895
1974
|
options: RequestOptions = {},
|
|
1896
1975
|
stream: bool = False,
|
|
1897
1976
|
stream_cls: type[_AsyncStreamT] | None = None,
|
|
1898
1977
|
) -> ResponseT | _AsyncStreamT:
|
|
1978
|
+
if body is not None and content is not None:
|
|
1979
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
1980
|
+
if files is not None and content is not None:
|
|
1981
|
+
raise TypeError("Passing both `files` and `content` is not supported")
|
|
1982
|
+
if isinstance(body, bytes):
|
|
1983
|
+
warnings.warn(
|
|
1984
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
1985
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
1986
|
+
DeprecationWarning,
|
|
1987
|
+
stacklevel=2,
|
|
1988
|
+
)
|
|
1899
1989
|
opts = FinalRequestOptions.construct(
|
|
1900
|
-
method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options
|
|
1990
|
+
method="post", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options
|
|
1901
1991
|
)
|
|
1902
1992
|
return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
|
|
1903
1993
|
|
|
@@ -1907,9 +1997,29 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1907
1997
|
*,
|
|
1908
1998
|
cast_to: Type[ResponseT],
|
|
1909
1999
|
body: Body | None = None,
|
|
2000
|
+
content: AsyncBinaryTypes | None = None,
|
|
2001
|
+
files: RequestFiles | None = None,
|
|
1910
2002
|
options: RequestOptions = {},
|
|
1911
2003
|
) -> ResponseT:
|
|
1912
|
-
|
|
2004
|
+
if body is not None and content is not None:
|
|
2005
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
2006
|
+
if files is not None and content is not None:
|
|
2007
|
+
raise TypeError("Passing both `files` and `content` is not supported")
|
|
2008
|
+
if isinstance(body, bytes):
|
|
2009
|
+
warnings.warn(
|
|
2010
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
2011
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
2012
|
+
DeprecationWarning,
|
|
2013
|
+
stacklevel=2,
|
|
2014
|
+
)
|
|
2015
|
+
opts = FinalRequestOptions.construct(
|
|
2016
|
+
method="patch",
|
|
2017
|
+
url=path,
|
|
2018
|
+
json_data=body,
|
|
2019
|
+
content=content,
|
|
2020
|
+
files=await async_to_httpx_files(files),
|
|
2021
|
+
**options,
|
|
2022
|
+
)
|
|
1913
2023
|
return await self.request(cast_to, opts)
|
|
1914
2024
|
|
|
1915
2025
|
async def put(
|
|
@@ -1918,11 +2028,23 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1918
2028
|
*,
|
|
1919
2029
|
cast_to: Type[ResponseT],
|
|
1920
2030
|
body: Body | None = None,
|
|
2031
|
+
content: AsyncBinaryTypes | None = None,
|
|
1921
2032
|
files: RequestFiles | None = None,
|
|
1922
2033
|
options: RequestOptions = {},
|
|
1923
2034
|
) -> ResponseT:
|
|
2035
|
+
if body is not None and content is not None:
|
|
2036
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
2037
|
+
if files is not None and content is not None:
|
|
2038
|
+
raise TypeError("Passing both `files` and `content` is not supported")
|
|
2039
|
+
if isinstance(body, bytes):
|
|
2040
|
+
warnings.warn(
|
|
2041
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
2042
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
2043
|
+
DeprecationWarning,
|
|
2044
|
+
stacklevel=2,
|
|
2045
|
+
)
|
|
1924
2046
|
opts = FinalRequestOptions.construct(
|
|
1925
|
-
method="put", url=path, json_data=body, files=await async_to_httpx_files(files), **options
|
|
2047
|
+
method="put", url=path, json_data=body, content=content, files=await async_to_httpx_files(files), **options
|
|
1926
2048
|
)
|
|
1927
2049
|
return await self.request(cast_to, opts)
|
|
1928
2050
|
|
|
@@ -1932,9 +2054,19 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
|
|
|
1932
2054
|
*,
|
|
1933
2055
|
cast_to: Type[ResponseT],
|
|
1934
2056
|
body: Body | None = None,
|
|
2057
|
+
content: AsyncBinaryTypes | None = None,
|
|
1935
2058
|
options: RequestOptions = {},
|
|
1936
2059
|
) -> ResponseT:
|
|
1937
|
-
|
|
2060
|
+
if body is not None and content is not None:
|
|
2061
|
+
raise TypeError("Passing both `body` and `content` is not supported")
|
|
2062
|
+
if isinstance(body, bytes):
|
|
2063
|
+
warnings.warn(
|
|
2064
|
+
"Passing raw bytes as `body` is deprecated and will be removed in a future version. "
|
|
2065
|
+
"Please pass raw bytes via the `content` parameter instead.",
|
|
2066
|
+
DeprecationWarning,
|
|
2067
|
+
stacklevel=2,
|
|
2068
|
+
)
|
|
2069
|
+
opts = FinalRequestOptions.construct(method="delete", url=path, json_data=body, content=content, **options)
|
|
1938
2070
|
return await self.request(cast_to, opts)
|
|
1939
2071
|
|
|
1940
2072
|
def get_api_list(
|
anthropic/_client.py
CHANGED
|
@@ -187,14 +187,10 @@ class Anthropic(SyncAPIClient):
|
|
|
187
187
|
# valid
|
|
188
188
|
return
|
|
189
189
|
|
|
190
|
-
if
|
|
191
|
-
return
|
|
192
|
-
if isinstance(custom_headers.get("X-Api-Key"), Omit):
|
|
190
|
+
if headers.get("X-Api-Key") or isinstance(custom_headers.get("X-Api-Key"), Omit):
|
|
193
191
|
return
|
|
194
192
|
|
|
195
|
-
if
|
|
196
|
-
return
|
|
197
|
-
if isinstance(custom_headers.get("Authorization"), Omit):
|
|
193
|
+
if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
|
|
198
194
|
return
|
|
199
195
|
|
|
200
196
|
raise TypeError(
|
|
@@ -431,14 +427,10 @@ class AsyncAnthropic(AsyncAPIClient):
|
|
|
431
427
|
# valid
|
|
432
428
|
return
|
|
433
429
|
|
|
434
|
-
if
|
|
435
|
-
return
|
|
436
|
-
if isinstance(custom_headers.get("X-Api-Key"), Omit):
|
|
430
|
+
if headers.get("X-Api-Key") or isinstance(custom_headers.get("X-Api-Key"), Omit):
|
|
437
431
|
return
|
|
438
432
|
|
|
439
|
-
if
|
|
440
|
-
return
|
|
441
|
-
if isinstance(custom_headers.get("Authorization"), Omit):
|
|
433
|
+
if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
|
|
442
434
|
return
|
|
443
435
|
|
|
444
436
|
raise TypeError(
|
anthropic/_compat.py
CHANGED
|
@@ -145,6 +145,7 @@ def model_dump(
|
|
|
145
145
|
exclude_defaults: bool = False,
|
|
146
146
|
warnings: bool = True,
|
|
147
147
|
mode: Literal["json", "python"] = "python",
|
|
148
|
+
by_alias: bool | None = None,
|
|
148
149
|
) -> dict[str, Any]:
|
|
149
150
|
if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
|
|
150
151
|
return model.model_dump(
|
|
@@ -154,13 +155,12 @@ def model_dump(
|
|
|
154
155
|
exclude_defaults=exclude_defaults,
|
|
155
156
|
# warnings are not supported in Pydantic v1
|
|
156
157
|
warnings=True if PYDANTIC_V1 else warnings,
|
|
158
|
+
by_alias=by_alias,
|
|
157
159
|
)
|
|
158
160
|
return cast(
|
|
159
161
|
"dict[str, Any]",
|
|
160
162
|
model.dict( # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
|
|
161
|
-
exclude=exclude,
|
|
162
|
-
exclude_unset=exclude_unset,
|
|
163
|
-
exclude_defaults=exclude_defaults,
|
|
163
|
+
exclude=exclude, exclude_unset=exclude_unset, exclude_defaults=exclude_defaults, by_alias=bool(by_alias)
|
|
164
164
|
),
|
|
165
165
|
)
|
|
166
166
|
|
anthropic/_models.py
CHANGED
|
@@ -3,7 +3,20 @@ from __future__ import annotations
|
|
|
3
3
|
import os
|
|
4
4
|
import inspect
|
|
5
5
|
import weakref
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import (
|
|
7
|
+
IO,
|
|
8
|
+
TYPE_CHECKING,
|
|
9
|
+
Any,
|
|
10
|
+
Type,
|
|
11
|
+
Union,
|
|
12
|
+
Generic,
|
|
13
|
+
TypeVar,
|
|
14
|
+
Callable,
|
|
15
|
+
Iterable,
|
|
16
|
+
Optional,
|
|
17
|
+
AsyncIterable,
|
|
18
|
+
cast,
|
|
19
|
+
)
|
|
7
20
|
from datetime import date, datetime
|
|
8
21
|
from typing_extensions import (
|
|
9
22
|
List,
|
|
@@ -833,6 +846,7 @@ class FinalRequestOptionsInput(TypedDict, total=False):
|
|
|
833
846
|
timeout: float | Timeout | None
|
|
834
847
|
files: HttpxRequestFiles | None
|
|
835
848
|
idempotency_key: str
|
|
849
|
+
content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None]
|
|
836
850
|
json_data: Body
|
|
837
851
|
extra_json: AnyMapping
|
|
838
852
|
follow_redirects: bool
|
|
@@ -851,6 +865,7 @@ class FinalRequestOptions(pydantic.BaseModel):
|
|
|
851
865
|
post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven()
|
|
852
866
|
follow_redirects: Union[bool, None] = None
|
|
853
867
|
|
|
868
|
+
content: Union[bytes, bytearray, IO[bytes], Iterable[bytes], AsyncIterable[bytes], None] = None
|
|
854
869
|
# It should be noted that we cannot use `json` here as that would override
|
|
855
870
|
# a BaseModel method in an incompatible fashion.
|
|
856
871
|
json_data: Union[Body, None] = None
|
anthropic/_streaming.py
CHANGED
|
@@ -77,44 +77,45 @@ class Stream(Generic[_T], metaclass=_SyncStreamMeta):
|
|
|
77
77
|
process_data = self._client._process_response_data
|
|
78
78
|
iterator = self._iter_events()
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
data
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
80
|
+
try:
|
|
81
|
+
for sse in iterator:
|
|
82
|
+
if sse.event == "completion":
|
|
83
|
+
yield process_data(data=sse.json(), cast_to=cast_to, response=response)
|
|
84
|
+
|
|
85
|
+
if (
|
|
86
|
+
sse.event == "message_start"
|
|
87
|
+
or sse.event == "message_delta"
|
|
88
|
+
or sse.event == "message_stop"
|
|
89
|
+
or sse.event == "content_block_start"
|
|
90
|
+
or sse.event == "content_block_delta"
|
|
91
|
+
or sse.event == "content_block_stop"
|
|
92
|
+
):
|
|
93
|
+
data = sse.json()
|
|
94
|
+
if is_dict(data) and "type" not in data:
|
|
95
|
+
data["type"] = sse.event
|
|
96
|
+
|
|
97
|
+
yield process_data(data=data, cast_to=cast_to, response=response)
|
|
98
|
+
|
|
99
|
+
if sse.event == "ping":
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
if sse.event == "error":
|
|
103
|
+
body = sse.data
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
body = sse.json()
|
|
107
|
+
err_msg = f"{body}"
|
|
108
|
+
except Exception:
|
|
109
|
+
err_msg = sse.data or f"Error code: {response.status_code}"
|
|
110
|
+
|
|
111
|
+
raise self._client._make_status_error(
|
|
112
|
+
err_msg,
|
|
113
|
+
body=body,
|
|
114
|
+
response=self.response,
|
|
115
|
+
)
|
|
116
|
+
finally:
|
|
117
|
+
# Ensure the response is closed even if the consumer doesn't read all data
|
|
118
|
+
response.close()
|
|
118
119
|
|
|
119
120
|
def __enter__(self) -> Self:
|
|
120
121
|
return self
|
|
@@ -194,44 +195,45 @@ class AsyncStream(Generic[_T], metaclass=_AsyncStreamMeta):
|
|
|
194
195
|
process_data = self._client._process_response_data
|
|
195
196
|
iterator = self._iter_events()
|
|
196
197
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
data
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
198
|
+
try:
|
|
199
|
+
async for sse in iterator:
|
|
200
|
+
if sse.event == "completion":
|
|
201
|
+
yield process_data(data=sse.json(), cast_to=cast_to, response=response)
|
|
202
|
+
|
|
203
|
+
if (
|
|
204
|
+
sse.event == "message_start"
|
|
205
|
+
or sse.event == "message_delta"
|
|
206
|
+
or sse.event == "message_stop"
|
|
207
|
+
or sse.event == "content_block_start"
|
|
208
|
+
or sse.event == "content_block_delta"
|
|
209
|
+
or sse.event == "content_block_stop"
|
|
210
|
+
):
|
|
211
|
+
data = sse.json()
|
|
212
|
+
if is_dict(data) and "type" not in data:
|
|
213
|
+
data["type"] = sse.event
|
|
214
|
+
|
|
215
|
+
yield process_data(data=data, cast_to=cast_to, response=response)
|
|
216
|
+
|
|
217
|
+
if sse.event == "ping":
|
|
218
|
+
continue
|
|
219
|
+
|
|
220
|
+
if sse.event == "error":
|
|
221
|
+
body = sse.data
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
body = sse.json()
|
|
225
|
+
err_msg = f"{body}"
|
|
226
|
+
except Exception:
|
|
227
|
+
err_msg = sse.data or f"Error code: {response.status_code}"
|
|
228
|
+
|
|
229
|
+
raise self._client._make_status_error(
|
|
230
|
+
err_msg,
|
|
231
|
+
body=body,
|
|
232
|
+
response=self.response,
|
|
233
|
+
)
|
|
234
|
+
finally:
|
|
235
|
+
# Ensure the response is closed even if the consumer doesn't read all data
|
|
236
|
+
await response.aclose()
|
|
235
237
|
|
|
236
238
|
async def __aenter__(self) -> Self:
|
|
237
239
|
return self
|
anthropic/_types.py
CHANGED
|
@@ -13,9 +13,11 @@ from typing import (
|
|
|
13
13
|
Mapping,
|
|
14
14
|
TypeVar,
|
|
15
15
|
Callable,
|
|
16
|
+
Iterable,
|
|
16
17
|
Iterator,
|
|
17
18
|
Optional,
|
|
18
19
|
Sequence,
|
|
20
|
+
AsyncIterable,
|
|
19
21
|
)
|
|
20
22
|
from typing_extensions import (
|
|
21
23
|
Set,
|
|
@@ -57,6 +59,13 @@ if TYPE_CHECKING:
|
|
|
57
59
|
else:
|
|
58
60
|
Base64FileInput = Union[IO[bytes], PathLike]
|
|
59
61
|
FileContent = Union[IO[bytes], bytes, PathLike] # PathLike is not subscriptable in Python 3.8.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# Used for sending raw binary data / streaming data in request bodies
|
|
65
|
+
# e.g. for file uploads without multipart encoding
|
|
66
|
+
BinaryTypes = Union[bytes, bytearray, IO[bytes], Iterable[bytes]]
|
|
67
|
+
AsyncBinaryTypes = Union[bytes, bytearray, IO[bytes], AsyncIterable[bytes]]
|
|
68
|
+
|
|
60
69
|
FileTypes = Union[
|
|
61
70
|
# file (or bytes)
|
|
62
71
|
FileContent,
|
|
@@ -245,6 +254,9 @@ _T_co = TypeVar("_T_co", covariant=True)
|
|
|
245
254
|
if TYPE_CHECKING:
|
|
246
255
|
# This works because str.__contains__ does not accept object (either in typeshed or at runtime)
|
|
247
256
|
# https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285
|
|
257
|
+
#
|
|
258
|
+
# Note: index() and count() methods are intentionally omitted to allow pyright to properly
|
|
259
|
+
# infer TypedDict types when dict literals are used in lists assigned to SequenceNotStr.
|
|
248
260
|
class SequenceNotStr(Protocol[_T_co]):
|
|
249
261
|
@overload
|
|
250
262
|
def __getitem__(self, index: SupportsIndex, /) -> _T_co: ...
|
|
@@ -253,8 +265,6 @@ if TYPE_CHECKING:
|
|
|
253
265
|
def __contains__(self, value: object, /) -> bool: ...
|
|
254
266
|
def __len__(self) -> int: ...
|
|
255
267
|
def __iter__(self) -> Iterator[_T_co]: ...
|
|
256
|
-
def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ...
|
|
257
|
-
def count(self, value: Any, /) -> int: ...
|
|
258
268
|
def __reversed__(self) -> Iterator[_T_co]: ...
|
|
259
269
|
else:
|
|
260
270
|
# just point this to a normal `Sequence` at runtime to avoid having to special case
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import Any
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing_extensions import override
|
|
5
|
+
|
|
6
|
+
import pydantic
|
|
7
|
+
|
|
8
|
+
from .._compat import model_dump
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def openapi_dumps(obj: Any) -> bytes:
|
|
12
|
+
"""
|
|
13
|
+
Serialize an object to UTF-8 encoded JSON bytes.
|
|
14
|
+
|
|
15
|
+
Extends the standard json.dumps with support for additional types
|
|
16
|
+
commonly used in the SDK, such as `datetime`, `pydantic.BaseModel`, etc.
|
|
17
|
+
"""
|
|
18
|
+
return json.dumps(
|
|
19
|
+
obj,
|
|
20
|
+
cls=_CustomEncoder,
|
|
21
|
+
# Uses the same defaults as httpx's JSON serialization
|
|
22
|
+
ensure_ascii=False,
|
|
23
|
+
separators=(",", ":"),
|
|
24
|
+
allow_nan=False,
|
|
25
|
+
).encode()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class _CustomEncoder(json.JSONEncoder):
|
|
29
|
+
@override
|
|
30
|
+
def default(self, o: Any) -> Any:
|
|
31
|
+
if isinstance(o, datetime):
|
|
32
|
+
return o.isoformat()
|
|
33
|
+
if isinstance(o, pydantic.BaseModel):
|
|
34
|
+
return model_dump(o, exclude_unset=True, mode="json", by_alias=True)
|
|
35
|
+
return super().default(o)
|
anthropic/_version.py
CHANGED