raccoonai 0.1.0a16__py3-none-any.whl → 0.1.0a18__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.

Potentially problematic release.


This version of raccoonai might be problematic. Click here for more details.

raccoonai/__init__.py CHANGED
@@ -1,5 +1,7 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
+ import typing as _t
4
+
3
5
  from . import types
4
6
  from ._types import NOT_GIVEN, Omit, NoneType, NotGiven, Transport, ProxiesTypes
5
7
  from ._utils import file_from_path
@@ -80,6 +82,9 @@ __all__ = [
80
82
  "DefaultAsyncHttpxClient",
81
83
  ]
82
84
 
85
+ if not _t.TYPE_CHECKING:
86
+ from ._utils._resources_proxy import resources as resources
87
+
83
88
  _setup_logging()
84
89
 
85
90
  # Update the __module__ attribute for exported symbols so that
raccoonai/_base_client.py CHANGED
@@ -98,7 +98,11 @@ _StreamT = TypeVar("_StreamT", bound=Stream[Any])
98
98
  _AsyncStreamT = TypeVar("_AsyncStreamT", bound=AsyncStream[Any])
99
99
 
100
100
  if TYPE_CHECKING:
101
- from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
101
+ from httpx._config import (
102
+ DEFAULT_TIMEOUT_CONFIG, # pyright: ignore[reportPrivateImportUsage]
103
+ )
104
+
105
+ HTTPX_DEFAULT_TIMEOUT = DEFAULT_TIMEOUT_CONFIG
102
106
  else:
103
107
  try:
104
108
  from httpx._config import DEFAULT_TIMEOUT_CONFIG as HTTPX_DEFAULT_TIMEOUT
@@ -115,6 +119,7 @@ class PageInfo:
115
119
 
116
120
  url: URL | NotGiven
117
121
  params: Query | NotGiven
122
+ json: Body | NotGiven
118
123
 
119
124
  @overload
120
125
  def __init__(
@@ -130,19 +135,30 @@ class PageInfo:
130
135
  params: Query,
131
136
  ) -> None: ...
132
137
 
138
+ @overload
139
+ def __init__(
140
+ self,
141
+ *,
142
+ json: Body,
143
+ ) -> None: ...
144
+
133
145
  def __init__(
134
146
  self,
135
147
  *,
136
148
  url: URL | NotGiven = NOT_GIVEN,
149
+ json: Body | NotGiven = NOT_GIVEN,
137
150
  params: Query | NotGiven = NOT_GIVEN,
138
151
  ) -> None:
139
152
  self.url = url
153
+ self.json = json
140
154
  self.params = params
141
155
 
142
156
  @override
143
157
  def __repr__(self) -> str:
144
158
  if self.url:
145
159
  return f"{self.__class__.__name__}(url={self.url})"
160
+ if self.json:
161
+ return f"{self.__class__.__name__}(json={self.json})"
146
162
  return f"{self.__class__.__name__}(params={self.params})"
147
163
 
148
164
 
@@ -191,6 +207,19 @@ class BasePage(GenericModel, Generic[_T]):
191
207
  options.url = str(url)
192
208
  return options
193
209
 
210
+ if not isinstance(info.json, NotGiven):
211
+ if not is_mapping(info.json):
212
+ raise TypeError("Pagination is only supported with mappings")
213
+
214
+ if not options.json_data:
215
+ options.json_data = {**info.json}
216
+ else:
217
+ if not is_mapping(options.json_data):
218
+ raise TypeError("Pagination is only supported with mappings")
219
+
220
+ options.json_data = {**options.json_data, **info.json}
221
+ return options
222
+
194
223
  raise ValueError("Unexpected PageInfo state")
195
224
 
196
225
 
@@ -408,8 +437,8 @@ class BaseClient(Generic[_HttpxClientT, _DefaultStreamT]):
408
437
  headers = httpx.Headers(headers_dict)
409
438
 
410
439
  idempotency_header = self._idempotency_header
411
- if idempotency_header and options.method.lower() != "get" and idempotency_header not in headers:
412
- headers[idempotency_header] = options.idempotency_key or self._idempotency_key()
440
+ if idempotency_header and options.idempotency_key and idempotency_header not in headers:
441
+ headers[idempotency_header] = options.idempotency_key
413
442
 
414
443
  # Don't set these headers if they were already set or removed by the caller. We check
415
444
  # `custom_headers`, which can contain `Omit()`, instead of `headers` to account for the removal case.
@@ -873,7 +902,6 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
873
902
  self,
874
903
  cast_to: Type[ResponseT],
875
904
  options: FinalRequestOptions,
876
- remaining_retries: Optional[int] = None,
877
905
  *,
878
906
  stream: Literal[True],
879
907
  stream_cls: Type[_StreamT],
@@ -884,7 +912,6 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
884
912
  self,
885
913
  cast_to: Type[ResponseT],
886
914
  options: FinalRequestOptions,
887
- remaining_retries: Optional[int] = None,
888
915
  *,
889
916
  stream: Literal[False] = False,
890
917
  ) -> ResponseT: ...
@@ -894,7 +921,6 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
894
921
  self,
895
922
  cast_to: Type[ResponseT],
896
923
  options: FinalRequestOptions,
897
- remaining_retries: Optional[int] = None,
898
924
  *,
899
925
  stream: bool = False,
900
926
  stream_cls: Type[_StreamT] | None = None,
@@ -904,121 +930,112 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
904
930
  self,
905
931
  cast_to: Type[ResponseT],
906
932
  options: FinalRequestOptions,
907
- remaining_retries: Optional[int] = None,
908
933
  *,
909
934
  stream: bool = False,
910
935
  stream_cls: type[_StreamT] | None = None,
911
936
  ) -> ResponseT | _StreamT:
912
- if remaining_retries is not None:
913
- retries_taken = options.get_max_retries(self.max_retries) - remaining_retries
914
- else:
915
- retries_taken = 0
916
-
917
- return self._request(
918
- cast_to=cast_to,
919
- options=options,
920
- stream=stream,
921
- stream_cls=stream_cls,
922
- retries_taken=retries_taken,
923
- )
937
+ cast_to = self._maybe_override_cast_to(cast_to, options)
924
938
 
925
- def _request(
926
- self,
927
- *,
928
- cast_to: Type[ResponseT],
929
- options: FinalRequestOptions,
930
- retries_taken: int,
931
- stream: bool,
932
- stream_cls: type[_StreamT] | None,
933
- ) -> ResponseT | _StreamT:
934
939
  # create a copy of the options we were given so that if the
935
940
  # options are mutated later & we then retry, the retries are
936
941
  # given the original options
937
942
  input_options = model_copy(options)
943
+ if input_options.idempotency_key is None and input_options.method.lower() != "get":
944
+ # ensure the idempotency key is reused between requests
945
+ input_options.idempotency_key = self._idempotency_key()
938
946
 
939
- cast_to = self._maybe_override_cast_to(cast_to, options)
940
- options = self._prepare_options(options)
947
+ response: httpx.Response | None = None
948
+ max_retries = input_options.get_max_retries(self.max_retries)
941
949
 
942
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
943
- request = self._build_request(options, retries_taken=retries_taken)
944
- self._prepare_request(request)
950
+ retries_taken = 0
951
+ for retries_taken in range(max_retries + 1):
952
+ options = model_copy(input_options)
953
+ options = self._prepare_options(options)
945
954
 
946
- kwargs: HttpxSendArgs = {}
947
- if self.custom_auth is not None:
948
- kwargs["auth"] = self.custom_auth
955
+ remaining_retries = max_retries - retries_taken
956
+ request = self._build_request(options, retries_taken=retries_taken)
957
+ self._prepare_request(request)
949
958
 
950
- log.debug("Sending HTTP Request: %s %s", request.method, request.url)
959
+ kwargs: HttpxSendArgs = {}
960
+ if self.custom_auth is not None:
961
+ kwargs["auth"] = self.custom_auth
951
962
 
952
- try:
953
- response = self._client.send(
954
- request,
955
- stream=stream or self._should_stream_response_body(request=request),
956
- **kwargs,
957
- )
958
- except httpx.TimeoutException as err:
959
- log.debug("Encountered httpx.TimeoutException", exc_info=True)
963
+ if options.follow_redirects is not None:
964
+ kwargs["follow_redirects"] = options.follow_redirects
960
965
 
961
- if remaining_retries > 0:
962
- return self._retry_request(
963
- input_options,
964
- cast_to,
965
- retries_taken=retries_taken,
966
- stream=stream,
967
- stream_cls=stream_cls,
968
- response_headers=None,
969
- )
966
+ log.debug("Sending HTTP Request: %s %s", request.method, request.url)
970
967
 
971
- log.debug("Raising timeout error")
972
- raise APITimeoutError(request=request) from err
973
- except Exception as err:
974
- log.debug("Encountered Exception", exc_info=True)
975
-
976
- if remaining_retries > 0:
977
- return self._retry_request(
978
- input_options,
979
- cast_to,
980
- retries_taken=retries_taken,
981
- stream=stream,
982
- stream_cls=stream_cls,
983
- response_headers=None,
968
+ response = None
969
+ try:
970
+ response = self._client.send(
971
+ request,
972
+ stream=stream or self._should_stream_response_body(request=request),
973
+ **kwargs,
984
974
  )
975
+ except httpx.TimeoutException as err:
976
+ log.debug("Encountered httpx.TimeoutException", exc_info=True)
977
+
978
+ if remaining_retries > 0:
979
+ self._sleep_for_retry(
980
+ retries_taken=retries_taken,
981
+ max_retries=max_retries,
982
+ options=input_options,
983
+ response=None,
984
+ )
985
+ continue
986
+
987
+ log.debug("Raising timeout error")
988
+ raise APITimeoutError(request=request) from err
989
+ except Exception as err:
990
+ log.debug("Encountered Exception", exc_info=True)
991
+
992
+ if remaining_retries > 0:
993
+ self._sleep_for_retry(
994
+ retries_taken=retries_taken,
995
+ max_retries=max_retries,
996
+ options=input_options,
997
+ response=None,
998
+ )
999
+ continue
1000
+
1001
+ log.debug("Raising connection error")
1002
+ raise APIConnectionError(request=request) from err
1003
+
1004
+ log.debug(
1005
+ 'HTTP Response: %s %s "%i %s" %s',
1006
+ request.method,
1007
+ request.url,
1008
+ response.status_code,
1009
+ response.reason_phrase,
1010
+ response.headers,
1011
+ )
985
1012
 
986
- log.debug("Raising connection error")
987
- raise APIConnectionError(request=request) from err
988
-
989
- log.debug(
990
- 'HTTP Response: %s %s "%i %s" %s',
991
- request.method,
992
- request.url,
993
- response.status_code,
994
- response.reason_phrase,
995
- response.headers,
996
- )
1013
+ try:
1014
+ response.raise_for_status()
1015
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1016
+ log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
1017
+
1018
+ if remaining_retries > 0 and self._should_retry(err.response):
1019
+ err.response.close()
1020
+ self._sleep_for_retry(
1021
+ retries_taken=retries_taken,
1022
+ max_retries=max_retries,
1023
+ options=input_options,
1024
+ response=response,
1025
+ )
1026
+ continue
997
1027
 
998
- try:
999
- response.raise_for_status()
1000
- except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1001
- log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
1002
-
1003
- if remaining_retries > 0 and self._should_retry(err.response):
1004
- err.response.close()
1005
- return self._retry_request(
1006
- input_options,
1007
- cast_to,
1008
- retries_taken=retries_taken,
1009
- response_headers=err.response.headers,
1010
- stream=stream,
1011
- stream_cls=stream_cls,
1012
- )
1028
+ # If the response is streamed then we need to explicitly read the response
1029
+ # to completion before attempting to access the response text.
1030
+ if not err.response.is_closed:
1031
+ err.response.read()
1013
1032
 
1014
- # If the response is streamed then we need to explicitly read the response
1015
- # to completion before attempting to access the response text.
1016
- if not err.response.is_closed:
1017
- err.response.read()
1033
+ log.debug("Re-raising status error")
1034
+ raise self._make_status_error_from_response(err.response) from None
1018
1035
 
1019
- log.debug("Re-raising status error")
1020
- raise self._make_status_error_from_response(err.response) from None
1036
+ break
1021
1037
 
1038
+ assert response is not None, "could not resolve response (should never happen)"
1022
1039
  return self._process_response(
1023
1040
  cast_to=cast_to,
1024
1041
  options=options,
@@ -1028,37 +1045,20 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1028
1045
  retries_taken=retries_taken,
1029
1046
  )
1030
1047
 
1031
- def _retry_request(
1032
- self,
1033
- options: FinalRequestOptions,
1034
- cast_to: Type[ResponseT],
1035
- *,
1036
- retries_taken: int,
1037
- response_headers: httpx.Headers | None,
1038
- stream: bool,
1039
- stream_cls: type[_StreamT] | None,
1040
- ) -> ResponseT | _StreamT:
1041
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
1048
+ def _sleep_for_retry(
1049
+ self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None
1050
+ ) -> None:
1051
+ remaining_retries = max_retries - retries_taken
1042
1052
  if remaining_retries == 1:
1043
1053
  log.debug("1 retry left")
1044
1054
  else:
1045
1055
  log.debug("%i retries left", remaining_retries)
1046
1056
 
1047
- timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers)
1057
+ timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None)
1048
1058
  log.info("Retrying request to %s in %f seconds", options.url, timeout)
1049
1059
 
1050
- # In a synchronous context we are blocking the entire thread. Up to the library user to run the client in a
1051
- # different thread if necessary.
1052
1060
  time.sleep(timeout)
1053
1061
 
1054
- return self._request(
1055
- options=options,
1056
- cast_to=cast_to,
1057
- retries_taken=retries_taken + 1,
1058
- stream=stream,
1059
- stream_cls=stream_cls,
1060
- )
1061
-
1062
1062
  def _process_response(
1063
1063
  self,
1064
1064
  *,
@@ -1071,7 +1071,14 @@ class SyncAPIClient(BaseClient[httpx.Client, Stream[Any]]):
1071
1071
  ) -> ResponseT:
1072
1072
  origin = get_origin(cast_to) or cast_to
1073
1073
 
1074
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1074
+ if (
1075
+ inspect.isclass(origin)
1076
+ and issubclass(origin, BaseAPIResponse)
1077
+ # we only want to actually return the custom BaseAPIResponse class if we're
1078
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1079
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1080
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1081
+ ):
1075
1082
  if not issubclass(origin, APIResponse):
1076
1083
  raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}")
1077
1084
 
@@ -1402,7 +1409,6 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1402
1409
  options: FinalRequestOptions,
1403
1410
  *,
1404
1411
  stream: Literal[False] = False,
1405
- remaining_retries: Optional[int] = None,
1406
1412
  ) -> ResponseT: ...
1407
1413
 
1408
1414
  @overload
@@ -1413,7 +1419,6 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1413
1419
  *,
1414
1420
  stream: Literal[True],
1415
1421
  stream_cls: type[_AsyncStreamT],
1416
- remaining_retries: Optional[int] = None,
1417
1422
  ) -> _AsyncStreamT: ...
1418
1423
 
1419
1424
  @overload
@@ -1424,7 +1429,6 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1424
1429
  *,
1425
1430
  stream: bool,
1426
1431
  stream_cls: type[_AsyncStreamT] | None = None,
1427
- remaining_retries: Optional[int] = None,
1428
1432
  ) -> ResponseT | _AsyncStreamT: ...
1429
1433
 
1430
1434
  async def request(
@@ -1434,116 +1438,114 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1434
1438
  *,
1435
1439
  stream: bool = False,
1436
1440
  stream_cls: type[_AsyncStreamT] | None = None,
1437
- remaining_retries: Optional[int] = None,
1438
- ) -> ResponseT | _AsyncStreamT:
1439
- if remaining_retries is not None:
1440
- retries_taken = options.get_max_retries(self.max_retries) - remaining_retries
1441
- else:
1442
- retries_taken = 0
1443
-
1444
- return await self._request(
1445
- cast_to=cast_to,
1446
- options=options,
1447
- stream=stream,
1448
- stream_cls=stream_cls,
1449
- retries_taken=retries_taken,
1450
- )
1451
-
1452
- async def _request(
1453
- self,
1454
- cast_to: Type[ResponseT],
1455
- options: FinalRequestOptions,
1456
- *,
1457
- stream: bool,
1458
- stream_cls: type[_AsyncStreamT] | None,
1459
- retries_taken: int,
1460
1441
  ) -> ResponseT | _AsyncStreamT:
1461
1442
  if self._platform is None:
1462
1443
  # `get_platform` can make blocking IO calls so we
1463
1444
  # execute it earlier while we are in an async context
1464
1445
  self._platform = await asyncify(get_platform)()
1465
1446
 
1447
+ cast_to = self._maybe_override_cast_to(cast_to, options)
1448
+
1466
1449
  # create a copy of the options we were given so that if the
1467
1450
  # options are mutated later & we then retry, the retries are
1468
1451
  # given the original options
1469
1452
  input_options = model_copy(options)
1453
+ if input_options.idempotency_key is None and input_options.method.lower() != "get":
1454
+ # ensure the idempotency key is reused between requests
1455
+ input_options.idempotency_key = self._idempotency_key()
1470
1456
 
1471
- cast_to = self._maybe_override_cast_to(cast_to, options)
1472
- options = await self._prepare_options(options)
1457
+ response: httpx.Response | None = None
1458
+ max_retries = input_options.get_max_retries(self.max_retries)
1473
1459
 
1474
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
1475
- request = self._build_request(options, retries_taken=retries_taken)
1476
- await self._prepare_request(request)
1460
+ retries_taken = 0
1461
+ for retries_taken in range(max_retries + 1):
1462
+ options = model_copy(input_options)
1463
+ options = await self._prepare_options(options)
1477
1464
 
1478
- kwargs: HttpxSendArgs = {}
1479
- if self.custom_auth is not None:
1480
- kwargs["auth"] = self.custom_auth
1465
+ remaining_retries = max_retries - retries_taken
1466
+ request = self._build_request(options, retries_taken=retries_taken)
1467
+ await self._prepare_request(request)
1481
1468
 
1482
- try:
1483
- response = await self._client.send(
1484
- request,
1485
- stream=stream or self._should_stream_response_body(request=request),
1486
- **kwargs,
1487
- )
1488
- except httpx.TimeoutException as err:
1489
- log.debug("Encountered httpx.TimeoutException", exc_info=True)
1469
+ kwargs: HttpxSendArgs = {}
1470
+ if self.custom_auth is not None:
1471
+ kwargs["auth"] = self.custom_auth
1490
1472
 
1491
- if remaining_retries > 0:
1492
- return await self._retry_request(
1493
- input_options,
1494
- cast_to,
1495
- retries_taken=retries_taken,
1496
- stream=stream,
1497
- stream_cls=stream_cls,
1498
- response_headers=None,
1499
- )
1473
+ if options.follow_redirects is not None:
1474
+ kwargs["follow_redirects"] = options.follow_redirects
1500
1475
 
1501
- log.debug("Raising timeout error")
1502
- raise APITimeoutError(request=request) from err
1503
- except Exception as err:
1504
- log.debug("Encountered Exception", exc_info=True)
1476
+ log.debug("Sending HTTP Request: %s %s", request.method, request.url)
1505
1477
 
1506
- if remaining_retries > 0:
1507
- return await self._retry_request(
1508
- input_options,
1509
- cast_to,
1510
- retries_taken=retries_taken,
1511
- stream=stream,
1512
- stream_cls=stream_cls,
1513
- response_headers=None,
1478
+ response = None
1479
+ try:
1480
+ response = await self._client.send(
1481
+ request,
1482
+ stream=stream or self._should_stream_response_body(request=request),
1483
+ **kwargs,
1514
1484
  )
1485
+ except httpx.TimeoutException as err:
1486
+ log.debug("Encountered httpx.TimeoutException", exc_info=True)
1487
+
1488
+ if remaining_retries > 0:
1489
+ await self._sleep_for_retry(
1490
+ retries_taken=retries_taken,
1491
+ max_retries=max_retries,
1492
+ options=input_options,
1493
+ response=None,
1494
+ )
1495
+ continue
1496
+
1497
+ log.debug("Raising timeout error")
1498
+ raise APITimeoutError(request=request) from err
1499
+ except Exception as err:
1500
+ log.debug("Encountered Exception", exc_info=True)
1501
+
1502
+ if remaining_retries > 0:
1503
+ await self._sleep_for_retry(
1504
+ retries_taken=retries_taken,
1505
+ max_retries=max_retries,
1506
+ options=input_options,
1507
+ response=None,
1508
+ )
1509
+ continue
1510
+
1511
+ log.debug("Raising connection error")
1512
+ raise APIConnectionError(request=request) from err
1513
+
1514
+ log.debug(
1515
+ 'HTTP Response: %s %s "%i %s" %s',
1516
+ request.method,
1517
+ request.url,
1518
+ response.status_code,
1519
+ response.reason_phrase,
1520
+ response.headers,
1521
+ )
1515
1522
 
1516
- log.debug("Raising connection error")
1517
- raise APIConnectionError(request=request) from err
1523
+ try:
1524
+ response.raise_for_status()
1525
+ except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1526
+ log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
1527
+
1528
+ if remaining_retries > 0 and self._should_retry(err.response):
1529
+ await err.response.aclose()
1530
+ await self._sleep_for_retry(
1531
+ retries_taken=retries_taken,
1532
+ max_retries=max_retries,
1533
+ options=input_options,
1534
+ response=response,
1535
+ )
1536
+ continue
1518
1537
 
1519
- log.debug(
1520
- 'HTTP Request: %s %s "%i %s"', request.method, request.url, response.status_code, response.reason_phrase
1521
- )
1538
+ # If the response is streamed then we need to explicitly read the response
1539
+ # to completion before attempting to access the response text.
1540
+ if not err.response.is_closed:
1541
+ await err.response.aread()
1522
1542
 
1523
- try:
1524
- response.raise_for_status()
1525
- except httpx.HTTPStatusError as err: # thrown on 4xx and 5xx status code
1526
- log.debug("Encountered httpx.HTTPStatusError", exc_info=True)
1527
-
1528
- if remaining_retries > 0 and self._should_retry(err.response):
1529
- await err.response.aclose()
1530
- return await self._retry_request(
1531
- input_options,
1532
- cast_to,
1533
- retries_taken=retries_taken,
1534
- response_headers=err.response.headers,
1535
- stream=stream,
1536
- stream_cls=stream_cls,
1537
- )
1543
+ log.debug("Re-raising status error")
1544
+ raise self._make_status_error_from_response(err.response) from None
1538
1545
 
1539
- # If the response is streamed then we need to explicitly read the response
1540
- # to completion before attempting to access the response text.
1541
- if not err.response.is_closed:
1542
- await err.response.aread()
1543
-
1544
- log.debug("Re-raising status error")
1545
- raise self._make_status_error_from_response(err.response) from None
1546
+ break
1546
1547
 
1548
+ assert response is not None, "could not resolve response (should never happen)"
1547
1549
  return await self._process_response(
1548
1550
  cast_to=cast_to,
1549
1551
  options=options,
@@ -1553,35 +1555,20 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1553
1555
  retries_taken=retries_taken,
1554
1556
  )
1555
1557
 
1556
- async def _retry_request(
1557
- self,
1558
- options: FinalRequestOptions,
1559
- cast_to: Type[ResponseT],
1560
- *,
1561
- retries_taken: int,
1562
- response_headers: httpx.Headers | None,
1563
- stream: bool,
1564
- stream_cls: type[_AsyncStreamT] | None,
1565
- ) -> ResponseT | _AsyncStreamT:
1566
- remaining_retries = options.get_max_retries(self.max_retries) - retries_taken
1558
+ async def _sleep_for_retry(
1559
+ self, *, retries_taken: int, max_retries: int, options: FinalRequestOptions, response: httpx.Response | None
1560
+ ) -> None:
1561
+ remaining_retries = max_retries - retries_taken
1567
1562
  if remaining_retries == 1:
1568
1563
  log.debug("1 retry left")
1569
1564
  else:
1570
1565
  log.debug("%i retries left", remaining_retries)
1571
1566
 
1572
- timeout = self._calculate_retry_timeout(remaining_retries, options, response_headers)
1567
+ timeout = self._calculate_retry_timeout(remaining_retries, options, response.headers if response else None)
1573
1568
  log.info("Retrying request to %s in %f seconds", options.url, timeout)
1574
1569
 
1575
1570
  await anyio.sleep(timeout)
1576
1571
 
1577
- return await self._request(
1578
- options=options,
1579
- cast_to=cast_to,
1580
- retries_taken=retries_taken + 1,
1581
- stream=stream,
1582
- stream_cls=stream_cls,
1583
- )
1584
-
1585
1572
  async def _process_response(
1586
1573
  self,
1587
1574
  *,
@@ -1594,7 +1581,14 @@ class AsyncAPIClient(BaseClient[httpx.AsyncClient, AsyncStream[Any]]):
1594
1581
  ) -> ResponseT:
1595
1582
  origin = get_origin(cast_to) or cast_to
1596
1583
 
1597
- if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse):
1584
+ if (
1585
+ inspect.isclass(origin)
1586
+ and issubclass(origin, BaseAPIResponse)
1587
+ # we only want to actually return the custom BaseAPIResponse class if we're
1588
+ # returning the raw response, or if we're not streaming SSE, as if we're streaming
1589
+ # SSE then `cast_to` doesn't actively reflect the type we need to parse into
1590
+ and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER)))
1591
+ ):
1598
1592
  if not issubclass(origin, AsyncAPIResponse):
1599
1593
  raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}")
1600
1594
 
raccoonai/_client.py CHANGED
@@ -19,10 +19,7 @@ from ._types import (
19
19
  ProxiesTypes,
20
20
  RequestOptions,
21
21
  )
22
- from ._utils import (
23
- is_given,
24
- get_async_library,
25
- )
22
+ from ._utils import is_given, get_async_library
26
23
  from ._version import __version__
27
24
  from ._streaming import Stream as Stream, AsyncStream as AsyncStream
28
25
  from ._exceptions import APIStatusError, RaccoonAIError
raccoonai/_models.py CHANGED
@@ -19,7 +19,6 @@ from typing_extensions import (
19
19
  )
20
20
 
21
21
  import pydantic
22
- import pydantic.generics
23
22
  from pydantic.fields import FieldInfo
24
23
 
25
24
  from ._types import (
@@ -627,8 +626,8 @@ def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any,
627
626
  # Note: if one variant defines an alias then they all should
628
627
  discriminator_alias = field_info.alias
629
628
 
630
- if field_info.annotation and is_literal_type(field_info.annotation):
631
- for entry in get_args(field_info.annotation):
629
+ if (annotation := getattr(field_info, "annotation", None)) and is_literal_type(annotation):
630
+ for entry in get_args(annotation):
632
631
  if isinstance(entry, str):
633
632
  mapping[entry] = variant
634
633
 
@@ -738,6 +737,7 @@ class FinalRequestOptionsInput(TypedDict, total=False):
738
737
  idempotency_key: str
739
738
  json_data: Body
740
739
  extra_json: AnyMapping
740
+ follow_redirects: bool
741
741
 
742
742
 
743
743
  @final
@@ -751,6 +751,7 @@ class FinalRequestOptions(pydantic.BaseModel):
751
751
  files: Union[HttpxRequestFiles, None] = None
752
752
  idempotency_key: Union[str, None] = None
753
753
  post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven()
754
+ follow_redirects: Union[bool, None] = None
754
755
 
755
756
  # It should be noted that we cannot use `json` here as that would override
756
757
  # a BaseModel method in an incompatible fashion.
raccoonai/_response.py CHANGED
@@ -233,7 +233,7 @@ class BaseAPIResponse(Generic[R]):
233
233
  # split is required to handle cases where additional information is included
234
234
  # in the response, e.g. application/json; charset=utf-8
235
235
  content_type, *_ = response.headers.get("content-type", "*").split(";")
236
- if content_type != "application/json":
236
+ if not content_type.endswith("json"):
237
237
  if is_basemodel(cast_to):
238
238
  try:
239
239
  data = response.json()
raccoonai/_types.py CHANGED
@@ -100,6 +100,7 @@ class RequestOptions(TypedDict, total=False):
100
100
  params: Query
101
101
  extra_json: AnyMapping
102
102
  idempotency_key: str
103
+ follow_redirects: bool
103
104
 
104
105
 
105
106
  # Sentinel class used until PEP 0661 is accepted
@@ -215,3 +216,4 @@ class _GenericAlias(Protocol):
215
216
 
216
217
  class HttpxSendArgs(TypedDict, total=False):
217
218
  auth: httpx.Auth
219
+ follow_redirects: bool
@@ -46,7 +46,10 @@ class LazyProxy(Generic[T], ABC):
46
46
  @property # type: ignore
47
47
  @override
48
48
  def __class__(self) -> type: # pyright: ignore
49
- proxied = self.__get_proxied__()
49
+ try:
50
+ proxied = self.__get_proxied__()
51
+ except Exception:
52
+ return type(self)
50
53
  if issubclass(type(proxied), LazyProxy):
51
54
  return type(proxied)
52
55
  return proxied.__class__
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+ from typing_extensions import override
5
+
6
+ from ._proxy import LazyProxy
7
+
8
+
9
+ class ResourcesProxy(LazyProxy[Any]):
10
+ """A proxy for the `raccoonai.resources` module.
11
+
12
+ This is used so that we can lazily import `raccoonai.resources` only when
13
+ needed *and* so that users can just import `raccoonai` and reference `raccoonai.resources`
14
+ """
15
+
16
+ @override
17
+ def __load__(self) -> Any:
18
+ import importlib
19
+
20
+ mod = importlib.import_module("raccoonai.resources")
21
+ return mod
22
+
23
+
24
+ resources = ResourcesProxy().__as_proxied__()
@@ -5,13 +5,15 @@ import base64
5
5
  import pathlib
6
6
  from typing import Any, Mapping, TypeVar, cast
7
7
  from datetime import date, datetime
8
- from typing_extensions import Literal, get_args, override, get_type_hints
8
+ from typing_extensions import Literal, get_args, override, get_type_hints as _get_type_hints
9
9
 
10
10
  import anyio
11
11
  import pydantic
12
12
 
13
13
  from ._utils import (
14
14
  is_list,
15
+ is_given,
16
+ lru_cache,
15
17
  is_mapping,
16
18
  is_iterable,
17
19
  )
@@ -108,6 +110,7 @@ def transform(
108
110
  return cast(_T, transformed)
109
111
 
110
112
 
113
+ @lru_cache(maxsize=8096)
111
114
  def _get_annotated_type(type_: type) -> type | None:
112
115
  """If the given type is an `Annotated` type then it is returned, if not `None` is returned.
113
116
 
@@ -142,6 +145,10 @@ def _maybe_transform_key(key: str, type_: type) -> str:
142
145
  return key
143
146
 
144
147
 
148
+ def _no_transform_needed(annotation: type) -> bool:
149
+ return annotation == float or annotation == int
150
+
151
+
145
152
  def _transform_recursive(
146
153
  data: object,
147
154
  *,
@@ -184,6 +191,15 @@ def _transform_recursive(
184
191
  return cast(object, data)
185
192
 
186
193
  inner_type = extract_type_arg(stripped_type, 0)
194
+ if _no_transform_needed(inner_type):
195
+ # for some types there is no need to transform anything, so we can get a small
196
+ # perf boost from skipping that work.
197
+ #
198
+ # but we still need to convert to a list to ensure the data is json-serializable
199
+ if is_list(data):
200
+ return data
201
+ return list(data)
202
+
187
203
  return [_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
188
204
 
189
205
  if is_union_type(stripped_type):
@@ -245,6 +261,11 @@ def _transform_typeddict(
245
261
  result: dict[str, object] = {}
246
262
  annotations = get_type_hints(expected_type, include_extras=True)
247
263
  for key, value in data.items():
264
+ if not is_given(value):
265
+ # we don't need to include `NotGiven` values here as they'll
266
+ # be stripped out before the request is sent anyway
267
+ continue
268
+
248
269
  type_ = annotations.get(key)
249
270
  if type_ is None:
250
271
  # we do not have a type annotation for this field, leave it as is
@@ -332,6 +353,15 @@ async def _async_transform_recursive(
332
353
  return cast(object, data)
333
354
 
334
355
  inner_type = extract_type_arg(stripped_type, 0)
356
+ if _no_transform_needed(inner_type):
357
+ # for some types there is no need to transform anything, so we can get a small
358
+ # perf boost from skipping that work.
359
+ #
360
+ # but we still need to convert to a list to ensure the data is json-serializable
361
+ if is_list(data):
362
+ return data
363
+ return list(data)
364
+
335
365
  return [await _async_transform_recursive(d, annotation=annotation, inner_type=inner_type) for d in data]
336
366
 
337
367
  if is_union_type(stripped_type):
@@ -393,6 +423,11 @@ async def _async_transform_typeddict(
393
423
  result: dict[str, object] = {}
394
424
  annotations = get_type_hints(expected_type, include_extras=True)
395
425
  for key, value in data.items():
426
+ if not is_given(value):
427
+ # we don't need to include `NotGiven` values here as they'll
428
+ # be stripped out before the request is sent anyway
429
+ continue
430
+
396
431
  type_ = annotations.get(key)
397
432
  if type_ is None:
398
433
  # we do not have a type annotation for this field, leave it as is
@@ -400,3 +435,13 @@ async def _async_transform_typeddict(
400
435
  else:
401
436
  result[_maybe_transform_key(key, type_)] = await _async_transform_recursive(value, annotation=type_)
402
437
  return result
438
+
439
+
440
+ @lru_cache(maxsize=8096)
441
+ def get_type_hints(
442
+ obj: Any,
443
+ globalns: dict[str, Any] | None = None,
444
+ localns: Mapping[str, Any] | None = None,
445
+ include_extras: bool = False,
446
+ ) -> dict[str, Any]:
447
+ return _get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras)
@@ -13,6 +13,7 @@ from typing_extensions import (
13
13
  get_origin,
14
14
  )
15
15
 
16
+ from ._utils import lru_cache
16
17
  from .._types import InheritsGeneric
17
18
  from .._compat import is_union as _is_union
18
19
 
@@ -66,6 +67,7 @@ def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]:
66
67
 
67
68
 
68
69
  # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]]
70
+ @lru_cache(maxsize=8096)
69
71
  def strip_annotated_type(typ: type) -> type:
70
72
  if is_required_type(typ) or is_annotated_type(typ):
71
73
  return strip_annotated_type(cast(type, get_args(typ)[0]))
@@ -108,7 +110,7 @@ def extract_type_var_from_base(
108
110
  ```
109
111
  """
110
112
  cls = cast(object, get_origin(typ) or typ)
111
- if cls in generic_bases:
113
+ if cls in generic_bases: # pyright: ignore[reportUnnecessaryContains]
112
114
  # we're given the class directly
113
115
  return extract_type_arg(typ, index)
114
116
 
@@ -72,8 +72,16 @@ def _extract_items(
72
72
  from .._files import assert_is_file_content
73
73
 
74
74
  # We have exhausted the path, return the entry we found.
75
- assert_is_file_content(obj, key=flattened_key)
76
75
  assert flattened_key is not None
76
+
77
+ if is_list(obj):
78
+ files: list[tuple[str, FileTypes]] = []
79
+ for entry in obj:
80
+ assert_is_file_content(entry, key=flattened_key + "[]" if flattened_key else "")
81
+ files.append((flattened_key + "[]", cast(FileTypes, entry)))
82
+ return files
83
+
84
+ assert_is_file_content(obj, key=flattened_key)
77
85
  return [(flattened_key, cast(FileTypes, obj))]
78
86
 
79
87
  index += 1
raccoonai/_version.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "raccoonai"
4
- __version__ = "0.1.0-alpha.16" # x-release-please-version
4
+ __version__ = "0.1.0-alpha.18" # x-release-please-version
@@ -7,12 +7,7 @@ from typing import Mapping, cast
7
7
  import httpx
8
8
 
9
9
  from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven, FileTypes
10
- from ..._utils import (
11
- extract_files,
12
- maybe_transform,
13
- deepcopy_minimal,
14
- async_maybe_transform,
15
- )
10
+ from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
16
11
  from ..._compat import cached_property
17
12
  from ..._resource import SyncAPIResource, AsyncAPIResource
18
13
  from ..._response import (
@@ -8,10 +8,7 @@ from typing_extensions import Literal
8
8
  import httpx
9
9
 
10
10
  from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
11
- from ..._utils import (
12
- maybe_transform,
13
- async_maybe_transform,
14
- )
11
+ from ..._utils import maybe_transform, async_maybe_transform
15
12
  from ..._compat import cached_property
16
13
  from ..._resource import SyncAPIResource, AsyncAPIResource
17
14
  from ..._response import (
@@ -17,11 +17,7 @@ from .tasks import (
17
17
  )
18
18
  from ...types import lam_run_params
19
19
  from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
20
- from ..._utils import (
21
- required_args,
22
- maybe_transform,
23
- async_maybe_transform,
24
- )
20
+ from ..._utils import required_args, maybe_transform, async_maybe_transform
25
21
  from ..._compat import cached_property
26
22
  from ..._resource import SyncAPIResource, AsyncAPIResource
27
23
  from ..._response import (
@@ -266,7 +262,7 @@ class LamResource(SyncAPIResource):
266
262
  "schema": schema,
267
263
  "stream": stream,
268
264
  },
269
- lam_run_params.LamRunParams,
265
+ lam_run_params.LamRunParamsStreaming if stream else lam_run_params.LamRunParamsNonStreaming,
270
266
  ),
271
267
  options=make_request_options(
272
268
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -506,7 +502,7 @@ class AsyncLamResource(AsyncAPIResource):
506
502
  "schema": schema,
507
503
  "stream": stream,
508
504
  },
509
- lam_run_params.LamRunParams,
505
+ lam_run_params.LamRunParamsStreaming if stream else lam_run_params.LamRunParamsNonStreaming,
510
506
  ),
511
507
  options=make_request_options(
512
508
  extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -8,10 +8,7 @@ from typing_extensions import Literal
8
8
  import httpx
9
9
 
10
10
  from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
11
- from ..._utils import (
12
- maybe_transform,
13
- async_maybe_transform,
14
- )
11
+ from ..._utils import maybe_transform, async_maybe_transform
15
12
  from ..._compat import cached_property
16
13
  from ..._resource import SyncAPIResource, AsyncAPIResource
17
14
  from ..._response import (
@@ -5,10 +5,7 @@ from __future__ import annotations
5
5
  import httpx
6
6
 
7
7
  from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
8
- from ..._utils import (
9
- maybe_transform,
10
- async_maybe_transform,
11
- )
8
+ from ..._utils import maybe_transform, async_maybe_transform
12
9
  from ..._compat import cached_property
13
10
  from ..._resource import SyncAPIResource, AsyncAPIResource
14
11
  from ..._response import (
@@ -8,10 +8,7 @@ from typing_extensions import Literal
8
8
  import httpx
9
9
 
10
10
  from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven
11
- from ..._utils import (
12
- maybe_transform,
13
- async_maybe_transform,
14
- )
11
+ from ..._utils import maybe_transform, async_maybe_transform
15
12
  from ..._compat import cached_property
16
13
  from ..._resource import SyncAPIResource, AsyncAPIResource
17
14
  from ..._response import (
@@ -1,6 +1,5 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
-
4
3
  from pydantic import Field as FieldInfo
5
4
 
6
5
  from ..._models import BaseModel
@@ -1,6 +1,5 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
-
4
3
  from pydantic import Field as FieldInfo
5
4
 
6
5
  from ..._models import BaseModel
@@ -1,6 +1,5 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
-
4
3
  from ..._models import BaseModel
5
4
 
6
5
  __all__ = ["SessionLogsResponse"]
@@ -1,6 +1,5 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
-
4
3
  from pydantic import Field as FieldInfo
5
4
 
6
5
  from ..._models import BaseModel
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: raccoonai
3
- Version: 0.1.0a16
3
+ Version: 0.1.0a18
4
4
  Summary: The official Python library for the raccoonAI API
5
5
  Project-URL: Homepage, https://github.com/raccoonaihq/raccoonai-python
6
6
  Project-URL: Repository, https://github.com/raccoonaihq/raccoonai-python
@@ -162,7 +162,6 @@ response = client.lam.run(
162
162
  raccoon_passcode="<end-user-raccoon-passcode>",
163
163
  advanced={
164
164
  "block_ads": True,
165
- "extension_ids": ["df2399ea-a938-438f-9d4b-ef3bc95cf8af"],
166
165
  "proxy": {
167
166
  "city": "sanfrancisco",
168
167
  "country": "us",
@@ -177,7 +176,7 @@ print(response.advanced)
177
176
 
178
177
  ## File uploads
179
178
 
180
- Request parameters that correspond to file uploads can be passed as `bytes`, a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
179
+ Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.
181
180
 
182
181
  ```python
183
182
  from pathlib import Path
@@ -1,53 +1,54 @@
1
- raccoonai/__init__.py,sha256=ut5jCAExi9IzT9pzrjpsJoVhn6bzWI6jIXNXB-fXBY4,2523
2
- raccoonai/_base_client.py,sha256=JVsNh33YxdFcdvPaIoCuOZGE_lx_3U7_OtuaO9doXec,64960
3
- raccoonai/_client.py,sha256=-QSzuORMlEWUeMf2Jc20frkx0KncFT66C-aQ5qXGFFw,18899
1
+ raccoonai/__init__.py,sha256=-A6AJxDjviQFqkzoBiO5BzSEe_LEMi5pQ861niFmLtk,2634
2
+ raccoonai/_base_client.py,sha256=R9UA9AEmUXbU3sPAQ8759ehYh9UAW640OGZ356drsTA,65887
3
+ raccoonai/_client.py,sha256=b4Du_3dCdsg2TTDuMwokhvEDTrn5CWy5bqcsubr2ZaY,18886
4
4
  raccoonai/_compat.py,sha256=VWemUKbj6DDkQ-O4baSpHVLJafotzeXmCQGJugfVTIw,6580
5
5
  raccoonai/_constants.py,sha256=FkmVVcfVS3gR69v_fTrqA_qjakyxJHOWJcw3jpEck8Y,465
6
6
  raccoonai/_exceptions.py,sha256=Y-DcD2M8xkSw8IEkk4KHj73O8GQxCtWm4HWYQ02j7z8,3226
7
7
  raccoonai/_files.py,sha256=a0SHeBu6FT5rt_CKotWZyna5GpgB42go35AUK5sEiD4,3624
8
- raccoonai/_models.py,sha256=Bg-k8-T1kDWURAYXrbDF5FSAyLEy7k90Jrvne-dF4Wc,29070
8
+ raccoonai/_models.py,sha256=G1vczEodX0vUySeVKbF-mbzlaObNL1oVAYH4c65agRk,29131
9
9
  raccoonai/_qs.py,sha256=AOkSz4rHtK4YI3ZU_kzea-zpwBUgEY8WniGmTPyEimc,4846
10
10
  raccoonai/_resource.py,sha256=zfxyYCvzutc1dvCP-j9UPc1sn9U8F-X9gGyqleOvCxY,1118
11
- raccoonai/_response.py,sha256=q3bfYfS84vvIRPz_wL8djh6ir9UHGDzzF2l3gKDOWX8,28807
11
+ raccoonai/_response.py,sha256=RuSNonzoPj-1q1FxDHtgUIMLvTqKLTg8GtTxrNV3XzY,28806
12
12
  raccoonai/_streaming.py,sha256=zHnkREZO5v33YJ7P0YZ7KhJET4ZzevGw1JzRY2-Mls4,10112
13
- raccoonai/_types.py,sha256=sN2zE-vBl9KBlBKL8fkN2DNZnItdjDl-3fTpP9cg69w,6146
14
- raccoonai/_version.py,sha256=ki3TqQ1xyy7C9RbybZmYkkGAOEf1BYZW-zXB4hLkVec,170
13
+ raccoonai/_types.py,sha256=nkB-Qzpl6R51fi6nwZsLH73N43GgXxZqG3KJ51pm8-o,6200
14
+ raccoonai/_version.py,sha256=pjqr1cd84GFAJEhrOZvHafZ9dAJuD3dgemPBXa1ZGj4,170
15
15
  raccoonai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  raccoonai/_utils/__init__.py,sha256=PNZ_QJuzZEgyYXqkO1HVhGkj5IU9bglVUcw7H-Knjzw,2062
17
17
  raccoonai/_utils/_logs.py,sha256=Af3FKkE-LAPzYTl8bnFD4yPvPBIO-QyCra-r9_dSmOM,784
18
- raccoonai/_utils/_proxy.py,sha256=z3zsateHtb0EARTWKk8QZNHfPkqJbqwd1lM993LBwGE,1902
18
+ raccoonai/_utils/_proxy.py,sha256=aglnj2yBTDyGX9Akk2crZHrl10oqRmceUy2Zp008XEs,1975
19
19
  raccoonai/_utils/_reflection.py,sha256=ZmGkIgT_PuwedyNBrrKGbxoWtkpytJNU1uU4QHnmEMU,1364
20
+ raccoonai/_utils/_resources_proxy.py,sha256=rlNyHdV3OTAHOl9OHEyoMVhEN_mlzxq-Wb9Hz_P-Hxo,604
20
21
  raccoonai/_utils/_streams.py,sha256=SMC90diFFecpEg_zgDRVbdR3hSEIgVVij4taD-noMLM,289
21
22
  raccoonai/_utils/_sync.py,sha256=TpGLrrhRNWTJtODNE6Fup3_k7zrWm1j2RlirzBwre-0,2862
22
- raccoonai/_utils/_transform.py,sha256=asrbdx4Pf5NupzaB8QdEjypW_DgHjjkpswHT0Jum4S0,13987
23
- raccoonai/_utils/_typing.py,sha256=nTJz0jcrQbEgxwy4TtAkNxuU0QHHlmc6mQtA6vIR8tg,4501
24
- raccoonai/_utils/_utils.py,sha256=8UmbPOy_AAr2uUjjFui-VZSrVBHRj6bfNEKRp5YZP2A,12004
23
+ raccoonai/_utils/_transform.py,sha256=n7kskEWz6o__aoNvhFoGVyDoalNe6mJwp-g7BWkdj88,15617
24
+ raccoonai/_utils/_typing.py,sha256=D0DbbNu8GnYQTSICnTSHDGsYXj8TcAKyhejb0XcnjtY,4602
25
+ raccoonai/_utils/_utils.py,sha256=ts4CiiuNpFiGB6YMdkQRh2SZvYvsl7mAF-JWHCcLDf4,12312
25
26
  raccoonai/lib/.keep,sha256=wuNrz-5SXo3jJaJOJgz4vFHM41YH_g20F5cRQo0vLes,224
26
27
  raccoonai/resources/__init__.py,sha256=J3rNFGIi-0n5C4uqUHDax-dZCtNhFxnz1_LiF1Hm498,1374
27
28
  raccoonai/resources/fleet/__init__.py,sha256=vGB3Zi0TL72b8i88mnBm-evtTa2DMGqZAQhdfMis6tQ,1517
28
- raccoonai/resources/fleet/extensions.py,sha256=lFILcLXF-9MtJfwvIN4o7LxcRCJfwR5exQuJZGHXx6Q,15318
29
+ raccoonai/resources/fleet/extensions.py,sha256=xHaXfCLLki5dSHJNoZG0834X_efayg5uJBXDGw2Io6c,15297
29
30
  raccoonai/resources/fleet/fleet.py,sha256=q8Ola3g7CQOMO0XQ9CDsQ0iG3n7FEnUe_4VJLGGlGfw,4818
30
- raccoonai/resources/fleet/sessions.py,sha256=0sRBZIyRzpaEpR8P8pnylTw5QDp2dJrrGLVZlkkwuPs,28540
31
+ raccoonai/resources/fleet/sessions.py,sha256=d-EmJr0PnmaxGuM2b7W7CVPWIDPj7LAxXCJGLMWq6vY,28527
31
32
  raccoonai/resources/lam/__init__.py,sha256=Thj6eBm5r07sqkqyE9K1JGjNKyzgaodJLy-qNrfrCWc,950
32
- raccoonai/resources/lam/lam.py,sha256=dkimES5beXY5eRXjrg62eAJxXw6kEIPoSweSBkRmAmU,22327
33
- raccoonai/resources/lam/tasks.py,sha256=e9YbmtwNx9tkVTP-F6RfL1uCDr95RymGIziC7vzn2dE,12542
33
+ raccoonai/resources/lam/lam.py,sha256=9QYNhhYDX1wUn6DsRPgjqhx-ikpfhy_uGlqQGbAoeHM,22438
34
+ raccoonai/resources/lam/tasks.py,sha256=K71XB-13oyb9_6QODgGFDf1BmWtgUZR6DZrz1CdcS2w,12529
34
35
  raccoonai/resources/tail/__init__.py,sha256=1iOxKP4PRjPGjU1ss2L_8YbwPZ_MIA5cnyFbyELeRoA,1387
35
- raccoonai/resources/tail/apps.py,sha256=532sI0g2sLUrLV3z_8qfbW8qnTTc8HyyQax1PD52BrA,8008
36
+ raccoonai/resources/tail/apps.py,sha256=SqxIPZ6M-f9pZl0bJezFi2HhqecmZ14NIfti94OqkPM,7995
36
37
  raccoonai/resources/tail/tail.py,sha256=L3HtDA-G4GSGdD5YjWp5IcjuYGINRFdua0-YKHrAavA,4517
37
- raccoonai/resources/tail/users.py,sha256=Y-_NjYurHFM7fTJjPeZ2yyL0n3VO_a1CZP1SM6u_9FU,14503
38
+ raccoonai/resources/tail/users.py,sha256=zlnmF5ycgv47dA3Zwj7ryADicsPw5pu3666kzmN7UgE,14490
38
39
  raccoonai/types/__init__.py,sha256=zPr9s--p1dwMuN9TZf38xnrr_T0G8FA2LLIPUazW4FA,243
39
40
  raccoonai/types/lam_run_params.py,sha256=WEz4-fSyhk72lke57m68n0ATFeiHwpOsaWvnguoz6yM,2733
40
41
  raccoonai/types/lam_run_response.py,sha256=pOBB0xmGZou7vMG-dmhUk6v5pMyJF4dXWnNWXAHvfW0,891
41
42
  raccoonai/types/fleet/__init__.py,sha256=4z1oeJkLJ-abdHCDxQ0lO9zOkpJXtSaR5qgVeVsaHLE,1101
42
43
  raccoonai/types/fleet/extension_all_response.py,sha256=J9Y5qq3Eukik_0Bmyq75kLEhJJohJOF_Hx8vWUv_Sq8,527
43
- raccoonai/types/fleet/extension_get_response.py,sha256=Z0JcFPJhu22Hw0w-qRh1cGRqMlIaIMu1JM1_Z6eUPbE,398
44
+ raccoonai/types/fleet/extension_get_response.py,sha256=MXYmru1ocw_-VtUQHGKYU5wOJ6QST5NzXfwPxl4wb7w,397
44
45
  raccoonai/types/fleet/extension_upload_params.py,sha256=UUR2H0DrvNgpLJfCTyO28Gv5xI8EEOEFErwmj3Ru5z0,328
45
- raccoonai/types/fleet/extension_upload_response.py,sha256=0ZETPTZa9h7T--ShFskafm_1bDuik_8xt1Z29BuSN-s,404
46
+ raccoonai/types/fleet/extension_upload_response.py,sha256=IDWmw40WxBfK8aZe2SgtZY4oEi-N1kSV7ZpjvCtdg24,403
46
47
  raccoonai/types/fleet/session_all_params.py,sha256=8PmXYnnvdc52Hw4q4d0bzWMeeq_7m5LraRghHwI_wl0,1432
47
48
  raccoonai/types/fleet/session_all_response.py,sha256=Z4_iJCGAtfFpYZTiBmYAZJaPzyVUfS1Qkwe5nEeuPcY,1721
48
49
  raccoonai/types/fleet/session_create_params.py,sha256=1DK11wJV9XqXRRIHPuHMpusxQeg3ueM1a5NcAaQOoZA,2567
49
50
  raccoonai/types/fleet/session_create_response.py,sha256=WbVwyfesj9QWuYEhDPoNji7U5eJmEOA44NmImWCl4qk,602
50
- raccoonai/types/fleet/session_logs_response.py,sha256=rHcBPnymndXeBYADOumMsdR6pKe_z0Cpt-x-dIUcjew,365
51
+ raccoonai/types/fleet/session_logs_response.py,sha256=-Qzhml3YEMUFMbsTlFX8OqA0qPOX040CO3U4LaQlweU,364
51
52
  raccoonai/types/fleet/session_media_response.py,sha256=FsE4vgxweb0y25J5YYa_fHbVy8IaQfstEZ90QIxVx3c,1118
52
53
  raccoonai/types/fleet/session_status_response.py,sha256=bmmZk4f6aV3lS3ENILoLQm38dKVkVY4uN-H-OTUrxgM,432
53
54
  raccoonai/types/fleet/session_terminate_response.py,sha256=UbA_9CwZOmRMcxqaNMIFNGA8pwpAY1fagb_2voYBQ0c,438
@@ -62,10 +63,10 @@ raccoonai/types/tail/app_linked_response.py,sha256=i7ox4Z5UsJhQMQm8DkB9YTz9chqNs
62
63
  raccoonai/types/tail/user_all_params.py,sha256=SeS6QCT2HYtQnUFaptIcy2Fla01CQq0deno72yb8TS8,832
63
64
  raccoonai/types/tail/user_all_response.py,sha256=J13hVLXOWD_S5AWs--i4fR73FUuiJ8cZQ9UoBIkPVRo,1227
64
65
  raccoonai/types/tail/user_create_params.py,sha256=4Pe2d2L_TqNAeBNtG92ml1zLA3wTt_NE_6zJ-2YDtFY,370
65
- raccoonai/types/tail/user_create_response.py,sha256=wGZuNVLZpm8ph60zD1aJHP1kPs9CCn2O7ZsyqEHRGgM,518
66
+ raccoonai/types/tail/user_create_response.py,sha256=eYexuFeSkGZs58pqSLga-9D4zAwCEiX7xi6OllB3F2Q,517
66
67
  raccoonai/types/tail/user_status_params.py,sha256=gxSN0_zGeqOSKpDaoKh0O6l8j0jMyxP7f7ONIPWOVZE,459
67
68
  raccoonai/types/tail/user_status_response.py,sha256=BakDkr-yhueamBAx-wrHCUZ4h9rYJCQPnDD49paA_aU,472
68
- raccoonai-0.1.0a16.dist-info/METADATA,sha256=zoikaeViUnBZZzBBijnofEkZ9Rcb9rFOhIkq44viZmw,15525
69
- raccoonai-0.1.0a16.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
70
- raccoonai-0.1.0a16.dist-info/licenses/LICENSE,sha256=enGvZ2fGU7wGgMPWkgyWhnsFhCpxwdeG_selO_ovoTM,11340
71
- raccoonai-0.1.0a16.dist-info/RECORD,,
69
+ raccoonai-0.1.0a18.dist-info/METADATA,sha256=Vo2rhDy5UXTSIh1O7Lk1vFG-XssKltyrMsHsW8koh2c,15461
70
+ raccoonai-0.1.0a18.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
71
+ raccoonai-0.1.0a18.dist-info/licenses/LICENSE,sha256=enGvZ2fGU7wGgMPWkgyWhnsFhCpxwdeG_selO_ovoTM,11340
72
+ raccoonai-0.1.0a18.dist-info/RECORD,,