nlbone 0.6.8__tar.gz → 0.6.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.
- {nlbone-0.6.8 → nlbone-0.6.9}/PKG-INFO +1 -1
- {nlbone-0.6.8 → nlbone-0.6.9}/pyproject.toml +1 -1
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/query_builder.py +103 -86
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/http_clients/pricing/pricing_service.py +19 -3
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/container.py +4 -3
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/pagination/offset_base.py +14 -12
- {nlbone-0.6.8 → nlbone-0.6.9}/.gitignore +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/LICENSE +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/README.md +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/auth/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/auth/keycloak.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/auth/token_provider.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/cache/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/cache/async_redis.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/cache/memory.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/cache/pubsub_listener.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/cache/redis.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/audit.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/base.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/engine.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/repository.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/schema.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/postgres/uow.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/redis/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/db/redis/client.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/http_clients/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/http_clients/pricing/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/http_clients/uploadchi/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/http_clients/uploadchi/uploadchi.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/http_clients/uploadchi/uploadchi_async.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/messaging/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/messaging/event_bus.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/messaging/redis.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/percolation/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/adapters/percolation/connection.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/config/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/config/logging.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/config/settings.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/application/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/application/base_worker.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/application/events.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/application/services/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/application/services.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/application/use_case.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/domain/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/domain/base.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/domain/events.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/domain/models.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/auth.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/cache.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/event_bus.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/files.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/messaging.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/repo.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/core/ports/uow.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/dependencies/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/dependencies/async_auth.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/dependencies/auth.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/dependencies/db.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/dependencies/uow.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/exception_handlers.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/exceptions.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/middleware/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/middleware/access_log.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/middleware/add_request_context.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/middleware/authentication.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/pagination/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/routers.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/api/schemas.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/cli/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/cli/init_db.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/cli/main.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/jobs/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/interfaces/jobs/sync_tokens.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/types.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/__init__.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/cache.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/cache_keys.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/cache_registry.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/context.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/http.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/redactor.py +0 -0
- {nlbone-0.6.8 → nlbone-0.6.9}/src/nlbone/utils/time.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Any, Callable, Optional, Sequence, Type, Union
|
|
2
2
|
|
|
3
|
-
from sqlalchemy import asc, desc, or_
|
|
3
|
+
from sqlalchemy import asc, desc, or_, and_, case, literal
|
|
4
4
|
from sqlalchemy.dialects.postgresql import ENUM as PGEnum
|
|
5
5
|
from sqlalchemy.orm import Query, Session
|
|
6
6
|
from sqlalchemy.orm.interfaces import LoaderOption
|
|
@@ -29,8 +29,15 @@ class _InvalidEnum(Exception):
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def _apply_order(pagination: PaginateRequest, entity, query):
|
|
32
|
+
order_clauses = []
|
|
33
|
+
|
|
34
|
+
include_ids = getattr(pagination, "include_ids", []) or []
|
|
35
|
+
if include_ids and hasattr(entity, "id"):
|
|
36
|
+
id_col = getattr(entity, "id")
|
|
37
|
+
whens = [(id_col == _id, idx) for idx, _id in enumerate(include_ids)]
|
|
38
|
+
order_clauses.append(asc(case(*whens, else_=literal(999_999))))
|
|
39
|
+
|
|
32
40
|
if pagination.sort:
|
|
33
|
-
order_clauses = []
|
|
34
41
|
for sort in pagination.sort:
|
|
35
42
|
field = sort["field"]
|
|
36
43
|
order = sort["order"]
|
|
@@ -42,8 +49,8 @@ def _apply_order(pagination: PaginateRequest, entity, query):
|
|
|
42
49
|
else:
|
|
43
50
|
order_clauses.append(desc(column))
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
if order_clauses:
|
|
53
|
+
query = query.order_by(*order_clauses)
|
|
47
54
|
return query
|
|
48
55
|
|
|
49
56
|
|
|
@@ -101,89 +108,100 @@ def _parse_field_and_op(field: str):
|
|
|
101
108
|
|
|
102
109
|
|
|
103
110
|
def _apply_filters(pagination, entity, query):
|
|
104
|
-
if not getattr(pagination, "filters", None):
|
|
111
|
+
if not getattr(pagination, "filters", None) and not getattr(pagination, "include_ids", None):
|
|
105
112
|
return query
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if isinstance(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
114
|
+
predicates = []
|
|
115
|
+
|
|
116
|
+
if getattr(pagination, "filters", None):
|
|
117
|
+
for raw_field, value in pagination.filters.items():
|
|
118
|
+
if value is None or value in NULL_SENTINELS or value == [] or value == {}:
|
|
119
|
+
value = None
|
|
120
|
+
|
|
121
|
+
field, op_hint = _parse_field_and_op(raw_field)
|
|
122
|
+
|
|
123
|
+
if not hasattr(entity, field):
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
col = getattr(entity, field)
|
|
127
|
+
coltype = getattr(col, "type", None)
|
|
128
|
+
|
|
129
|
+
def coerce(v):
|
|
130
|
+
if v is None:
|
|
131
|
+
return None
|
|
132
|
+
# Enums
|
|
133
|
+
if isinstance(coltype, (SAEnum, PGEnum)):
|
|
134
|
+
return _coerce_enum(coltype, v)
|
|
135
|
+
# Text
|
|
136
|
+
if _is_text_type(coltype):
|
|
137
|
+
return str(v)
|
|
138
|
+
# Numbers
|
|
139
|
+
if isinstance(coltype, (Integer, BigInteger, SmallInteger)):
|
|
140
|
+
return int(v)
|
|
141
|
+
if isinstance(coltype, (Float, Numeric)):
|
|
142
|
+
return float(v)
|
|
143
|
+
# Booleans
|
|
144
|
+
if isinstance(coltype, Boolean):
|
|
145
|
+
if isinstance(v, bool):
|
|
146
|
+
return v
|
|
147
|
+
if isinstance(v, (int, float)):
|
|
148
|
+
return bool(v)
|
|
149
|
+
if isinstance(v, str):
|
|
150
|
+
vl = v.strip().lower()
|
|
151
|
+
if vl in {"true", "1", "yes", "y", "t"}:
|
|
152
|
+
return True
|
|
153
|
+
if vl in {"false", "0", "no", "n", "f"}:
|
|
154
|
+
return False
|
|
155
|
+
return None
|
|
156
|
+
return v
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
def _use_ilike(v) -> bool:
|
|
160
|
+
if op_hint == "ilike":
|
|
161
|
+
return True
|
|
162
|
+
if _is_text_type(coltype) and isinstance(v, str) and _looks_like_wildcard(v):
|
|
142
163
|
return True
|
|
143
|
-
|
|
144
|
-
return False
|
|
145
|
-
return None
|
|
146
|
-
# fallback
|
|
147
|
-
return v
|
|
164
|
+
return False
|
|
148
165
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if op_hint == "ilike":
|
|
153
|
-
return True
|
|
154
|
-
if _is_text_type(coltype) and isinstance(v, str) and _looks_like_wildcard(v):
|
|
155
|
-
return True
|
|
156
|
-
return False
|
|
157
|
-
|
|
158
|
-
if isinstance(value, (list, tuple, set)):
|
|
159
|
-
vals = [v for v in value if v not in (None, "", "null", "None")]
|
|
160
|
-
if not vals:
|
|
161
|
-
continue
|
|
162
|
-
|
|
163
|
-
# if any value signals ilike, apply OR of ilike; else IN / EQs
|
|
164
|
-
if any(_use_ilike(v) for v in vals) and _is_text_type(coltype):
|
|
165
|
-
patterns = [_to_sql_like_pattern(str(v)) for v in vals]
|
|
166
|
-
query = query.filter(or_(*[col.ilike(p) for p in patterns]))
|
|
167
|
-
else:
|
|
168
|
-
coerced = [coerce(v) for v in vals]
|
|
169
|
-
if not coerced:
|
|
166
|
+
if isinstance(value, (list, tuple, set)):
|
|
167
|
+
vals = [v for v in value if v not in (None, "", "null", "None")]
|
|
168
|
+
if not vals:
|
|
170
169
|
continue
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
|
|
171
|
+
if any(_use_ilike(v) for v in vals) and _is_text_type(coltype):
|
|
172
|
+
patterns = [_to_sql_like_pattern(str(v)) for v in vals]
|
|
173
|
+
predicates.append(or_(*[col.ilike(p) for p in patterns]))
|
|
174
|
+
else:
|
|
175
|
+
coerced = [coerce(v) for v in vals]
|
|
176
|
+
if not coerced:
|
|
177
|
+
continue
|
|
178
|
+
predicates.append(col.in_(coerced))
|
|
176
179
|
else:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
if _use_ilike(value) and _is_text_type(coltype):
|
|
181
|
+
pattern = _to_sql_like_pattern(str(value))
|
|
182
|
+
predicates.append(col.ilike(pattern))
|
|
180
183
|
else:
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
v = coerce(value)
|
|
185
|
+
if v is None:
|
|
186
|
+
predicates.append(col.is_(None))
|
|
187
|
+
else:
|
|
188
|
+
predicates.append(col == v)
|
|
189
|
+
|
|
190
|
+
except _InvalidEnum as e:
|
|
191
|
+
raise UnprocessableEntityException(str(e), loc=["query", "filters", raw_field]) from e
|
|
192
|
+
|
|
193
|
+
include_ids = getattr(pagination, "include_ids", []) or []
|
|
194
|
+
if include_ids and hasattr(entity, "id"):
|
|
195
|
+
id_col = getattr(entity, "id")
|
|
196
|
+
include_pred = id_col.in_(include_ids)
|
|
197
|
+
if predicates:
|
|
198
|
+
final_pred = or_(and_(*predicates), include_pred)
|
|
199
|
+
else:
|
|
200
|
+
final_pred = or_(and_(*[1 == 1]), include_pred)
|
|
201
|
+
return query.filter(final_pred)
|
|
202
|
+
|
|
203
|
+
if predicates:
|
|
204
|
+
query = query.filter(and_(*predicates))
|
|
187
205
|
return query
|
|
188
206
|
|
|
189
207
|
|
|
@@ -210,24 +228,24 @@ def _serialize_item(item: Any, output_cls: OutputType) -> Any:
|
|
|
210
228
|
|
|
211
229
|
if hasattr(output_cls, "model_validate"):
|
|
212
230
|
try:
|
|
213
|
-
model = output_cls.model_validate(item, from_attributes=True)
|
|
231
|
+
model = output_cls.model_validate(item, from_attributes=True)
|
|
214
232
|
if hasattr(model, "model_dump"):
|
|
215
|
-
return model.model_dump()
|
|
233
|
+
return model.model_dump()
|
|
216
234
|
return model
|
|
217
235
|
except Exception:
|
|
218
236
|
pass
|
|
219
237
|
|
|
220
238
|
if hasattr(output_cls, "from_orm"):
|
|
221
239
|
try:
|
|
222
|
-
model = output_cls.from_orm(item)
|
|
240
|
+
model = output_cls.from_orm(item)
|
|
223
241
|
if hasattr(model, "dict"):
|
|
224
|
-
return model.dict()
|
|
242
|
+
return model.dict()
|
|
225
243
|
return model
|
|
226
244
|
except Exception:
|
|
227
245
|
pass
|
|
228
246
|
|
|
229
247
|
try:
|
|
230
|
-
obj = output_cls(item)
|
|
248
|
+
obj = output_cls(item)
|
|
231
249
|
try:
|
|
232
250
|
from dataclasses import asdict, is_dataclass
|
|
233
251
|
|
|
@@ -249,7 +267,6 @@ def get_paginated_response(
|
|
|
249
267
|
output_cls: Optional[Type] = None,
|
|
250
268
|
eager_options: Optional[Sequence[LoaderOption]] = None,
|
|
251
269
|
) -> dict:
|
|
252
|
-
# پایهی کوئری
|
|
253
270
|
query = session.query(entity)
|
|
254
271
|
if eager_options:
|
|
255
272
|
query = query.options(*eager_options)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
1
2
|
from enum import Enum
|
|
2
|
-
from typing import List, Literal, Optional
|
|
3
|
+
from typing import Dict, List, Literal, Optional, Union
|
|
3
4
|
|
|
4
5
|
import httpx
|
|
5
6
|
import requests
|
|
@@ -32,7 +33,7 @@ class Product(BaseModel):
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class Pricing(BaseModel):
|
|
35
|
-
source: Literal["formula", "static"]
|
|
36
|
+
source: Optional[Literal["formula", "static"]] = None
|
|
36
37
|
price: Optional[float] = None
|
|
37
38
|
discount: Optional[float] = None
|
|
38
39
|
discount_type: Optional[DiscountType] = None
|
|
@@ -61,7 +62,7 @@ class PricingRule(BaseModel):
|
|
|
61
62
|
pricing: Pricing
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
class CalculatePriceOut(RootModel[List[PricingRule]]):
|
|
65
|
+
class CalculatePriceOut(RootModel[Union[List[PricingRule], Dict[str, PricingRule]]]):
|
|
65
66
|
pass
|
|
66
67
|
|
|
67
68
|
|
|
@@ -98,3 +99,18 @@ class PricingService:
|
|
|
98
99
|
return CalculatePriceOut.model_validate(root=[])
|
|
99
100
|
|
|
100
101
|
return CalculatePriceOut.model_validate(r.json())
|
|
102
|
+
|
|
103
|
+
def exchange_rates(self) -> Dict[str, Decimal]:
|
|
104
|
+
r = self._client.get(
|
|
105
|
+
f"{self._base_url}/variables/key/exchange_rates",
|
|
106
|
+
headers=auth_headers(self._token_provider.get_access_token()),
|
|
107
|
+
timeout=self._timeout,
|
|
108
|
+
verify=False,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if r.status_code != 200:
|
|
112
|
+
raise PricingError(r.status_code, r.text)
|
|
113
|
+
|
|
114
|
+
values = r.json().get("values")
|
|
115
|
+
|
|
116
|
+
return {f"{value['key']}": Decimal(value["value"]) for value in values}
|
|
@@ -15,6 +15,7 @@ from nlbone.adapters.http_clients import PricingService
|
|
|
15
15
|
from nlbone.adapters.http_clients.uploadchi import UploadchiClient
|
|
16
16
|
from nlbone.adapters.http_clients.uploadchi.uploadchi_async import UploadchiAsyncClient
|
|
17
17
|
from nlbone.adapters.messaging import InMemoryEventBus
|
|
18
|
+
from nlbone.config.settings import Settings
|
|
18
19
|
from nlbone.core.ports import EventBusPort
|
|
19
20
|
from nlbone.core.ports.cache import AsyncCachePort, CachePort
|
|
20
21
|
from nlbone.core.ports.files import AsyncFileServicePort, FileServicePort
|
|
@@ -62,12 +63,12 @@ class Container(containers.DeclarativeContainer):
|
|
|
62
63
|
def create_container(settings: Optional[Any] = None) -> Container:
|
|
63
64
|
c = Container()
|
|
64
65
|
if settings is not None:
|
|
65
|
-
if
|
|
66
|
+
if isinstance(settings, Settings):
|
|
67
|
+
c.config.override(settings)
|
|
68
|
+
elif hasattr(settings, "model_dump"):
|
|
66
69
|
c.config.from_dict(settings.model_dump()) # Pydantic v2
|
|
67
70
|
elif hasattr(settings, "dict"):
|
|
68
71
|
c.config.from_dict(settings.dict()) # Pydantic v1
|
|
69
72
|
elif isinstance(settings, Mapping):
|
|
70
73
|
c.config.from_dict(dict(settings))
|
|
71
|
-
else:
|
|
72
|
-
c.config.override(settings)
|
|
73
74
|
return c
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from math import ceil
|
|
3
|
-
from typing import Any, Optional
|
|
3
|
+
from typing import Any, Optional, List
|
|
4
4
|
|
|
5
5
|
from fastapi import Query
|
|
6
6
|
|
|
@@ -13,16 +13,18 @@ class PaginateRequest:
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
def __init__(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
self,
|
|
17
|
+
limit: int = 10,
|
|
18
|
+
offset: int = 0,
|
|
19
|
+
sort: Optional[str] = None,
|
|
20
|
+
filters: Optional[str] = Query(None, description="e.g. title:abc"),
|
|
21
|
+
include: Optional[str] = None,
|
|
21
22
|
) -> None:
|
|
22
23
|
self.limit = max(0, limit)
|
|
23
24
|
self.offset = max(0, offset)
|
|
24
25
|
self.sort = self._parse_sort(sort)
|
|
25
26
|
self.filters = self._parse_filters(filters or "")
|
|
27
|
+
self.include_ids: List[int] = ([int(x) for x in include.split(",") if x.strip().isdigit()] if include else [])[:50]
|
|
26
28
|
|
|
27
29
|
@staticmethod
|
|
28
30
|
def _parse_sort(sort_str: Optional[str]) -> list[dict[str, str]]:
|
|
@@ -81,12 +83,12 @@ class PaginateResponse:
|
|
|
81
83
|
"""
|
|
82
84
|
|
|
83
85
|
def __init__(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
self,
|
|
87
|
+
data: list[Any],
|
|
88
|
+
total_count: int | None,
|
|
89
|
+
limit: int,
|
|
90
|
+
offset: int,
|
|
91
|
+
use_data_key: bool = True,
|
|
90
92
|
) -> None:
|
|
91
93
|
self.data = data
|
|
92
94
|
self.total_count = total_count
|
|
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
|
|
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
|
|
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
|
|
File without changes
|