sotkalib 0.0.2__py3-none-any.whl → 0.0.4__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.
- sotkalib/__init__.py +2 -4
- sotkalib/config/field.py +0 -16
- sotkalib/config/struct.py +121 -121
- sotkalib/enum/__init__.py +3 -0
- sotkalib/enum/mixins.py +59 -0
- sotkalib/exceptions/__init__.py +3 -0
- sotkalib/exceptions/api/__init__.py +1 -0
- sotkalib/exceptions/api/exc.py +53 -0
- sotkalib/exceptions/handlers/__init__.py +4 -0
- sotkalib/exceptions/handlers/args_incl_error.py +15 -0
- sotkalib/exceptions/handlers/core.py +33 -0
- sotkalib/http/__init__.py +12 -12
- sotkalib/http/client_session.py +217 -206
- sotkalib/log/factory.py +1 -18
- sotkalib/redis/__init__.py +8 -0
- sotkalib/redis/client.py +38 -0
- sotkalib/redis/lock.py +82 -0
- sotkalib/sqla/__init__.py +3 -0
- sotkalib/sqla/db.py +101 -0
- {sotkalib-0.0.2.dist-info → sotkalib-0.0.4.dist-info}/METADATA +3 -1
- sotkalib-0.0.4.dist-info/RECORD +25 -0
- {sotkalib-0.0.2.dist-info → sotkalib-0.0.4.dist-info}/WHEEL +1 -1
- sotkalib-0.0.2.dist-info/RECORD +0 -12
sotkalib/sqla/db.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from sqlalchemy import Engine, create_engine
|
|
3
|
+
from sqlalchemy.ext.asyncio import AsyncEngine, async_sessionmaker, create_async_engine
|
|
4
|
+
from sqlalchemy.ext.asyncio.session import AsyncSession
|
|
5
|
+
from sqlalchemy.orm import Session, sessionmaker
|
|
6
|
+
|
|
7
|
+
from sotkalib.log import get_logger
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ConnectionTimeoutError(Exception): pass
|
|
11
|
+
|
|
12
|
+
class DatabaseSettings(BaseModel):
|
|
13
|
+
uri: str = Field(examples=[
|
|
14
|
+
"postgresql://username:password@localhost:5432/database"
|
|
15
|
+
])
|
|
16
|
+
async_driver: str = "asyncpg"
|
|
17
|
+
echo: bool = False
|
|
18
|
+
pool_size: int = 10
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def async_uri(self) -> str:
|
|
22
|
+
return self.uri.replace("postgresql://", "postgresql" + self.async_driver + "://")
|
|
23
|
+
|
|
24
|
+
class Database:
|
|
25
|
+
_sync_engine: Engine | None
|
|
26
|
+
_async_engine: AsyncEngine | None
|
|
27
|
+
_sync_session_factory: sessionmaker = None
|
|
28
|
+
_async_session_factory: async_sessionmaker = None
|
|
29
|
+
|
|
30
|
+
logger = get_logger("sqldb.instance")
|
|
31
|
+
|
|
32
|
+
def __init__(self, settings: DatabaseSettings):
|
|
33
|
+
self.__async_uri = settings.async_uri
|
|
34
|
+
self.__sync_uri = settings.uri
|
|
35
|
+
self.echo = settings.echo
|
|
36
|
+
self.pool_size = settings.pool_size
|
|
37
|
+
|
|
38
|
+
def __enter__(self):
|
|
39
|
+
return self
|
|
40
|
+
|
|
41
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
42
|
+
if self._sync_engine:
|
|
43
|
+
self._sync_engine.dispose()
|
|
44
|
+
self.logger.info("closed sync db connection")
|
|
45
|
+
|
|
46
|
+
async def __aenter__(self):
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
async def __aexit__(self, *args):
|
|
50
|
+
if self._async_engine:
|
|
51
|
+
await self._async_engine.dispose()
|
|
52
|
+
self.logger.info("closed async db connection")
|
|
53
|
+
|
|
54
|
+
def __async_init(self):
|
|
55
|
+
self._async_engine = create_async_engine(
|
|
56
|
+
url=self.__async_uri,
|
|
57
|
+
echo=self.echo,
|
|
58
|
+
pool_size=self.pool_size,
|
|
59
|
+
)
|
|
60
|
+
self._async_session_factory = async_sessionmaker(bind=self._async_engine, expire_on_commit=False)
|
|
61
|
+
self.logger.debug( # noqa: PLE1205
|
|
62
|
+
"successfully initialized async db connection, engine.status = {} sessionmaker.status = {}",
|
|
63
|
+
self._async_engine.name is not None,
|
|
64
|
+
self._async_session_factory is not None,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def async_session(self) -> async_sessionmaker[AsyncSession]:
|
|
69
|
+
if self._async_engine is None or self._async_session_factory is None:
|
|
70
|
+
self.logger.debug("async_sf not found, initializing")
|
|
71
|
+
self.__async_init()
|
|
72
|
+
if self._async_engine is None or self._async_session_factory is None:
|
|
73
|
+
self.logger.error(c := "could not asynchronously connect to pgsql")
|
|
74
|
+
raise ConnectionTimeoutError(c)
|
|
75
|
+
self.logger.debug("success getting (asyncmaker)")
|
|
76
|
+
return self._async_session_factory
|
|
77
|
+
|
|
78
|
+
def __sync_init(self):
|
|
79
|
+
self._sync_engine = create_engine(
|
|
80
|
+
url=self.__sync_uri,
|
|
81
|
+
echo=self.echo,
|
|
82
|
+
pool_size=self.pool_size,
|
|
83
|
+
)
|
|
84
|
+
self._sync_session_factory = sessionmaker(bind=self._sync_engine, expire_on_commit=False)
|
|
85
|
+
self.logger.debug( # noqa
|
|
86
|
+
" -> (__sync_init) successfully initialized sync db connection,\n"
|
|
87
|
+
"\t\t\t\tengine.status = {} sessionmaker.status = {}",
|
|
88
|
+
self._sync_engine.name is not None,
|
|
89
|
+
self._sync_session_factory is not None,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def session(self) -> sessionmaker[Session]:
|
|
94
|
+
if self._sync_engine is None or self._sync_session_factory is None:
|
|
95
|
+
self.logger.debug("not found, initializing...")
|
|
96
|
+
self.__sync_init()
|
|
97
|
+
if self._sync_engine is None or self._sync_session_factory is None:
|
|
98
|
+
self.logger.error(c := "could not synchronously connect to pgsql")
|
|
99
|
+
raise ConnectionTimeoutError(c)
|
|
100
|
+
self.logger.debug("success getting (syncmaker)")
|
|
101
|
+
return self._sync_session_factory
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sotkalib
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary:
|
|
5
5
|
Author: alexey
|
|
6
6
|
Author-email: alexey <me@pyrorhythm.dev>
|
|
@@ -8,6 +8,8 @@ Requires-Dist: aiohttp>=3.13.3
|
|
|
8
8
|
Requires-Dist: dotenv>=0.9.9
|
|
9
9
|
Requires-Dist: loguru>=0.7.3
|
|
10
10
|
Requires-Dist: pydantic>=2.12.5
|
|
11
|
+
Requires-Dist: redis>=7.1.0
|
|
12
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.46
|
|
11
13
|
Requires-Python: >=3.13
|
|
12
14
|
Description-Content-Type: text/markdown
|
|
13
15
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
sotkalib/__init__.py,sha256=t3dEAlrtHABFRZdF7RM5K2N1fDUTVwUPmBPG4jFdvSY,138
|
|
2
|
+
sotkalib/config/__init__.py,sha256=CSjn02NCnBPO14QOg4OzKI-lTxyKoBxQ4ODsiWamlIM,102
|
|
3
|
+
sotkalib/config/field.py,sha256=596_6DLnUIMN86h2uob9YN5IrHnc7fguWScSbIYsTH4,326
|
|
4
|
+
sotkalib/config/struct.py,sha256=gv1jFrSRytMC6bZTUDOUQf00Zo1iKxQvuTxGv9qnyHI,5679
|
|
5
|
+
sotkalib/enum/__init__.py,sha256=pKpLPm8fqHO4Et21TWIybIPRiehN1KrmxcBh6hPRsxM,127
|
|
6
|
+
sotkalib/enum/mixins.py,sha256=rgXb0eXaBSozrviOMJo1671x4DiN9SELtw3-x6PvhDM,1821
|
|
7
|
+
sotkalib/exceptions/__init__.py,sha256=H2h-yW1o0_X1Z9O-hWgj6h2spFxpzJJQ_N2ITMr600A,58
|
|
8
|
+
sotkalib/exceptions/api/__init__.py,sha256=tIFOiRlbPkgCRNv5OPZ1M98nRnAMkFIuqSK7dZpKMRI,38
|
|
9
|
+
sotkalib/exceptions/api/exc.py,sha256=gqx4GrHXUvKcR7tEmJpRqPbDWOT2AgKoyck8-FovQCc,1329
|
|
10
|
+
sotkalib/exceptions/handlers/__init__.py,sha256=rA6o6_LVa-0TToyPhT1vB_Lz2E0U8EUfHICAYgAUd78,178
|
|
11
|
+
sotkalib/exceptions/handlers/args_incl_error.py,sha256=DB8TMhZdSkwZwEahOJ99zXWknqBTkSC4IKZsZ5psxdg,535
|
|
12
|
+
sotkalib/exceptions/handlers/core.py,sha256=5fhusoxBhUz59TaVWobplBvD-sbkZKBnmmu-fcSyRk4,836
|
|
13
|
+
sotkalib/http/__init__.py,sha256=HxOuGbHbz39MD0ICjOSh4zv-nGPZca9TgxP4rCceamw,241
|
|
14
|
+
sotkalib/http/client_session.py,sha256=OtGTpwr8I7tsgOxRGS8c7tby5sGT_T6B0Zc8HTC9Sxs,8838
|
|
15
|
+
sotkalib/log/__init__.py,sha256=xrBx--c8QU5xkb3_n61LuqF8ySUaxlQkHCxHyH_D8aE,58
|
|
16
|
+
sotkalib/log/factory.py,sha256=Wl8qY2-vimpctRlRYSWPLjC0KgeEGgSSuDDJaxWtvK8,309
|
|
17
|
+
sotkalib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
sotkalib/redis/__init__.py,sha256=wv3AIRw3aXXLgTTrt6my8C8jSBl4-R3dWRfGLbGTHng,167
|
|
19
|
+
sotkalib/redis/client.py,sha256=0TWe-gYqFiuCjqimCQrVrnTHSM0EROIoJL36M3qwOtQ,1118
|
|
20
|
+
sotkalib/redis/lock.py,sha256=nEZjIyXmgq3vH-Urs8qXC_N8lmXNho00SaTZ7wJIEIo,2528
|
|
21
|
+
sotkalib/sqla/__init__.py,sha256=fYT8O-bPcdXxJ3QVu3KbypwbZ_hpm8Eq1CuQgjvyNJ8,86
|
|
22
|
+
sotkalib/sqla/db.py,sha256=lxE6XLgX-CowyhfRwTAA_FGJybiihaGWWzlNe8M41CE,3866
|
|
23
|
+
sotkalib-0.0.4.dist-info/WHEEL,sha256=5DEXXimM34_d4Gx1AuF9ysMr1_maoEtGKjaILM3s4w4,80
|
|
24
|
+
sotkalib-0.0.4.dist-info/METADATA,sha256=4OxxOFpmiDXvjlOjQveYAlGtkXS1P8WXNZz0jchKDVY,380
|
|
25
|
+
sotkalib-0.0.4.dist-info/RECORD,,
|
sotkalib-0.0.2.dist-info/RECORD
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
sotkalib/__init__.py,sha256=ebrSgK8GtSh2aZNdP3vKA6A4b1iHLFNWzpgznyOOn8Q,48
|
|
2
|
-
sotkalib/config/__init__.py,sha256=CSjn02NCnBPO14QOg4OzKI-lTxyKoBxQ4ODsiWamlIM,102
|
|
3
|
-
sotkalib/config/field.py,sha256=UaIiZBa4TUOB-akEqIvFJKxj2QjjsTaAjL2r163N-V4,790
|
|
4
|
-
sotkalib/config/struct.py,sha256=kUabPNOv9uA8d0SzBOfr-w08YOYKy-D8LN0sof_ZQ5Q,6453
|
|
5
|
-
sotkalib/http/__init__.py,sha256=gkuf1ZM7qXRmnm-yDUMmxxbCuu7bLek_PL3UmMQBtlM,317
|
|
6
|
-
sotkalib/http/client_session.py,sha256=9AyOLFQFXf_lkirJcfp0NBIzx5owdRtDJZM-PEcCKtI,8952
|
|
7
|
-
sotkalib/log/__init__.py,sha256=xrBx--c8QU5xkb3_n61LuqF8ySUaxlQkHCxHyH_D8aE,58
|
|
8
|
-
sotkalib/log/factory.py,sha256=N8SZNvCdBLmsM0ES38x2BxZbJD1GgdMHtJ8h8lZjv7A,806
|
|
9
|
-
sotkalib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
sotkalib-0.0.2.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
|
|
11
|
-
sotkalib-0.0.2.dist-info/METADATA,sha256=TOF1FK1cVfMXt1kXc4gVjFsFsGj8hi5uMdQkude7sMQ,309
|
|
12
|
-
sotkalib-0.0.2.dist-info/RECORD,,
|