dycw-utilities 0.149.11__py3-none-any.whl → 0.150.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.149.11
3
+ Version: 0.150.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=ODa44fHOmk12CX4kZdMwXIvOfgua6psr4jhzHKVTZf0,61
1
+ utilities/__init__.py,sha256=-FKXlj49n14usgRRgsXp-6U1_cXzP-blAYQWGuSGKL8,60
2
2
  utilities/altair.py,sha256=92E2lCdyHY4Zb-vCw6rEJIsWdKipuu-Tu2ab1ufUfAk,9079
3
3
  utilities/asyncio.py,sha256=2m2a2C-Qgc6OHTTHL332-t66A7xDITt_SORT7a1DJWo,16792
4
4
  utilities/atomicwrites.py,sha256=xcOWenTBRS0oat3kg7Sqe51AohNThMQ2ixPL7QCG8hw,5795
@@ -66,7 +66,7 @@ utilities/sentinel.py,sha256=3jIwgpMekWgDAxPDA_hXMP2St43cPhciKN3LWiZ7kv0,1248
66
66
  utilities/shelve.py,sha256=4OzjQI6kGuUbJciqf535rwnao-_IBv66gsT6tRGiUt0,759
67
67
  utilities/slack_sdk.py,sha256=ppFBvKgfg5IRWiIoKPtpTyzBtBF4XmwEvU3I5wLJikM,2140
68
68
  utilities/socket.py,sha256=K77vfREvzoVTrpYKo6MZakol0EYu2q1sWJnnZqL0So0,118
69
- utilities/sqlalchemy.py,sha256=q2aYUDAC3SE88Lt6XaKa3CLzT_ePaWvQu_OuRk19x9g,35520
69
+ utilities/sqlalchemy.py,sha256=M__UwdIiXDc6W8oRHQ6u3h_zEb9uTKwfl506KJCrOl4,37231
70
70
  utilities/sqlalchemy_polars.py,sha256=18AoEbeNJUKF3-5hroNy9J5LQwS_QJAXbMfKc9sChtk,14250
71
71
  utilities/statsmodels.py,sha256=koyiBHvpMcSiBfh99wFUfSggLNx7cuAw3rwyfAhoKpQ,3410
72
72
  utilities/string.py,sha256=MB0X6UPTUc06JdAdj-PctZ238IXeCjE5dAJibNw6ZrU,587
@@ -89,8 +89,8 @@ utilities/zoneinfo.py,sha256=oEH-nL3t4h9uawyZqWDtNtDAl6M-CLpLYGI_nI6DulM,1971
89
89
  utilities/pytest_plugins/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
90
90
  utilities/pytest_plugins/pytest_randomly.py,sha256=NXzCcGKbpgYouz5yehKb4jmxmi2SexKKpgF4M65bi10,414
91
91
  utilities/pytest_plugins/pytest_regressions.py,sha256=Iwhfv_OJH7UCPZCfoh7ugZ2Xjqjil-BBBsOb8sDwiGI,1471
92
- dycw_utilities-0.149.11.dist-info/METADATA,sha256=wXNAZioNfRMvkYH6pANvwG5RbGy1D-9z7hSwmANMABA,1698
93
- dycw_utilities-0.149.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
94
- dycw_utilities-0.149.11.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
95
- dycw_utilities-0.149.11.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
96
- dycw_utilities-0.149.11.dist-info/RECORD,,
92
+ dycw_utilities-0.150.0.dist-info/METADATA,sha256=F2t8-Dhx3lTo-_ns45mIJ0vtLW9KTBUHrViS1bR94v0,1697
93
+ dycw_utilities-0.150.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
94
+ dycw_utilities-0.150.0.dist-info/entry_points.txt,sha256=BOD_SoDxwsfJYOLxhrSXhHP_T7iw-HXI9f2WVkzYxvQ,135
95
+ dycw_utilities-0.150.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
96
+ dycw_utilities-0.150.0.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.149.11"
3
+ __version__ = "0.150.0"
utilities/sqlalchemy.py CHANGED
@@ -18,8 +18,19 @@ from itertools import chain
18
18
  from math import floor
19
19
  from operator import ge, le
20
20
  from re import search
21
- from typing import TYPE_CHECKING, Any, Literal, TypeGuard, assert_never, cast, override
21
+ from typing import (
22
+ TYPE_CHECKING,
23
+ Any,
24
+ Literal,
25
+ TypeGuard,
26
+ assert_never,
27
+ cast,
28
+ overload,
29
+ override,
30
+ )
22
31
 
32
+ import sqlalchemy
33
+ import sqlalchemy.ext.asyncio
23
34
  from sqlalchemy import (
24
35
  URL,
25
36
  Column,
@@ -42,12 +53,12 @@ from sqlalchemy.dialects.postgresql import Insert as postgresql_Insert
42
53
  from sqlalchemy.dialects.postgresql import dialect as postgresql_dialect
43
54
  from sqlalchemy.dialects.postgresql import insert as postgresql_insert
44
55
  from sqlalchemy.dialects.postgresql.asyncpg import PGDialect_asyncpg
56
+ from sqlalchemy.dialects.postgresql.psycopg import PGDialect_psycopg
45
57
  from sqlalchemy.dialects.sqlite import Insert as sqlite_Insert
46
58
  from sqlalchemy.dialects.sqlite import dialect as sqlite_dialect
47
59
  from sqlalchemy.dialects.sqlite import insert as sqlite_insert
48
- from sqlalchemy.exc import ArgumentError, DatabaseError
60
+ from sqlalchemy.exc import ArgumentError, DatabaseError, OperationalError
49
61
  from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine
50
- from sqlalchemy.ext.asyncio import create_async_engine as _create_async_engine
51
62
  from sqlalchemy.orm import (
52
63
  DeclarativeBase,
53
64
  InstrumentedAttribute,
@@ -99,6 +110,18 @@ CHUNK_SIZE_FRAC = 0.8
99
110
  ##
100
111
 
101
112
 
113
+ def check_connect(engine: Engine, /) -> bool:
114
+ """Check if an engine can connect."""
115
+ try:
116
+ with engine.connect() as conn:
117
+ return bool(conn.execute(text("SELECT 1")).scalar_one())
118
+ except OperationalError:
119
+ return False
120
+
121
+
122
+ ##
123
+
124
+
102
125
  async def check_engine(
103
126
  engine: AsyncEngine,
104
127
  /,
@@ -187,7 +210,49 @@ def _columnwise_minmax(*columns: Any, op: Callable[[Any, Any], Any]) -> Any:
187
210
  ##
188
211
 
189
212
 
190
- def create_async_engine(
213
+ @overload
214
+ def create_engine(
215
+ drivername: str,
216
+ /,
217
+ *,
218
+ username: str | None = None,
219
+ password: str | None = None,
220
+ host: str | None = None,
221
+ port: int | None = None,
222
+ database: str | None = None,
223
+ query: StrMapping | None = None,
224
+ poolclass: type[Pool] | None = NullPool,
225
+ async_: Literal[True],
226
+ ) -> AsyncEngine: ...
227
+ @overload
228
+ def create_engine(
229
+ drivername: str,
230
+ /,
231
+ *,
232
+ username: str | None = None,
233
+ password: str | None = None,
234
+ host: str | None = None,
235
+ port: int | None = None,
236
+ database: str | None = None,
237
+ query: StrMapping | None = None,
238
+ poolclass: type[Pool] | None = NullPool,
239
+ async_: Literal[False] = False,
240
+ ) -> Engine: ...
241
+ @overload
242
+ def create_engine(
243
+ drivername: str,
244
+ /,
245
+ *,
246
+ username: str | None = None,
247
+ password: str | None = None,
248
+ host: str | None = None,
249
+ port: int | None = None,
250
+ database: str | None = None,
251
+ query: StrMapping | None = None,
252
+ poolclass: type[Pool] | None = NullPool,
253
+ async_: bool = False,
254
+ ) -> Engine | AsyncEngine: ...
255
+ def create_engine(
191
256
  drivername: str,
192
257
  /,
193
258
  *,
@@ -198,7 +263,8 @@ def create_async_engine(
198
263
  database: str | None = None,
199
264
  query: StrMapping | None = None,
200
265
  poolclass: type[Pool] | None = NullPool,
201
- ) -> AsyncEngine:
266
+ async_: bool = False,
267
+ ) -> Engine | AsyncEngine:
202
268
  """Create a SQLAlchemy engine."""
203
269
  if query is None:
204
270
  kwargs = {}
@@ -217,7 +283,13 @@ def create_async_engine(
217
283
  database=database,
218
284
  **kwargs,
219
285
  )
220
- return _create_async_engine(url, poolclass=poolclass)
286
+ match async_:
287
+ case False:
288
+ return sqlalchemy.create_engine(url, poolclass=poolclass)
289
+ case True:
290
+ return sqlalchemy.ext.asyncio.create_async_engine(url, poolclass=poolclass)
291
+ case _ as never:
292
+ assert_never(never)
221
293
 
222
294
 
223
295
  ##
@@ -825,7 +897,7 @@ def _get_dialect(engine_or_conn: EngineOrConnectionOrAsync, /) -> Dialect:
825
897
  if isinstance(dialect, oracle_dialect): # pragma: no cover
826
898
  return "oracle"
827
899
  if isinstance( # skipif-ci-and-not-linux
828
- dialect, postgresql_dialect | PGDialect_asyncpg
900
+ dialect, (postgresql_dialect, PGDialect_asyncpg, PGDialect_psycopg)
829
901
  ):
830
902
  return "postgresql"
831
903
  if isinstance(dialect, sqlite_dialect):
@@ -1107,10 +1179,11 @@ __all__ = [
1107
1179
  "InsertItemsError",
1108
1180
  "TablenameMixin",
1109
1181
  "UpsertItemsError",
1182
+ "check_connect",
1110
1183
  "check_engine",
1111
1184
  "columnwise_max",
1112
1185
  "columnwise_min",
1113
- "create_async_engine",
1186
+ "create_engine",
1114
1187
  "ensure_tables_created",
1115
1188
  "ensure_tables_dropped",
1116
1189
  "enum_name",