unique_sdk 0.9.7__tar.gz → 0.9.9__tar.gz
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.
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/CHANGELOG.md +6 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/PKG-INFO +9 -3
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/pyproject.toml +4 -2
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_api_resource.py +13 -1
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_util.py +65 -4
- unique_sdk-0.9.9/unique_sdk/_version.py +1 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_message.py +15 -0
- unique_sdk-0.9.7/unique_sdk/_version.py +0 -1
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/LICENSE +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/README.md +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/__init__.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_api_requestor.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_api_version.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_error.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_http_client.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_list_object.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_object_classes.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_request_options.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_unique_object.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_unique_ql.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_unique_response.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/_webhook.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/__init__.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_acronyms.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_chat_completion.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_content.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_embedding.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_event.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_integrated.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_search.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_search_string.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/api_resources/_short_term_memory.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/utils/chat_history.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/utils/file_io.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/utils/sources.py +0 -0
- {unique_sdk-0.9.7 → unique_sdk-0.9.9}/unique_sdk/utils/token.py +0 -0
|
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.9.9] - 2024-10-23
|
|
9
|
+
- Revert deletion of `Message.retrieve` method
|
|
10
|
+
|
|
11
|
+
## [0.9.8] - 2024-10-16
|
|
12
|
+
- Add `retries` for `_static_request` and `_static_request_async` in `APIResource` - When the error messages contains either `"problem proxying the request"`,
|
|
13
|
+
or `"Upstream service reached a hard timeout"`,
|
|
8
14
|
## [0.9.7] - 2024-09-23
|
|
9
15
|
- Add `completedAt` to `CreateParams` of `Message`
|
|
10
16
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: unique_sdk
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.9
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
|
-
Author:
|
|
7
|
-
Author-email:
|
|
6
|
+
Author: Martin Fadler
|
|
7
|
+
Author-email: martin.fadler@unique.ch
|
|
8
8
|
Requires-Python: >=3.11,<4.0
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -894,6 +894,12 @@ All notable changes to this project will be documented in this file.
|
|
|
894
894
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
895
895
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
896
896
|
|
|
897
|
+
## [0.9.9] - 2024-10-23
|
|
898
|
+
- Revert deletion of `Message.retrieve` method
|
|
899
|
+
|
|
900
|
+
## [0.9.8] - 2024-10-16
|
|
901
|
+
- Add `retries` for `_static_request` and `_static_request_async` in `APIResource` - When the error messages contains either `"problem proxying the request"`,
|
|
902
|
+
or `"Upstream service reached a hard timeout"`,
|
|
897
903
|
## [0.9.7] - 2024-09-23
|
|
898
904
|
- Add `completedAt` to `CreateParams` of `Message`
|
|
899
905
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "unique_sdk"
|
|
3
|
-
version = "0.9.
|
|
3
|
+
version = "0.9.9"
|
|
4
4
|
description = ""
|
|
5
5
|
authors = [
|
|
6
|
+
"Martin Fadler <martin.fadler@unique.ch>",
|
|
6
7
|
"Konstantin Krauss <konstantin@unique.ch>",
|
|
7
8
|
"Andreas Hauri <andreas@unique.ch>",
|
|
8
9
|
]
|
|
@@ -16,10 +17,11 @@ typing-extensions = "^4.9.0"
|
|
|
16
17
|
|
|
17
18
|
[tool.poetry.group.dev.dependencies]
|
|
18
19
|
ruff = "0.4.10"
|
|
19
|
-
pytest = "^
|
|
20
|
+
pytest = "^8.0"
|
|
20
21
|
tox = "^4.11.4"
|
|
21
22
|
pyright = "^1.1.341"
|
|
22
23
|
pytest-cov = "^4.1.0"
|
|
24
|
+
pytest-asyncio = "^0.24.0"
|
|
23
25
|
|
|
24
26
|
[build-system]
|
|
25
27
|
requires = ["poetry-core"]
|
|
@@ -14,10 +14,20 @@ from urllib.parse import quote_plus
|
|
|
14
14
|
from unique_sdk._api_requestor import APIRequestor
|
|
15
15
|
from unique_sdk._error import InvalidRequestError
|
|
16
16
|
from unique_sdk._unique_object import UniqueObject
|
|
17
|
-
from unique_sdk._util import convert_to_unique_object
|
|
17
|
+
from unique_sdk._util import convert_to_unique_object, retry_on_error
|
|
18
18
|
|
|
19
19
|
T = TypeVar("T", bound=UniqueObject)
|
|
20
20
|
|
|
21
|
+
retry_dict = {
|
|
22
|
+
"error_messages": [
|
|
23
|
+
"problem proxying the request",
|
|
24
|
+
"Upstream service reached a hard timeout",
|
|
25
|
+
],
|
|
26
|
+
"max_retries": 3,
|
|
27
|
+
"backoff_factor": 2,
|
|
28
|
+
"initial_delay": 1,
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
|
|
22
32
|
class APIResource(UniqueObject, Generic[T]):
|
|
23
33
|
OBJECT_NAME: ClassVar[str]
|
|
@@ -164,6 +174,7 @@ class APIResource(UniqueObject, Generic[T]):
|
|
|
164
174
|
# The `method_` and `url_` arguments are suffixed with an underscore to
|
|
165
175
|
# avoid conflicting with actual request parameters in `params`.
|
|
166
176
|
@classmethod
|
|
177
|
+
@retry_on_error(**retry_dict)
|
|
167
178
|
def _static_request(
|
|
168
179
|
cls,
|
|
169
180
|
method_,
|
|
@@ -182,6 +193,7 @@ class APIResource(UniqueObject, Generic[T]):
|
|
|
182
193
|
# The `method_` and `url_` arguments are suffixed with an underscore to
|
|
183
194
|
# avoid conflicting with actual request parameters in `params`.
|
|
184
195
|
@classmethod
|
|
196
|
+
@retry_on_error(**retry_dict)
|
|
185
197
|
async def _static_request_async(
|
|
186
198
|
cls,
|
|
187
199
|
method_,
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import functools
|
|
2
3
|
import logging
|
|
3
4
|
import os
|
|
5
|
+
import random
|
|
4
6
|
import re
|
|
5
7
|
import sys
|
|
6
|
-
|
|
8
|
+
import time
|
|
9
|
+
from functools import wraps
|
|
10
|
+
from typing import Any, Callable, Dict, List, Optional, TypeVar, Union, cast, overload
|
|
7
11
|
|
|
8
12
|
from typing_extensions import TYPE_CHECKING, Type
|
|
9
13
|
|
|
10
14
|
import unique_sdk # noqa: F401
|
|
15
|
+
from unique_sdk._error import APIError
|
|
11
16
|
|
|
12
17
|
if TYPE_CHECKING:
|
|
13
18
|
from unique_sdk._unique_object import UniqueObject
|
|
@@ -21,10 +26,9 @@ logger: logging.Logger = logging.getLogger("unique")
|
|
|
21
26
|
def _console_log_level():
|
|
22
27
|
if unique_sdk.log in ["debug", "info"]:
|
|
23
28
|
return unique_sdk.log
|
|
24
|
-
|
|
29
|
+
if UNIQUE_LOG in ["debug", "info"]:
|
|
25
30
|
return UNIQUE_LOG
|
|
26
|
-
|
|
27
|
-
return None
|
|
31
|
+
return None
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
def log_debug(message, **params):
|
|
@@ -188,3 +192,60 @@ class class_method_variant(object):
|
|
|
188
192
|
return class_method(*args, **kwargs)
|
|
189
193
|
|
|
190
194
|
return _wrapper
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def retry_on_error(
|
|
198
|
+
error_messages: List[str],
|
|
199
|
+
max_retries: int = 3,
|
|
200
|
+
initial_delay: int = 1,
|
|
201
|
+
backoff_factor: int = 2,
|
|
202
|
+
error_class=APIError,
|
|
203
|
+
):
|
|
204
|
+
def decorator(func: Callable) -> Callable:
|
|
205
|
+
@wraps(func)
|
|
206
|
+
async def async_wrapper(*args, **kwargs) -> Any:
|
|
207
|
+
attempts = 0
|
|
208
|
+
while attempts < max_retries:
|
|
209
|
+
try:
|
|
210
|
+
return await func(*args, **kwargs)
|
|
211
|
+
except Exception as e:
|
|
212
|
+
if not any(
|
|
213
|
+
err_msg.lower() in str(e).lower() for err_msg in error_messages
|
|
214
|
+
):
|
|
215
|
+
raise e # Raise the error if none of the messages match
|
|
216
|
+
|
|
217
|
+
attempts += 1
|
|
218
|
+
if attempts >= max_retries:
|
|
219
|
+
raise error_class(f"Failed after {max_retries} attempts: {e}")
|
|
220
|
+
|
|
221
|
+
# Calculate exponential backoff with some randomness (jitter)
|
|
222
|
+
delay = initial_delay * (backoff_factor ** (attempts - 1))
|
|
223
|
+
jitter = random.uniform(0, 0.1 * delay)
|
|
224
|
+
await asyncio.sleep(delay + jitter)
|
|
225
|
+
|
|
226
|
+
def sync_wrapper(*args, **kwargs) -> Any:
|
|
227
|
+
attempts = 0
|
|
228
|
+
while attempts < max_retries:
|
|
229
|
+
try:
|
|
230
|
+
return func(*args, **kwargs)
|
|
231
|
+
except Exception as e:
|
|
232
|
+
if not any(
|
|
233
|
+
err_msg.lower() in str(e).lower() for err_msg in error_messages
|
|
234
|
+
):
|
|
235
|
+
raise e # Raise the error if none of the messages match
|
|
236
|
+
|
|
237
|
+
attempts += 1
|
|
238
|
+
if attempts >= max_retries:
|
|
239
|
+
raise error_class(f"Failed after {max_retries} attempts: {e}")
|
|
240
|
+
|
|
241
|
+
# Calculate exponential backoff with some randomness (jitter)
|
|
242
|
+
delay = initial_delay * (backoff_factor ** (attempts - 1))
|
|
243
|
+
jitter = random.uniform(0, 0.1 * delay)
|
|
244
|
+
time.sleep(delay + jitter)
|
|
245
|
+
|
|
246
|
+
# Return the appropriate wrapper based on whether the function is async
|
|
247
|
+
if asyncio.iscoroutinefunction(func):
|
|
248
|
+
return async_wrapper
|
|
249
|
+
return sync_wrapper
|
|
250
|
+
|
|
251
|
+
return decorator
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.9.8"
|
|
@@ -115,6 +115,21 @@ class Message(APIResource["Message"]):
|
|
|
115
115
|
|
|
116
116
|
return result
|
|
117
117
|
|
|
118
|
+
@classmethod
|
|
119
|
+
def retrieve(
|
|
120
|
+
cls,
|
|
121
|
+
user_id: str,
|
|
122
|
+
company_id: str,
|
|
123
|
+
id: str,
|
|
124
|
+
**params: Unpack["Message.RetrieveParams"],
|
|
125
|
+
) -> "Message":
|
|
126
|
+
"""
|
|
127
|
+
Retrieves a Message object.
|
|
128
|
+
"""
|
|
129
|
+
instance = cls(user_id, company_id, id, **params)
|
|
130
|
+
instance.refresh(user_id, company_id)
|
|
131
|
+
return instance
|
|
132
|
+
|
|
118
133
|
@classmethod
|
|
119
134
|
async def retrieve_async(
|
|
120
135
|
cls,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.9.7"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|