jararaca 0.3.11a3__py3-none-any.whl → 0.3.11a4__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 jararaca might be problematic. Click here for more details.
- jararaca/__init__.py +28 -0
- jararaca/persistence/base.py +2 -1
- jararaca/persistence/interceptors/aiosqa_interceptor.py +86 -13
- {jararaca-0.3.11a3.dist-info → jararaca-0.3.11a4.dist-info}/METADATA +1 -1
- {jararaca-0.3.11a3.dist-info → jararaca-0.3.11a4.dist-info}/RECORD +8 -8
- {jararaca-0.3.11a3.dist-info → jararaca-0.3.11a4.dist-info}/LICENSE +0 -0
- {jararaca-0.3.11a3.dist-info → jararaca-0.3.11a4.dist-info}/WHEEL +0 -0
- {jararaca-0.3.11a3.dist-info → jararaca-0.3.11a4.dist-info}/entry_points.txt +0 -0
jararaca/__init__.py
CHANGED
|
@@ -73,7 +73,11 @@ if TYPE_CHECKING:
|
|
|
73
73
|
from .persistence.interceptors.aiosqa_interceptor import (
|
|
74
74
|
AIOSQAConfig,
|
|
75
75
|
AIOSqlAlchemySessionInterceptor,
|
|
76
|
+
providing_new_session,
|
|
77
|
+
providing_session,
|
|
78
|
+
providing_transaction,
|
|
76
79
|
use_session,
|
|
80
|
+
use_transaction,
|
|
77
81
|
)
|
|
78
82
|
from .persistence.utilities import (
|
|
79
83
|
CriteriaBasedAttributeQueryInjector,
|
|
@@ -191,6 +195,10 @@ if TYPE_CHECKING:
|
|
|
191
195
|
"Container",
|
|
192
196
|
"WebSocketInterceptor",
|
|
193
197
|
"use_session",
|
|
198
|
+
"use_transaction",
|
|
199
|
+
"providing_session",
|
|
200
|
+
"providing_transaction",
|
|
201
|
+
"providing_new_session",
|
|
194
202
|
"Post",
|
|
195
203
|
"Get",
|
|
196
204
|
"Patch",
|
|
@@ -335,6 +343,26 @@ _dynamic_imports: "dict[str, tuple[str, str, str | None]]" = {
|
|
|
335
343
|
"persistence.interceptors.aiosqa_interceptor",
|
|
336
344
|
None,
|
|
337
345
|
),
|
|
346
|
+
"use_transaction": (
|
|
347
|
+
__SPEC_PARENT__,
|
|
348
|
+
"persistence.interceptors.aiosqa_interceptor",
|
|
349
|
+
None,
|
|
350
|
+
),
|
|
351
|
+
"providing_session": (
|
|
352
|
+
__SPEC_PARENT__,
|
|
353
|
+
"persistence.interceptors.aiosqa_interceptor",
|
|
354
|
+
None,
|
|
355
|
+
),
|
|
356
|
+
"providing_new_session": (
|
|
357
|
+
__SPEC_PARENT__,
|
|
358
|
+
"persistence.interceptors.aiosqa_interceptor",
|
|
359
|
+
None,
|
|
360
|
+
),
|
|
361
|
+
"providing_transaction": (
|
|
362
|
+
__SPEC_PARENT__,
|
|
363
|
+
"persistence.interceptors.aiosqa_interceptor",
|
|
364
|
+
None,
|
|
365
|
+
),
|
|
338
366
|
"Post": (__SPEC_PARENT__, "presentation.decorators", None),
|
|
339
367
|
"Get": (__SPEC_PARENT__, "presentation.decorators", None),
|
|
340
368
|
"Patch": (__SPEC_PARENT__, "presentation.decorators", None),
|
jararaca/persistence/base.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import Any, Self, Type, TypeVar
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel
|
|
4
|
+
from sqlalchemy.ext.asyncio import AsyncAttrs
|
|
4
5
|
from sqlalchemy.orm import DeclarativeBase
|
|
5
6
|
|
|
6
7
|
IDENTIFIABLE_SCHEMA_T = TypeVar("IDENTIFIABLE_SCHEMA_T")
|
|
@@ -20,7 +21,7 @@ def recursive_get_dict(obj: Any) -> Any:
|
|
|
20
21
|
return obj
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
class BaseEntity(DeclarativeBase):
|
|
24
|
+
class BaseEntity(AsyncAttrs, DeclarativeBase):
|
|
24
25
|
|
|
25
26
|
@classmethod
|
|
26
27
|
def from_basemodel(cls, mutation: T_BASEMODEL) -> "Self":
|
|
@@ -3,21 +3,47 @@ from contextvars import ContextVar
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from typing import Any, AsyncGenerator, Generator
|
|
5
5
|
|
|
6
|
-
from sqlalchemy.ext.asyncio import
|
|
6
|
+
from sqlalchemy.ext.asyncio import (
|
|
7
|
+
AsyncSession,
|
|
8
|
+
AsyncSessionTransaction,
|
|
9
|
+
async_sessionmaker,
|
|
10
|
+
create_async_engine,
|
|
11
|
+
)
|
|
7
12
|
from sqlalchemy.ext.asyncio.engine import AsyncEngine
|
|
8
13
|
|
|
9
14
|
from jararaca.microservice import AppContext, AppInterceptor
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
ctx_default_connection_name: ContextVar[str] = ContextVar("ctx_default_connection_name")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def ensure_name(name: str | None) -> str:
|
|
20
|
+
if name is None:
|
|
21
|
+
return ctx_default_connection_name.get()
|
|
22
|
+
return name
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class PersistenceCtx:
|
|
27
|
+
session: AsyncSession
|
|
28
|
+
tx: AsyncSessionTransaction
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
ctx_session_map = ContextVar[dict[str, PersistenceCtx]]("ctx_session_map", default={})
|
|
12
32
|
|
|
13
33
|
|
|
14
34
|
@contextmanager
|
|
15
|
-
def
|
|
16
|
-
|
|
35
|
+
def providing_session(
|
|
36
|
+
session: AsyncSession,
|
|
37
|
+
tx: AsyncSessionTransaction,
|
|
38
|
+
connection_name: str | None = None,
|
|
17
39
|
) -> Generator[None, Any, None]:
|
|
40
|
+
|
|
41
|
+
connection_name = ensure_name(connection_name)
|
|
18
42
|
current_map = ctx_session_map.get({})
|
|
19
43
|
|
|
20
|
-
token = ctx_session_map.set(
|
|
44
|
+
token = ctx_session_map.set(
|
|
45
|
+
{**current_map, connection_name: PersistenceCtx(session, tx)}
|
|
46
|
+
)
|
|
21
47
|
|
|
22
48
|
try:
|
|
23
49
|
yield
|
|
@@ -26,18 +52,60 @@ def provide_session(
|
|
|
26
52
|
ctx_session_map.reset(token)
|
|
27
53
|
|
|
28
54
|
|
|
29
|
-
|
|
55
|
+
@asynccontextmanager
|
|
56
|
+
async def providing_new_session(
|
|
57
|
+
connection_name: str | None = None,
|
|
58
|
+
) -> AsyncGenerator[AsyncSession, None]:
|
|
59
|
+
|
|
60
|
+
current_session = use_session(connection_name)
|
|
61
|
+
|
|
62
|
+
async with AsyncSession(
|
|
63
|
+
current_session.bind,
|
|
64
|
+
) as new_session, new_session.begin() as new_tx:
|
|
65
|
+
with providing_session(new_session, new_tx, connection_name):
|
|
66
|
+
yield new_session
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def use_session(connection_name: str | None = None) -> AsyncSession:
|
|
70
|
+
connection_name = ensure_name(connection_name)
|
|
30
71
|
current_map = ctx_session_map.get({})
|
|
31
72
|
if connection_name not in current_map:
|
|
32
73
|
raise ValueError(f"Session not found for connection {connection_name}")
|
|
33
74
|
|
|
34
|
-
return current_map[connection_name]
|
|
75
|
+
return current_map[connection_name].session
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@contextmanager
|
|
79
|
+
def providing_transaction(
|
|
80
|
+
tx: AsyncSessionTransaction,
|
|
81
|
+
connection_name: str | None = None,
|
|
82
|
+
) -> Generator[None, Any, None]:
|
|
83
|
+
connection_name = ensure_name(connection_name)
|
|
84
|
+
|
|
85
|
+
current_map = ctx_session_map.get({})
|
|
86
|
+
|
|
87
|
+
if connection_name not in current_map:
|
|
88
|
+
raise ValueError(f"No session found for connection {connection_name}")
|
|
89
|
+
|
|
90
|
+
with providing_session(current_map[connection_name].session, tx, connection_name):
|
|
91
|
+
yield
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def use_transaction(connection_name: str | None = None) -> AsyncSessionTransaction:
|
|
95
|
+
current_map = ctx_session_map.get({})
|
|
96
|
+
if connection_name not in current_map:
|
|
97
|
+
raise ValueError(f"Transaction not found for connection {connection_name}")
|
|
98
|
+
|
|
99
|
+
return current_map[connection_name].tx
|
|
35
100
|
|
|
36
101
|
|
|
37
|
-
@dataclass
|
|
38
102
|
class AIOSQAConfig:
|
|
39
|
-
connection_name: str
|
|
40
103
|
url: str | AsyncEngine
|
|
104
|
+
connection_name: str
|
|
105
|
+
|
|
106
|
+
def __init__(self, url: str | AsyncEngine, connection_name: str = "default"):
|
|
107
|
+
self.url = url
|
|
108
|
+
self.connection_name = connection_name
|
|
41
109
|
|
|
42
110
|
|
|
43
111
|
class AIOSqlAlchemySessionInterceptor(AppInterceptor):
|
|
@@ -54,11 +122,16 @@ class AIOSqlAlchemySessionInterceptor(AppInterceptor):
|
|
|
54
122
|
|
|
55
123
|
@asynccontextmanager
|
|
56
124
|
async def intercept(self, app_context: AppContext) -> AsyncGenerator[None, None]:
|
|
57
|
-
|
|
58
|
-
|
|
125
|
+
|
|
126
|
+
async with self.sessionmaker() as session, session.begin() as tx:
|
|
127
|
+
token = ctx_default_connection_name.set(self.config.connection_name)
|
|
128
|
+
with providing_session(session, tx, self.config.connection_name):
|
|
59
129
|
try:
|
|
60
130
|
yield
|
|
61
|
-
|
|
131
|
+
if tx.is_active:
|
|
132
|
+
await tx.commit()
|
|
62
133
|
except Exception as e:
|
|
63
|
-
await
|
|
134
|
+
await tx.rollback()
|
|
64
135
|
raise e
|
|
136
|
+
finally:
|
|
137
|
+
ctx_default_connection_name.reset(token)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
jararaca/__init__.py,sha256=
|
|
1
|
+
jararaca/__init__.py,sha256=LL97aPXyHyb-bjW4EYL2y33UjJER2GlvjMlZiTLioEw,16387
|
|
2
2
|
jararaca/__main__.py,sha256=-O3vsB5lHdqNFjUtoELDF81IYFtR-DSiiFMzRaiSsv4,67
|
|
3
3
|
jararaca/broker_backend/__init__.py,sha256=GzEIuHR1xzgCJD4FE3harNjoaYzxHMHoEL0_clUaC-k,3528
|
|
4
4
|
jararaca/broker_backend/mapper.py,sha256=vTsi7sWpNvlga1PWPFg0rCJ5joJ0cdzykkIc2Tuvenc,696
|
|
@@ -27,10 +27,10 @@ jararaca/observability/decorators.py,sha256=XffBinFXdiNkY6eo8_1nkr_GapM0RUGBg0ai
|
|
|
27
27
|
jararaca/observability/interceptor.py,sha256=GHkuGKFWftN7MDjvYeGFGEPnuJETNhtxRK6yuPrCrpU,1462
|
|
28
28
|
jararaca/observability/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
29
|
jararaca/observability/providers/otel.py,sha256=LgfoITdoQTCxKebfLcEfwMiG992wlWY_0AUTd2fo8hY,6065
|
|
30
|
-
jararaca/persistence/base.py,sha256=
|
|
30
|
+
jararaca/persistence/base.py,sha256=xnGUbsLNz3gO-9iJt-Sn5NY13Yc9-misP8wLwQuGGoM,1024
|
|
31
31
|
jararaca/persistence/exports.py,sha256=Ghx4yoFaB4QVTb9WxrFYgmcSATXMNvrOvT8ybPNKXCA,62
|
|
32
32
|
jararaca/persistence/interceptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
-
jararaca/persistence/interceptors/aiosqa_interceptor.py,sha256=
|
|
33
|
+
jararaca/persistence/interceptors/aiosqa_interceptor.py,sha256=VOaoSFZtcCJTrdYxjLUtzkG6bWMVbOKT6WI1BP2hmls,4090
|
|
34
34
|
jararaca/persistence/session.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
35
|
jararaca/persistence/sort_filter.py,sha256=agggpN0YvNjUr6wJjy69NkaqxoDDW13ys9B3r85OujA,9226
|
|
36
36
|
jararaca/persistence/utilities.py,sha256=imcV4Oi5kXNk6m9QF2-OsnFpcTRY4w5mBYLdEx5XTSQ,14296
|
|
@@ -66,8 +66,8 @@ jararaca/tools/metadata.py,sha256=7nlCDYgItNybentPSSCc2MLqN7IpBd0VyQzfjfQycVI,14
|
|
|
66
66
|
jararaca/tools/typescript/interface_parser.py,sha256=35xbOrZDQDyTXdMrVZQ8nnFw79f28lJuLYNHAspIqi8,30492
|
|
67
67
|
jararaca/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
68
68
|
jararaca/utils/rabbitmq_utils.py,sha256=FPDP8ZVgvitZXV-oK73D7EIANsqUzXTW7HdpEKsIsyI,2811
|
|
69
|
-
jararaca-0.3.
|
|
70
|
-
jararaca-0.3.
|
|
71
|
-
jararaca-0.3.
|
|
72
|
-
jararaca-0.3.
|
|
73
|
-
jararaca-0.3.
|
|
69
|
+
jararaca-0.3.11a4.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
70
|
+
jararaca-0.3.11a4.dist-info/METADATA,sha256=VeC353GhTULAEFtJysdLpvMX1MBxRhwXsL35n4pCm5k,4954
|
|
71
|
+
jararaca-0.3.11a4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
72
|
+
jararaca-0.3.11a4.dist-info/entry_points.txt,sha256=WIh3aIvz8LwUJZIDfs4EeH3VoFyCGEk7cWJurW38q0I,45
|
|
73
|
+
jararaca-0.3.11a4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|