sqla-fancy-core 1.1.0__py3-none-any.whl → 1.1.2__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 sqla-fancy-core might be problematic. Click here for more details.

@@ -7,7 +7,9 @@ from typing import Union, overload
7
7
  import sqlalchemy as sa
8
8
  from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine
9
9
 
10
- EngineType = Union[sa.engine.Engine, AsyncEngine]
10
+ from sqla_fancy_core.wrappers import AsyncFancyEngineWrapper, FancyEngineWrapper
11
+
12
+ EngineType = Union[sa.Engine, AsyncEngine, FancyEngineWrapper, AsyncFancyEngineWrapper]
11
13
 
12
14
 
13
15
  class _Injectable:
@@ -16,9 +18,9 @@ class _Injectable:
16
18
 
17
19
 
18
20
  @overload
19
- def Inject(engine: sa.Engine) -> sa.Connection: ...
21
+ def Inject(engine: Union[sa.Engine, FancyEngineWrapper]) -> sa.Connection: ...
20
22
  @overload
21
- def Inject(engine: AsyncEngine) -> AsyncConnection: ...
23
+ def Inject(engine: Union[AsyncEngine, AsyncFancyEngineWrapper]) -> AsyncConnection: ...
22
24
  def Inject(engine: EngineType): # type: ignore
23
25
  """A marker class for dependency injection."""
24
26
  return _Injectable(engine)
@@ -44,7 +46,6 @@ def transact(func):
44
46
  create_user(name="existing", conn=conn)
45
47
  """
46
48
 
47
- # Find the parameter with value Inject
48
49
  sig = inspect.signature(func)
49
50
  inject_param_name = None
50
51
  for name, param in sig.parameters.items():
@@ -56,8 +57,21 @@ def transact(func):
56
57
  if inject_param_name is None:
57
58
  return func # No injection needed
58
59
 
59
- engine = sig.parameters[inject_param_name].default.engine
60
- is_async = isinstance(engine, AsyncEngine)
60
+ engine_arg = sig.parameters[inject_param_name].default.engine
61
+ if isinstance(engine_arg, sa.Engine):
62
+ is_async = False
63
+ engine = engine_arg
64
+ elif isinstance(engine_arg, FancyEngineWrapper):
65
+ is_async = False
66
+ engine = engine_arg.engine
67
+ elif isinstance(engine_arg, AsyncEngine):
68
+ is_async = True
69
+ engine = engine_arg
70
+ elif isinstance(engine_arg, AsyncFancyEngineWrapper):
71
+ is_async = True
72
+ engine = engine_arg.engine
73
+ else:
74
+ raise TypeError("Unsupported engine type")
61
75
 
62
76
  if is_async:
63
77
 
@@ -70,8 +84,14 @@ def transact(func):
70
84
  else:
71
85
  async with conn.begin():
72
86
  return await func(*args, **kwargs)
87
+ elif isinstance(conn, sa.Connection):
88
+ if conn.in_transaction():
89
+ return await func(*args, **kwargs)
90
+ else:
91
+ with conn.begin():
92
+ return await func(*args, **kwargs)
73
93
  else:
74
- async with engine.begin() as conn:
94
+ async with engine.begin() as conn: # type: ignore
75
95
  kwargs[inject_param_name] = conn
76
96
  return await func(*args, **kwargs)
77
97
 
@@ -88,8 +108,10 @@ def transact(func):
88
108
  else:
89
109
  with conn.begin():
90
110
  return func(*args, **kwargs)
111
+ elif isinstance(conn, AsyncConnection):
112
+ raise TypeError("AsyncConnection cannot be used in sync function")
91
113
  else:
92
- with engine.begin() as conn:
114
+ with engine.begin() as conn: # type: ignore
93
115
  kwargs[inject_param_name] = conn
94
116
  return func(*args, **kwargs)
95
117
 
@@ -116,7 +138,6 @@ def connect(func):
116
138
  count = get_user_count(conn)
117
139
  """
118
140
 
119
- # Find the parameter with value Inject
120
141
  sig = inspect.signature(func)
121
142
  inject_param_name = None
122
143
  for name, param in sig.parameters.items():
@@ -128,18 +149,31 @@ def connect(func):
128
149
  if inject_param_name is None:
129
150
  return func # No injection needed
130
151
 
131
- engine = sig.parameters[inject_param_name].default.engine
132
- is_async = isinstance(engine, AsyncEngine)
152
+ engine_arg = sig.parameters[inject_param_name].default.engine
153
+ if isinstance(engine_arg, sa.Engine):
154
+ is_async = False
155
+ engine = engine_arg
156
+ elif isinstance(engine_arg, FancyEngineWrapper):
157
+ is_async = False
158
+ engine = engine_arg.engine
159
+ elif isinstance(engine_arg, AsyncEngine):
160
+ is_async = True
161
+ engine = engine_arg
162
+ elif isinstance(engine_arg, AsyncFancyEngineWrapper):
163
+ is_async = True
164
+ engine = engine_arg.engine
165
+ else:
166
+ raise TypeError("Unsupported engine type")
133
167
 
134
168
  if is_async:
135
169
 
136
170
  @functools.wraps(func)
137
171
  async def async_wrapper(*args, **kwargs):
138
172
  conn = kwargs.get(inject_param_name)
139
- if isinstance(conn, AsyncConnection):
173
+ if isinstance(conn, (AsyncConnection, sa.Connection)):
140
174
  return await func(*args, **kwargs)
141
175
  else:
142
- async with engine.connect() as conn:
176
+ async with engine.connect() as conn: # type: ignore
143
177
  kwargs[inject_param_name] = conn
144
178
  return await func(*args, **kwargs)
145
179
 
@@ -152,8 +186,10 @@ def connect(func):
152
186
  conn = kwargs.get(inject_param_name)
153
187
  if isinstance(conn, sa.Connection):
154
188
  return func(*args, **kwargs)
189
+ elif isinstance(conn, AsyncConnection):
190
+ raise TypeError("AsyncConnection cannot be used in sync function")
155
191
  else:
156
- with engine.connect() as conn:
192
+ with engine.connect() as conn: # type: ignore
157
193
  kwargs[inject_param_name] = conn
158
194
  return func(*args, **kwargs)
159
195
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqla-fancy-core
3
- Version: 1.1.0
3
+ Version: 1.1.2
4
4
  Summary: SQLAlchemy core, but fancier
5
5
  Project-URL: Homepage, https://github.com/sayanarijit/sqla-fancy-core
6
6
  Author-email: Arijit Basu <sayanarijit@gmail.com>
@@ -242,27 +242,24 @@ users = sa.Table(
242
242
  )
243
243
  metadata.create_all(engine)
244
244
 
245
- # 1) Ensure a connection is available (no implicit transaction)
246
245
  @connect
247
246
  def get_user_count(conn=Inject(engine)):
248
247
  return conn.execute(sa.select(sa.func.count()).select_from(users)).scalar_one()
249
248
 
250
249
  assert get_user_count() == 0
251
250
 
252
- # 2) Wrap in a transaction automatically
253
251
  @transact
254
252
  def create_user(name: str, conn=Inject(engine)):
255
253
  conn.execute(sa.insert(users).values(name=name))
256
254
 
255
+ # Without an explicit transaction
257
256
  create_user("alice")
258
257
  assert get_user_count() == 1
259
258
 
260
- # 3) Reuse an explicit connection or transaction
259
+ # With an explicit transaction
261
260
  with engine.begin() as txn:
262
261
  create_user("bob", conn=txn)
263
262
  assert get_user_count(conn=txn) == 2
264
-
265
- assert get_user_count() == 2
266
263
  ```
267
264
 
268
265
  ### Async examples
@@ -293,10 +290,12 @@ async def get_user_count(conn=Inject(engine)):
293
290
  async def create_user(name: str, conn=Inject(engine)):
294
291
  await conn.execute(sa.insert(users).values(name=name))
295
292
 
293
+ # Without an explicit transaction
296
294
  assert await get_user_count() == 0
297
295
  await create_user("carol")
298
296
  assert await get_user_count() == 1
299
297
 
298
+ # With an explicit transaction
300
299
  async with engine.connect() as conn:
301
300
  await create_user("dave", conn=conn)
302
301
  assert await get_user_count(conn=conn) == 2
@@ -0,0 +1,8 @@
1
+ sqla_fancy_core/__init__.py,sha256=iCfZrKbdoAG65CeHGducjiA1p4zYLgFSrxGDzQEhM8U,256
2
+ sqla_fancy_core/decorators.py,sha256=VhkYf5x6qwcQnc8QCuUzKPQxMI3tNNGM7nVSPUqMkPw,6649
3
+ sqla_fancy_core/factories.py,sha256=EgOhc15rCo9GyIuSNhuoB1pJ6lXx_UtRR5y9hh2lEtM,6326
4
+ sqla_fancy_core/wrappers.py,sha256=TesGKm9ddsd7dJwbkonZPl46Huvqeh7AfUwB623qRwA,8165
5
+ sqla_fancy_core-1.1.2.dist-info/METADATA,sha256=dWdZEq6fwzkvrK9zoYpAdh5QQLtMd1lc5NATrp2-1Yo,14419
6
+ sqla_fancy_core-1.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ sqla_fancy_core-1.1.2.dist-info/licenses/LICENSE,sha256=XcYXJ0ipvwOn-nzko6p_xoCCbke8tAhmlIN04rUZDLk,1068
8
+ sqla_fancy_core-1.1.2.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- sqla_fancy_core/__init__.py,sha256=iCfZrKbdoAG65CeHGducjiA1p4zYLgFSrxGDzQEhM8U,256
2
- sqla_fancy_core/decorators.py,sha256=0UlOL2MUAJq3Rv3hE7mLspvrZDX16f2pm_yh1mLgQWQ,5056
3
- sqla_fancy_core/factories.py,sha256=EgOhc15rCo9GyIuSNhuoB1pJ6lXx_UtRR5y9hh2lEtM,6326
4
- sqla_fancy_core/wrappers.py,sha256=TesGKm9ddsd7dJwbkonZPl46Huvqeh7AfUwB623qRwA,8165
5
- sqla_fancy_core-1.1.0.dist-info/METADATA,sha256=1imY4gioOlMMTxS3GBit_-eUSGz71_ArMl9D7WWMxxU,14473
6
- sqla_fancy_core-1.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- sqla_fancy_core-1.1.0.dist-info/licenses/LICENSE,sha256=XcYXJ0ipvwOn-nzko6p_xoCCbke8tAhmlIN04rUZDLk,1068
8
- sqla_fancy_core-1.1.0.dist-info/RECORD,,