nlbone 0.7.20__py3-none-any.whl → 0.7.22__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.
- nlbone/adapters/auth/token_provider.py +2 -2
- nlbone/interfaces/api/exceptions.py +8 -0
- nlbone/interfaces/api/schema/base_response_model.py +7 -0
- nlbone/utils/cache.py +55 -47
- {nlbone-0.7.20.dist-info → nlbone-0.7.22.dist-info}/METADATA +1 -1
- {nlbone-0.7.20.dist-info → nlbone-0.7.22.dist-info}/RECORD +9 -9
- {nlbone-0.7.20.dist-info → nlbone-0.7.22.dist-info}/WHEEL +1 -1
- {nlbone-0.7.20.dist-info → nlbone-0.7.22.dist-info}/entry_points.txt +0 -0
- {nlbone-0.7.20.dist-info → nlbone-0.7.22.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,13 +2,13 @@ import threading
|
|
|
2
2
|
import time
|
|
3
3
|
from typing import Any, Dict, Optional
|
|
4
4
|
|
|
5
|
-
from nlbone.
|
|
5
|
+
from nlbone.core.ports.auth import AuthService as BaseAuthService
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ClientTokenProvider:
|
|
9
9
|
"""Caches Keycloak client-credentials token and refreshes before expiry."""
|
|
10
10
|
|
|
11
|
-
def __init__(self, auth:
|
|
11
|
+
def __init__(self, auth: BaseAuthService, *, skew_seconds: int = 30) -> None:
|
|
12
12
|
self._auth = auth
|
|
13
13
|
self._skew = skew_seconds
|
|
14
14
|
self._lock = threading.Lock()
|
|
@@ -86,3 +86,11 @@ class UnprocessableEntityException(BaseHttpException):
|
|
|
86
86
|
class LogicalValidationException(UnprocessableEntityException):
|
|
87
87
|
def __init__(self, detail: str, loc: Iterable[Any] | None = None, type_: str = "logical_error"):
|
|
88
88
|
super().__init__(detail=detail, loc=loc, type_=type_)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class GoneException(BaseHttpException):
|
|
92
|
+
def __init__(self, detail: str = "Gone"):
|
|
93
|
+
super().__init__(
|
|
94
|
+
status_code=status.HTTP_410_GONE,
|
|
95
|
+
detail=detail,
|
|
96
|
+
)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
from typing import Any
|
|
1
2
|
from pydantic import BaseModel, ConfigDict, model_serializer
|
|
2
3
|
|
|
3
4
|
from nlbone.core.domain.base import BaseId
|
|
4
5
|
|
|
5
6
|
EXCLUDE_NONE = "exclude_none"
|
|
6
7
|
|
|
8
|
+
def convert_decimal_to_string(v: Any) -> Any:
|
|
9
|
+
"""Converts a value to string if it's a large integer (over the safe limit)."""
|
|
10
|
+
if isinstance(v, int) and v > 9007199254740991:
|
|
11
|
+
return str(v)
|
|
12
|
+
return v
|
|
7
13
|
|
|
8
14
|
class BaseResponseModel(BaseModel):
|
|
9
15
|
model_config = ConfigDict(
|
|
@@ -11,6 +17,7 @@ class BaseResponseModel(BaseModel):
|
|
|
11
17
|
arbitrary_types_allowed=True,
|
|
12
18
|
json_encoders={
|
|
13
19
|
BaseId: lambda v: str(v.value),
|
|
20
|
+
int: convert_decimal_to_string,
|
|
14
21
|
},
|
|
15
22
|
)
|
|
16
23
|
|
nlbone/utils/cache.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import hashlib
|
|
2
3
|
import inspect
|
|
3
4
|
import json
|
|
4
|
-
from typing import Any, Callable, Iterable, Optional
|
|
5
|
-
import hashlib
|
|
6
|
-
from makefun import wraps as mf_wraps
|
|
5
|
+
from typing import Any, Callable, Iterable, Optional
|
|
7
6
|
|
|
7
|
+
from makefun import wraps as mf_wraps
|
|
8
8
|
|
|
9
9
|
from nlbone.utils.cache_registry import get_cache
|
|
10
10
|
|
|
@@ -61,10 +61,10 @@ def to_jsonable(obj):
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _key_from_template(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
tpl: Optional[str],
|
|
65
|
+
func: Callable,
|
|
66
|
+
args,
|
|
67
|
+
kwargs,
|
|
68
68
|
) -> str:
|
|
69
69
|
"""Format key template with bound arguments or build a stable default."""
|
|
70
70
|
bound = _bind(func, args, kwargs)
|
|
@@ -84,10 +84,10 @@ def _key_from_template(
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
def _format_tags(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
tag_tpls: Optional[Iterable[str]],
|
|
88
|
+
func: Callable,
|
|
89
|
+
args,
|
|
90
|
+
kwargs,
|
|
91
91
|
) -> list[str] | None:
|
|
92
92
|
if not tag_tpls:
|
|
93
93
|
return None
|
|
@@ -126,21 +126,14 @@ def _run_maybe_async(func: Callable, *args, **kwargs):
|
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
def cached(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
129
|
+
*,
|
|
130
|
+
ttl: int,
|
|
131
|
+
key: str | None = None,
|
|
132
|
+
tags: Iterable[str] | None = None,
|
|
133
|
+
serializer: Callable[[Any], bytes] = default_serialize,
|
|
134
|
+
deserializer: Callable[[bytes], Any] = default_deserialize,
|
|
135
|
+
cache_resolver: Optional[Callable[[], Any]] = None,
|
|
136
136
|
):
|
|
137
|
-
"""
|
|
138
|
-
Framework-agnostic caching for SYNC or ASYNC callables.
|
|
139
|
-
- Preserves function signature (good for FastAPI/OpenAPI).
|
|
140
|
-
- Works with sync/async cache backends (CachePort / AsyncCachePort).
|
|
141
|
-
- `key` & `tags` are string templates, e.g. "file:{file_id}".
|
|
142
|
-
"""
|
|
143
|
-
|
|
144
137
|
def deco(func: Callable):
|
|
145
138
|
is_async_func = asyncio.iscoroutinefunction(func)
|
|
146
139
|
|
|
@@ -154,24 +147,31 @@ def cached(
|
|
|
154
147
|
k = _key_from_template(key, func, args, kwargs)
|
|
155
148
|
tg = _format_tags(tags, func, args, kwargs)
|
|
156
149
|
|
|
157
|
-
# GET
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
150
|
+
# SAFE GET
|
|
151
|
+
cached_bytes = None
|
|
152
|
+
try:
|
|
153
|
+
if _is_async_method(cache, "get"):
|
|
154
|
+
cached_bytes = await cache.get(k)
|
|
155
|
+
else:
|
|
156
|
+
cached_bytes = cache.get(k)
|
|
157
|
+
except Exception:
|
|
158
|
+
pass
|
|
162
159
|
|
|
163
160
|
if cached_bytes is not None:
|
|
164
161
|
return deserializer(cached_bytes)
|
|
165
162
|
|
|
166
|
-
# MISS
|
|
163
|
+
# MISS → compute
|
|
167
164
|
result = await func(*args, **kwargs)
|
|
168
165
|
|
|
169
|
-
# SET
|
|
166
|
+
# SAFE SET
|
|
170
167
|
data = serializer(result)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
168
|
+
try:
|
|
169
|
+
if _is_async_method(cache, "set"):
|
|
170
|
+
await cache.set(k, data, ttl=ttl, tags=tg)
|
|
171
|
+
else:
|
|
172
|
+
cache.set(k, data, ttl=ttl, tags=tg)
|
|
173
|
+
except Exception:
|
|
174
|
+
pass
|
|
175
175
|
|
|
176
176
|
return result
|
|
177
177
|
|
|
@@ -183,27 +183,35 @@ def cached(
|
|
|
183
183
|
cache = (cache_resolver or get_cache)()
|
|
184
184
|
if not cache:
|
|
185
185
|
return func(*args, **kwargs)
|
|
186
|
+
|
|
186
187
|
k = _key_from_template(key, func, args, kwargs)
|
|
187
188
|
tg = _format_tags(tags, func, args, kwargs)
|
|
188
189
|
|
|
189
|
-
# GET (
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
190
|
+
# SAFE GET (maybe async)
|
|
191
|
+
cached_bytes = None
|
|
192
|
+
try:
|
|
193
|
+
if _is_async_method(cache, "get"):
|
|
194
|
+
cached_bytes = _run_maybe_async(cache.get, k)
|
|
195
|
+
else:
|
|
196
|
+
cached_bytes = cache.get(k)
|
|
197
|
+
except Exception:
|
|
198
|
+
pass
|
|
194
199
|
|
|
195
200
|
if cached_bytes is not None:
|
|
196
201
|
return deserializer(cached_bytes)
|
|
197
202
|
|
|
198
|
-
# MISS
|
|
203
|
+
# MISS → compute
|
|
199
204
|
result = func(*args, **kwargs)
|
|
200
205
|
|
|
201
|
-
# SET (
|
|
206
|
+
# SAFE SET (maybe async)
|
|
202
207
|
data = serializer(result)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
208
|
+
try:
|
|
209
|
+
if _is_async_method(cache, "set"):
|
|
210
|
+
_run_maybe_async(cache.set, k, data, ttl=ttl, tags=tg)
|
|
211
|
+
else:
|
|
212
|
+
cache.set(k, data, ttl=ttl, tags=tg)
|
|
213
|
+
except Exception:
|
|
214
|
+
pass
|
|
207
215
|
|
|
208
216
|
return result
|
|
209
217
|
|
|
@@ -6,7 +6,7 @@ nlbone/adapters/snowflake.py,sha256=lmq7vi6HdX9hEuTW6BlTEAy91wmrA4Bx3tvGoagHTW4,
|
|
|
6
6
|
nlbone/adapters/auth/__init__.py,sha256=hkDHvsFhw_UiOHG9ZSMqjiAhK4wumEforitveSZswVw,42
|
|
7
7
|
nlbone/adapters/auth/auth_service.py,sha256=p1Yax036xd7uoppptaoDd4m2qPvKJtqrrP5PYwFZ7OY,2108
|
|
8
8
|
nlbone/adapters/auth/keycloak.py,sha256=IhEriaFl5mjIGT6ZUCU9qROd678ARchvWgd4UJ6zH7s,4925
|
|
9
|
-
nlbone/adapters/auth/token_provider.py,sha256=
|
|
9
|
+
nlbone/adapters/auth/token_provider.py,sha256=kzjFAaFY8SPnU0Tn6l-YVrhEOAiFV0QE3eit3D7u2VQ,1438
|
|
10
10
|
nlbone/adapters/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
nlbone/adapters/cache/async_redis.py,sha256=vvu5w4ANx0BVRHL95RAMGsD8CcaC-tSBMbCius2cuNc,6212
|
|
12
12
|
nlbone/adapters/cache/memory.py,sha256=y8M4erHQXApiSMAqG6Qk4pxEb60hRdu1szPv6iqvO9c,3738
|
|
@@ -66,7 +66,7 @@ nlbone/core/ports/uow.py,sha256=VhqSc-Ryt9m-rlNMiXTzD3dPGz6mM_JxND8D0UJGRu4,962
|
|
|
66
66
|
nlbone/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
nlbone/interfaces/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
68
|
nlbone/interfaces/api/exception_handlers.py,sha256=vxNEBgAaQygLgAz1UNt3wHj0SdCJOwtLOv_BwTfir3o,4050
|
|
69
|
-
nlbone/interfaces/api/exceptions.py,sha256=
|
|
69
|
+
nlbone/interfaces/api/exceptions.py,sha256=jshNmu6tqPEjUelTdHKByI3n5CX5jDErB8fEwn3X1oo,2696
|
|
70
70
|
nlbone/interfaces/api/routers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
71
|
nlbone/interfaces/api/schemas.py,sha256=NIEKeTdJtwwIkIxL7WURNZF8g34I4TlRAqs-x1Uq7YI,108
|
|
72
72
|
nlbone/interfaces/api/additional_filed/__init__.py,sha256=BWemliLSQV9iq1vdUaF733q0FOSipSWBOQk9eYj732Q,318
|
|
@@ -89,7 +89,7 @@ nlbone/interfaces/api/pagination/__init__.py,sha256=pA1uC4rK6eqDI5IkLVxmgO2B6lEx
|
|
|
89
89
|
nlbone/interfaces/api/pagination/offset_base.py,sha256=AwuHLQELAKut58fQSL2hk-QhfwsG1coJWz-Jkh2gnmg,4113
|
|
90
90
|
nlbone/interfaces/api/schema/__init__.py,sha256=LAqgynfupeqOQ6u0I5ucrcYnojRMZUg9yW8IjKSQTNI,119
|
|
91
91
|
nlbone/interfaces/api/schema/adaptive_schema.py,sha256=bdWBNpP2NfOJ_in4btXn0lrZOK70x-OqfmZ-NpIJdoQ,3347
|
|
92
|
-
nlbone/interfaces/api/schema/base_response_model.py,sha256=
|
|
92
|
+
nlbone/interfaces/api/schema/base_response_model.py,sha256=8cs06qpgYfkzimjctjay6TFGPRotIv_j-tl5Jhl5_Lo,1059
|
|
93
93
|
nlbone/interfaces/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
94
94
|
nlbone/interfaces/cli/crypto.py,sha256=lh2uUbSYKT6XxAt9uP1-VksopqAgdxiSKoKgXwXB0aE,692
|
|
95
95
|
nlbone/interfaces/cli/init_db.py,sha256=Hk3aZ8w9KdfgQfDWaOnIgNEAegn2uNggkkSgDXQLgyc,1791
|
|
@@ -99,7 +99,7 @@ nlbone/interfaces/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
99
99
|
nlbone/interfaces/jobs/dispatch_outbox.py,sha256=yLZSC3nvkgxT2LL4Pq_DYzCyf_tZB-FknrjjgN89GFg,809
|
|
100
100
|
nlbone/interfaces/jobs/sync_tokens.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
101
101
|
nlbone/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
102
|
-
nlbone/utils/cache.py,sha256=
|
|
102
|
+
nlbone/utils/cache.py,sha256=KHUYjhIo6dbaSdY9RjbxUJQlLMdacMLjdDm5QZ5dLUw,7305
|
|
103
103
|
nlbone/utils/cache_keys.py,sha256=Y2YSellHTbUOcoaNbl1jaD4r485VU_e4KXsfBWhYTBo,1075
|
|
104
104
|
nlbone/utils/cache_registry.py,sha256=3FWYyhujW8oPBiVUPzk1CqJ3jJfxs9729Sbb1pQ5Fag,707
|
|
105
105
|
nlbone/utils/context.py,sha256=MmclJ24BG2uvSTg1IK7J-Da9BhVFDQ5ag4Ggs2FF1_w,1600
|
|
@@ -108,8 +108,8 @@ nlbone/utils/http.py,sha256=MPDEyaC16AKsL0YH6sWCPp8NC2TgzEHpWERYK5HcaYQ,1001
|
|
|
108
108
|
nlbone/utils/normalize_mobile.py,sha256=sGH4tV9gX-6eVKozviNWJhm1DN1J28Nj-ERldCYkS_E,732
|
|
109
109
|
nlbone/utils/redactor.py,sha256=-V4HrHmHwPi3Kez587Ek1uJlgK35qGSrwBOvcbw8Jas,1279
|
|
110
110
|
nlbone/utils/time.py,sha256=DjjyQ9GLsfXoT6NK8RDW2rOlJg3e6sF04Jw6PBUrSvg,1268
|
|
111
|
-
nlbone-0.7.
|
|
112
|
-
nlbone-0.7.
|
|
113
|
-
nlbone-0.7.
|
|
114
|
-
nlbone-0.7.
|
|
115
|
-
nlbone-0.7.
|
|
111
|
+
nlbone-0.7.22.dist-info/METADATA,sha256=Ot4i8NvJ9NaRmohME6fDJvWsiqO1F3-AerVFHSchuDE,2295
|
|
112
|
+
nlbone-0.7.22.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
113
|
+
nlbone-0.7.22.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
|
|
114
|
+
nlbone-0.7.22.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
115
|
+
nlbone-0.7.22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|