dycw-utilities 0.149.10__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.
- {dycw_utilities-0.149.10.dist-info → dycw_utilities-0.150.0.dist-info}/METADATA +1 -1
- {dycw_utilities-0.149.10.dist-info → dycw_utilities-0.150.0.dist-info}/RECORD +8 -8
- utilities/__init__.py +1 -1
- utilities/pottery.py +9 -1
- utilities/sqlalchemy.py +81 -8
- {dycw_utilities-0.149.10.dist-info → dycw_utilities-0.150.0.dist-info}/WHEEL +0 -0
- {dycw_utilities-0.149.10.dist-info → dycw_utilities-0.150.0.dist-info}/entry_points.txt +0 -0
- {dycw_utilities-0.149.10.dist-info → dycw_utilities-0.150.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
utilities/__init__.py,sha256
|
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
|
@@ -50,7 +50,7 @@ utilities/platform.py,sha256=Ue9LSxYvg9yUXGKuz5aZoy_qkUEXde-v6B09exgSctU,2813
|
|
50
50
|
utilities/polars.py,sha256=BgiDryAVOapi41ddfJqN0wYh_sDj8BNEYtPB36LaHdo,71824
|
51
51
|
utilities/polars_ols.py,sha256=Uc9V5kvlWZ5cU93lKZ-cfAKdVFFw81tqwLW9PxtUvMs,5618
|
52
52
|
utilities/postgres.py,sha256=C3TxpQymM7S5ZivxIN_AFTM5g5TtENptzx8-XYf7pow,12182
|
53
|
-
utilities/pottery.py,sha256=
|
53
|
+
utilities/pottery.py,sha256=u0uvyGgYyujxftEMlsv6ppYTKQoVVjHt5jnVxxYz9s4,6596
|
54
54
|
utilities/pqdm.py,sha256=BTsYPtbKQWwX-iXF4qCkfPG7DPxIB54J989n83bXrIo,3092
|
55
55
|
utilities/psutil.py,sha256=KUlu4lrUw9Zg1V7ZGetpWpGb9DB8l_SSDWGbANFNCPU,2104
|
56
56
|
utilities/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -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=
|
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.
|
93
|
-
dycw_utilities-0.
|
94
|
-
dycw_utilities-0.
|
95
|
-
dycw_utilities-0.
|
96
|
-
dycw_utilities-0.
|
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
utilities/pottery.py
CHANGED
@@ -12,12 +12,14 @@ from redis.asyncio import Redis
|
|
12
12
|
|
13
13
|
from utilities.asyncio import loop_until_succeed, sleep_td, timeout_td
|
14
14
|
from utilities.contextlib import enhanced_async_context_manager
|
15
|
+
from utilities.contextvars import yield_set_context
|
15
16
|
from utilities.iterables import always_iterable
|
16
17
|
from utilities.logging import get_logger
|
17
18
|
from utilities.whenever import MILLISECOND, SECOND, to_seconds
|
18
19
|
|
19
20
|
if TYPE_CHECKING:
|
20
21
|
from collections.abc import AsyncIterator, Callable, Iterable
|
22
|
+
from contextvars import ContextVar
|
21
23
|
|
22
24
|
from whenever import Delta
|
23
25
|
|
@@ -57,6 +59,7 @@ async def try_yield_coroutine_looper(
|
|
57
59
|
throttle: Delta | None = None,
|
58
60
|
logger: LoggerOrName | None = None,
|
59
61
|
sleep_error: Delta | None = None,
|
62
|
+
context: ContextVar[bool] | None = None,
|
60
63
|
) -> AsyncIterator[CoroutineLooper | None]:
|
61
64
|
"""Try acquire access to a coroutine looper."""
|
62
65
|
try: # skipif-ci-and-not-linux
|
@@ -70,7 +73,12 @@ async def try_yield_coroutine_looper(
|
|
70
73
|
sleep=sleep_acquire,
|
71
74
|
throttle=throttle,
|
72
75
|
) as lock:
|
73
|
-
|
76
|
+
looper = CoroutineLooper(lock=lock, logger=logger, sleep=sleep_error)
|
77
|
+
if context is None:
|
78
|
+
yield looper
|
79
|
+
else:
|
80
|
+
with yield_set_context(context):
|
81
|
+
yield looper
|
74
82
|
except _YieldAccessUnableToAcquireLockError as error: # skipif-ci-and-not-linux
|
75
83
|
if logger is not None:
|
76
84
|
get_logger(logger=logger).info("%s", error)
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
"
|
1186
|
+
"create_engine",
|
1114
1187
|
"ensure_tables_created",
|
1115
1188
|
"ensure_tables_dropped",
|
1116
1189
|
"enum_name",
|
File without changes
|
File without changes
|
File without changes
|