nlbone 0.7.19__py3-none-any.whl → 0.7.21__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.
@@ -35,7 +35,7 @@ class AuthService(BaseAuthService):
35
35
  return None
36
36
 
37
37
  def get_client_token(self) -> dict | None:
38
- url = f"{self._base_url}/introspect"
38
+ url = f"{self._base_url}/token"
39
39
  result = self._client.post(url, data={
40
40
  "client_id": self.client_id,
41
41
  "client_secret": self.client_secret,
@@ -2,13 +2,13 @@ import threading
2
2
  import time
3
3
  from typing import Any, Dict, Optional
4
4
 
5
- from nlbone.adapters.auth.keycloak import KeycloakAuthService
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: KeycloakAuthService, *, skew_seconds: int = 30) -> None:
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()
@@ -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, Mapping
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
- tpl: Optional[str],
65
- func: Callable,
66
- args,
67
- kwargs,
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
- tag_tpls: Optional[Iterable[str]],
88
- func: Callable,
89
- args,
90
- kwargs,
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
- 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,
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
- if _is_async_method(cache, "get"):
159
- cached_bytes = await cache.get(k)
160
- else:
161
- cached_bytes = cache.get(k)
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 -> compute
163
+ # MISS compute
167
164
  result = await func(*args, **kwargs)
168
165
 
169
- # SET
166
+ # SAFE SET
170
167
  data = serializer(result)
171
- if _is_async_method(cache, "set"):
172
- await cache.set(k, data, ttl=ttl, tags=tg)
173
- else:
174
- cache.set(k, data, ttl=ttl, tags=tg)
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 (may be async)
190
- if _is_async_method(cache, "get"):
191
- cached_bytes = _run_maybe_async(cache.get, k)
192
- else:
193
- cached_bytes = cache.get(k)
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 -> compute
203
+ # MISS compute
199
204
  result = func(*args, **kwargs)
200
205
 
201
- # SET (may be async)
206
+ # SAFE SET (maybe async)
202
207
  data = serializer(result)
203
- if _is_async_method(cache, "set"):
204
- _run_maybe_async(cache.set, k, data, ttl=ttl, tags=tg)
205
- else:
206
- cache.set(k, data, ttl=ttl, tags=tg)
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nlbone
3
- Version: 0.7.19
3
+ Version: 0.7.21
4
4
  Summary: Backbone package for interfaces and infrastructure in Python projects
5
5
  Author-email: Amir Hosein Kahkbazzadeh <a.khakbazzadeh@gmail.com>
6
6
  License: MIT
@@ -4,9 +4,9 @@ nlbone/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  nlbone/adapters/__init__.py,sha256=NzUmk4XPyp3GJOw7VSE86xkQMZLtG3MrOoXLeoB551M,41
5
5
  nlbone/adapters/snowflake.py,sha256=lmq7vi6HdX9hEuTW6BlTEAy91wmrA4Bx3tvGoagHTW4,2315
6
6
  nlbone/adapters/auth/__init__.py,sha256=hkDHvsFhw_UiOHG9ZSMqjiAhK4wumEforitveSZswVw,42
7
- nlbone/adapters/auth/auth_service.py,sha256=oFkqBaJJX2OEwxY6GcuNbqWlMtfK1zeyIfwTXx0dDzo,2113
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=EcZ7nSXxPZJZGaWnyo3QDvrEbGdeXXWnhHnP1-kMniY,1438
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
@@ -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=IdAw01ScbqWcyKLwn0LLY5C8wPq2188BkHDUEJw-4lw,775
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=BJoWbDicwTS1CF9m8sBKIEgfG-OszoQEEsMqrCHwNL0,7204
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.19.dist-info/METADATA,sha256=VcpV2x6nt4JD3zdvowi72_MLSDJ7tiiDx6HH7KanDU8,2295
112
- nlbone-0.7.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
113
- nlbone-0.7.19.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
114
- nlbone-0.7.19.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
- nlbone-0.7.19.dist-info/RECORD,,
111
+ nlbone-0.7.21.dist-info/METADATA,sha256=rbwKRkIxnjb56sCLEIql0jONFgcjeVzk23a9KbCDIqU,2295
112
+ nlbone-0.7.21.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
113
+ nlbone-0.7.21.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
114
+ nlbone-0.7.21.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
115
+ nlbone-0.7.21.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any