ddcdatabases 4.0.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.
@@ -0,0 +1,200 @@
1
+ # ddcdatabases Environment Variables Example
2
+ # Copy this file to .env and adjust values as needed
3
+
4
+ # SQLite Database Settings
5
+ SQLITE_FILE_PATH=sqlite.db
6
+ SQLITE_ECHO=false
7
+ # Connection Retry settings
8
+ SQLITE_CONNECTION_ENABLE_RETRY=false
9
+ SQLITE_CONNECTION_MAX_RETRIES=1
10
+ SQLITE_CONNECTION_INITIAL_RETRY_DELAY=1.0
11
+ SQLITE_CONNECTION_MAX_RETRY_DELAY=30.0
12
+ # Operation Retry settings
13
+ SQLITE_OPERATION_ENABLE_RETRY=false
14
+ SQLITE_OPERATION_MAX_RETRIES=1
15
+ SQLITE_OPERATION_INITIAL_RETRY_DELAY=0.5
16
+ SQLITE_OPERATION_MAX_RETRY_DELAY=10.0
17
+ SQLITE_OPERATION_JITTER=0.1
18
+
19
+ # PostgreSQL Database Settings
20
+ POSTGRESQL_HOST=localhost
21
+ POSTGRESQL_PORT=5432
22
+ POSTGRESQL_USER=postgres
23
+ POSTGRESQL_PASSWORD=password
24
+ POSTGRESQL_DATABASE=postgres
25
+ # Comma-separated for multiple schemas (e.g. public,schema2)
26
+ POSTGRESQL_SCHEMA=public
27
+ # Session settings
28
+ POSTGRESQL_ECHO=false
29
+ POSTGRESQL_AUTOFLUSH=false
30
+ POSTGRESQL_EXPIRE_ON_COMMIT=false
31
+ POSTGRESQL_AUTOCOMMIT=false
32
+ # Pool settings
33
+ POSTGRESQL_CONNECTION_TIMEOUT=30
34
+ POSTGRESQL_POOL_RECYCLE=3600
35
+ POSTGRESQL_POOL_SIZE=25
36
+ POSTGRESQL_MAX_OVERFLOW=50
37
+ # SSL settings
38
+ POSTGRESQL_SSL_MODE=disable
39
+ POSTGRESQL_SSL_CA_CERT_PATH=
40
+ POSTGRESQL_SSL_CLIENT_CERT_PATH=
41
+ POSTGRESQL_SSL_CLIENT_KEY_PATH=
42
+ # Connection Retry settings
43
+ POSTGRESQL_CONNECTION_ENABLE_RETRY=true
44
+ POSTGRESQL_CONNECTION_MAX_RETRIES=3
45
+ POSTGRESQL_CONNECTION_INITIAL_RETRY_DELAY=1.0
46
+ POSTGRESQL_CONNECTION_MAX_RETRY_DELAY=30.0
47
+ POSTGRESQL_CONNECTION_DISCONNECT_IDLE_TIMEOUT=300
48
+ # Operation Retry settings
49
+ POSTGRESQL_OPERATION_ENABLE_RETRY=true
50
+ POSTGRESQL_OPERATION_MAX_RETRIES=3
51
+ POSTGRESQL_OPERATION_INITIAL_RETRY_DELAY=0.5
52
+ POSTGRESQL_OPERATION_MAX_RETRY_DELAY=10.0
53
+ POSTGRESQL_OPERATION_JITTER=0.1
54
+ # Persistent connection settings
55
+ POSTGRESQL_PERSISTENT_IDLE_TIMEOUT=300
56
+ POSTGRESQL_PERSISTENT_HEALTH_CHECK_INTERVAL=30
57
+ POSTGRESQL_PERSISTENT_AUTO_RECONNECT=true
58
+
59
+ # Microsoft SQL Server Database Settings
60
+ MSSQL_HOST=localhost
61
+ MSSQL_PORT=1433
62
+ MSSQL_USER=sa
63
+ MSSQL_PASSWORD=password
64
+ MSSQL_DATABASE=master
65
+ MSSQL_SCHEMA=dbo
66
+ # Session settings
67
+ MSSQL_ECHO=false
68
+ MSSQL_AUTOFLUSH=false
69
+ MSSQL_EXPIRE_ON_COMMIT=false
70
+ MSSQL_AUTOCOMMIT=false
71
+ # Pool settings
72
+ MSSQL_CONNECTION_TIMEOUT=30
73
+ MSSQL_POOL_RECYCLE=3600
74
+ MSSQL_POOL_SIZE=25
75
+ MSSQL_MAX_OVERFLOW=50
76
+ MSSQL_ODBCDRIVER_VERSION=18
77
+ # SSL settings
78
+ MSSQL_SSL_ENCRYPT=false
79
+ MSSQL_SSL_TRUST_SERVER_CERTIFICATE=true
80
+ MSSQL_SSL_CA_CERT_PATH=
81
+ # Connection Retry settings
82
+ MSSQL_CONNECTION_ENABLE_RETRY=true
83
+ MSSQL_CONNECTION_MAX_RETRIES=3
84
+ MSSQL_CONNECTION_INITIAL_RETRY_DELAY=1.0
85
+ MSSQL_CONNECTION_MAX_RETRY_DELAY=30.0
86
+ MSSQL_CONNECTION_DISCONNECT_IDLE_TIMEOUT=300
87
+ # Operation Retry settings
88
+ MSSQL_OPERATION_ENABLE_RETRY=true
89
+ MSSQL_OPERATION_MAX_RETRIES=3
90
+ MSSQL_OPERATION_INITIAL_RETRY_DELAY=0.5
91
+ MSSQL_OPERATION_MAX_RETRY_DELAY=10.0
92
+ MSSQL_OPERATION_JITTER=0.1
93
+ # Persistent connection settings
94
+ MSSQL_PERSISTENT_IDLE_TIMEOUT=300
95
+ MSSQL_PERSISTENT_HEALTH_CHECK_INTERVAL=30
96
+ MSSQL_PERSISTENT_AUTO_RECONNECT=true
97
+
98
+ # MySQL Database Settings
99
+ MYSQL_HOST=localhost
100
+ MYSQL_PORT=3306
101
+ MYSQL_USER=root
102
+ MYSQL_PASSWORD=password
103
+ MYSQL_DATABASE=dev
104
+ # Session settings
105
+ MYSQL_ECHO=false
106
+ MYSQL_AUTOFLUSH=false
107
+ MYSQL_EXPIRE_ON_COMMIT=false
108
+ MYSQL_AUTOCOMMIT=true
109
+ # Pool settings
110
+ MYSQL_CONNECTION_TIMEOUT=30
111
+ MYSQL_POOL_RECYCLE=3600
112
+ MYSQL_POOL_SIZE=10
113
+ MYSQL_MAX_OVERFLOW=20
114
+ # SSL settings
115
+ MYSQL_SSL_MODE=DISABLED
116
+ MYSQL_SSL_CA_CERT_PATH=
117
+ MYSQL_SSL_CLIENT_CERT_PATH=
118
+ MYSQL_SSL_CLIENT_KEY_PATH=
119
+ # Connection Retry settings
120
+ MYSQL_CONNECTION_ENABLE_RETRY=true
121
+ MYSQL_CONNECTION_MAX_RETRIES=3
122
+ MYSQL_CONNECTION_INITIAL_RETRY_DELAY=1.0
123
+ MYSQL_CONNECTION_MAX_RETRY_DELAY=30.0
124
+ MYSQL_CONNECTION_DISCONNECT_IDLE_TIMEOUT=300
125
+ # Operation Retry settings
126
+ MYSQL_OPERATION_ENABLE_RETRY=true
127
+ MYSQL_OPERATION_MAX_RETRIES=3
128
+ MYSQL_OPERATION_INITIAL_RETRY_DELAY=0.5
129
+ MYSQL_OPERATION_MAX_RETRY_DELAY=10.0
130
+ MYSQL_OPERATION_JITTER=0.1
131
+ # Persistent connection settings
132
+ MYSQL_PERSISTENT_IDLE_TIMEOUT=300
133
+ MYSQL_PERSISTENT_HEALTH_CHECK_INTERVAL=30
134
+ MYSQL_PERSISTENT_AUTO_RECONNECT=true
135
+
136
+ # Oracle Database Settings
137
+ ORACLE_HOST=localhost
138
+ ORACLE_PORT=1521
139
+ ORACLE_USER=system
140
+ ORACLE_PASSWORD=oracle
141
+ ORACLE_SERVICENAME=xe
142
+ # Session settings
143
+ ORACLE_ECHO=false
144
+ ORACLE_AUTOFLUSH=false
145
+ ORACLE_EXPIRE_ON_COMMIT=false
146
+ ORACLE_AUTOCOMMIT=false
147
+ # Pool settings
148
+ ORACLE_CONNECTION_TIMEOUT=30
149
+ ORACLE_POOL_RECYCLE=3600
150
+ ORACLE_POOL_SIZE=10
151
+ ORACLE_MAX_OVERFLOW=20
152
+ # SSL settings
153
+ ORACLE_SSL_ENABLED=false
154
+ ORACLE_SSL_WALLET_PATH=
155
+ # Connection Retry settings
156
+ ORACLE_CONNECTION_ENABLE_RETRY=true
157
+ ORACLE_CONNECTION_MAX_RETRIES=3
158
+ ORACLE_CONNECTION_INITIAL_RETRY_DELAY=1.0
159
+ ORACLE_CONNECTION_MAX_RETRY_DELAY=30.0
160
+ ORACLE_CONNECTION_DISCONNECT_IDLE_TIMEOUT=300
161
+ # Operation Retry settings
162
+ ORACLE_OPERATION_ENABLE_RETRY=true
163
+ ORACLE_OPERATION_MAX_RETRIES=3
164
+ ORACLE_OPERATION_INITIAL_RETRY_DELAY=0.5
165
+ ORACLE_OPERATION_MAX_RETRY_DELAY=10.0
166
+ ORACLE_OPERATION_JITTER=0.1
167
+ # Persistent connection settings
168
+ ORACLE_PERSISTENT_IDLE_TIMEOUT=300
169
+ ORACLE_PERSISTENT_HEALTH_CHECK_INTERVAL=30
170
+ ORACLE_PERSISTENT_AUTO_RECONNECT=true
171
+
172
+ # MongoDB Database Settings
173
+ MONGODB_HOST=localhost
174
+ MONGODB_PORT=27017
175
+ MONGODB_USER=admin
176
+ MONGODB_PASSWORD=admin
177
+ MONGODB_DATABASE=admin
178
+ MONGODB_BATCH_SIZE=2865
179
+ MONGODB_LIMIT=0
180
+ # TLS settings
181
+ MONGODB_TLS_ENABLED=false
182
+ MONGODB_TLS_CA_CERT_PATH=
183
+ MONGODB_TLS_CERT_KEY_PATH=
184
+ MONGODB_TLS_ALLOW_INVALID_CERTIFICATES=false
185
+ # Connection Retry settings
186
+ MONGODB_CONNECTION_ENABLE_RETRY=true
187
+ MONGODB_CONNECTION_MAX_RETRIES=3
188
+ MONGODB_CONNECTION_INITIAL_RETRY_DELAY=1.0
189
+ MONGODB_CONNECTION_MAX_RETRY_DELAY=30.0
190
+ MONGODB_CONNECTION_DISCONNECT_IDLE_TIMEOUT=300
191
+ # Operation Retry settings
192
+ MONGODB_OPERATION_ENABLE_RETRY=true
193
+ MONGODB_OPERATION_MAX_RETRIES=3
194
+ MONGODB_OPERATION_INITIAL_RETRY_DELAY=0.5
195
+ MONGODB_OPERATION_MAX_RETRY_DELAY=10.0
196
+ MONGODB_OPERATION_JITTER=0.1
197
+ # Persistent connection settings
198
+ MONGODB_PERSISTENT_IDLE_TIMEOUT=300
199
+ MONGODB_PERSISTENT_HEALTH_CHECK_INTERVAL=30
200
+ MONGODB_PERSISTENT_AUTO_RECONNECT=true
@@ -0,0 +1,203 @@
1
+ import logging
2
+ from .core.operations import DBUtils, DBUtilsAsync
3
+ from .core.persistent import PersistentConnectionConfig, close_all_persistent_connections
4
+ from importlib.metadata import version
5
+
6
+ __all__ = [
7
+ "DBUtils",
8
+ "DBUtilsAsync",
9
+ "PersistentConnectionConfig",
10
+ "close_all_persistent_connections",
11
+ ]
12
+
13
+ # Conditional imports based on available dependencies
14
+ try:
15
+ from .core.settings import clear_sqlite_settings_cache, get_sqlite_settings
16
+ from .sqlite import (
17
+ Sqlite,
18
+ SqliteConnectionRetryConfig,
19
+ SqliteOperationRetryConfig,
20
+ SqliteSessionConfig,
21
+ )
22
+
23
+ __all__ += [
24
+ "Sqlite",
25
+ "SqliteConnectionRetryConfig",
26
+ "SqliteOperationRetryConfig",
27
+ "SqliteSessionConfig",
28
+ "clear_sqlite_settings_cache",
29
+ "get_sqlite_settings",
30
+ ]
31
+ except ImportError:
32
+ pass
33
+
34
+ try:
35
+ from .core.persistent import MongoDBPersistent
36
+ from .core.settings import clear_mongodb_settings_cache, get_mongodb_settings
37
+ from .mongodb import (
38
+ MongoDB,
39
+ MongoDBConnectionConfig,
40
+ MongoDBConnectionRetryConfig,
41
+ MongoDBOperationRetryConfig,
42
+ MongoDBQueryConfig,
43
+ MongoDBTLSConfig,
44
+ )
45
+
46
+ __all__ += [
47
+ "MongoDB",
48
+ "MongoDBConnectionConfig",
49
+ "MongoDBConnectionRetryConfig",
50
+ "MongoDBOperationRetryConfig",
51
+ "MongoDBPersistent",
52
+ "MongoDBQueryConfig",
53
+ "MongoDBTLSConfig",
54
+ "clear_mongodb_settings_cache",
55
+ "get_mongodb_settings",
56
+ ]
57
+ except ImportError:
58
+ pass
59
+
60
+ try:
61
+ from .core.persistent import MSSQLPersistent
62
+ from .core.settings import clear_mssql_settings_cache, get_mssql_settings
63
+ from .mssql import (
64
+ MSSQL,
65
+ MSSQLConnectionConfig,
66
+ MSSQLConnectionRetryConfig,
67
+ MSSQLOperationRetryConfig,
68
+ MSSQLPoolConfig,
69
+ MSSQLSessionConfig,
70
+ MSSQLSSLConfig,
71
+ )
72
+
73
+ __all__ += [
74
+ "MSSQL",
75
+ "MSSQLConnectionConfig",
76
+ "MSSQLConnectionRetryConfig",
77
+ "MSSQLOperationRetryConfig",
78
+ "MSSQLPersistent",
79
+ "MSSQLPoolConfig",
80
+ "MSSQLSessionConfig",
81
+ "MSSQLSSLConfig",
82
+ "clear_mssql_settings_cache",
83
+ "get_mssql_settings",
84
+ ]
85
+ except ImportError:
86
+ pass
87
+
88
+ try:
89
+ from .core.persistent import MySQLPersistent
90
+ from .core.settings import clear_mysql_settings_cache, get_mysql_settings
91
+ from .mysql import (
92
+ MySQL,
93
+ MySQLConnectionConfig,
94
+ MySQLConnectionRetryConfig,
95
+ MySQLOperationRetryConfig,
96
+ MySQLPoolConfig,
97
+ MySQLSessionConfig,
98
+ MySQLSSLConfig,
99
+ )
100
+
101
+ # MariaDB aliases (MariaDB is fully compatible with MySQL driver)
102
+ MariaDB = MySQL
103
+ MariaDBConnectionConfig = MySQLConnectionConfig
104
+ MariaDBConnectionRetryConfig = MySQLConnectionRetryConfig
105
+ MariaDBOperationRetryConfig = MySQLOperationRetryConfig
106
+ MariaDBPersistent = MySQLPersistent
107
+ MariaDBPoolConfig = MySQLPoolConfig
108
+ MariaDBSessionConfig = MySQLSessionConfig
109
+ MariaDBSSLConfig = MySQLSSLConfig
110
+ clear_mariadb_settings_cache = clear_mysql_settings_cache
111
+ get_mariadb_settings = get_mysql_settings
112
+
113
+ __all__ += [
114
+ "MySQL",
115
+ "MySQLConnectionConfig",
116
+ "MySQLConnectionRetryConfig",
117
+ "MySQLOperationRetryConfig",
118
+ "MySQLPersistent",
119
+ "MySQLPoolConfig",
120
+ "MySQLSessionConfig",
121
+ "MySQLSSLConfig",
122
+ "clear_mysql_settings_cache",
123
+ "get_mysql_settings",
124
+ # MariaDB aliases
125
+ "MariaDB",
126
+ "MariaDBConnectionConfig",
127
+ "MariaDBConnectionRetryConfig",
128
+ "MariaDBOperationRetryConfig",
129
+ "MariaDBPersistent",
130
+ "MariaDBPoolConfig",
131
+ "MariaDBSessionConfig",
132
+ "MariaDBSSLConfig",
133
+ "clear_mariadb_settings_cache",
134
+ "get_mariadb_settings",
135
+ ]
136
+ except ImportError:
137
+ pass
138
+
139
+ try:
140
+ from .core.persistent import OraclePersistent
141
+ from .core.settings import clear_oracle_settings_cache, get_oracle_settings
142
+ from .oracle import (
143
+ Oracle,
144
+ OracleConnectionConfig,
145
+ OracleConnectionRetryConfig,
146
+ OracleOperationRetryConfig,
147
+ OraclePoolConfig,
148
+ OracleSessionConfig,
149
+ OracleSSLConfig,
150
+ )
151
+
152
+ __all__ += [
153
+ "Oracle",
154
+ "OracleConnectionConfig",
155
+ "OracleConnectionRetryConfig",
156
+ "OracleOperationRetryConfig",
157
+ "OraclePersistent",
158
+ "OraclePoolConfig",
159
+ "OracleSessionConfig",
160
+ "OracleSSLConfig",
161
+ "clear_oracle_settings_cache",
162
+ "get_oracle_settings",
163
+ ]
164
+ except ImportError:
165
+ pass
166
+
167
+ try:
168
+ from .core.persistent import PostgreSQLPersistent
169
+ from .core.settings import clear_postgresql_settings_cache, get_postgresql_settings
170
+ from .postgresql import (
171
+ PostgreSQL,
172
+ PostgreSQLConnectionConfig,
173
+ PostgreSQLConnectionRetryConfig,
174
+ PostgreSQLOperationRetryConfig,
175
+ PostgreSQLPoolConfig,
176
+ PostgreSQLSessionConfig,
177
+ PostgreSQLSSLConfig,
178
+ )
179
+
180
+ __all__ += [
181
+ "PostgreSQL",
182
+ "PostgreSQLConnectionConfig",
183
+ "PostgreSQLConnectionRetryConfig",
184
+ "PostgreSQLOperationRetryConfig",
185
+ "PostgreSQLPersistent",
186
+ "PostgreSQLPoolConfig",
187
+ "PostgreSQLSessionConfig",
188
+ "PostgreSQLSSLConfig",
189
+ "clear_postgresql_settings_cache",
190
+ "get_postgresql_settings",
191
+ ]
192
+ except ImportError:
193
+ pass
194
+
195
+ __all__ = tuple(__all__)
196
+ __title__ = "ddcdatabases"
197
+ __author__ = "Daniel Costa"
198
+ __email__ = "daniel@ddcsoftwares.com"
199
+ __license__ = "MIT"
200
+ __copyright__ = "Copyright 2024-present DDC Softwares"
201
+ __version__ = version(__title__)
202
+
203
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
File without changes
@@ -0,0 +1,192 @@
1
+ from __future__ import annotations
2
+ import logging
3
+ import sqlalchemy as sa
4
+ from .configs import BaseOperationRetryConfig, BaseRetryConfig
5
+ from .retry import retry_operation, retry_operation_async
6
+ from collections.abc import AsyncGenerator, Generator
7
+ from contextlib import asynccontextmanager, contextmanager
8
+ from datetime import datetime
9
+ from sqlalchemy.engine import URL, Engine, create_engine
10
+ from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker, create_async_engine
11
+ from sqlalchemy.orm import Session, sessionmaker
12
+ from typing import Any
13
+
14
+ _logger = logging.getLogger(__name__)
15
+ _logger.addHandler(logging.NullHandler())
16
+
17
+
18
+ class BaseConnection:
19
+ __slots__ = (
20
+ "connection_url",
21
+ "engine_args",
22
+ "autoflush",
23
+ "expire_on_commit",
24
+ "sync_driver",
25
+ "async_driver",
26
+ "session",
27
+ "is_connected",
28
+ "_temp_engine",
29
+ "connection_retry_config",
30
+ "operation_retry_config",
31
+ "logger",
32
+ )
33
+
34
+ def __init__(
35
+ self,
36
+ connection_url: dict,
37
+ engine_args: dict,
38
+ autoflush: bool,
39
+ expire_on_commit: bool,
40
+ sync_driver: str | None,
41
+ async_driver: str | None,
42
+ connection_retry_config: BaseRetryConfig | None = None,
43
+ operation_retry_config: BaseOperationRetryConfig | None = None,
44
+ logger: Any = None,
45
+ ) -> None:
46
+ self.connection_url = connection_url
47
+ self.engine_args = engine_args
48
+ self.autoflush = autoflush
49
+ self.expire_on_commit = expire_on_commit
50
+ self.sync_driver = sync_driver
51
+ self.async_driver = async_driver
52
+ self.session: Session | AsyncSession | None = None
53
+ self.is_connected = False
54
+ self._temp_engine: Engine | AsyncEngine | None = None
55
+ self.connection_retry_config = connection_retry_config or BaseRetryConfig()
56
+ self.operation_retry_config = operation_retry_config or BaseOperationRetryConfig()
57
+ self.logger = logger if logger is not None else _logger
58
+
59
+ def __enter__(self) -> Session:
60
+ def connect() -> Session:
61
+ with self._get_engine() as self._temp_engine:
62
+ session_maker = sessionmaker(
63
+ bind=self._temp_engine,
64
+ class_=Session,
65
+ autoflush=self.autoflush,
66
+ expire_on_commit=self.expire_on_commit,
67
+ )
68
+ with session_maker.begin() as self.session:
69
+ self._test_connection_sync(self.session)
70
+ self.is_connected = True
71
+ return self.session
72
+
73
+ return retry_operation(connect, self.connection_retry_config, "sync_connect", logger=self.logger)
74
+
75
+ def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any) -> None:
76
+ if self.session:
77
+ self.session.close()
78
+ if self._temp_engine:
79
+ self._temp_engine.dispose()
80
+ self.is_connected = False
81
+ self.logger.debug("Disconnected")
82
+
83
+ async def __aenter__(self) -> AsyncSession:
84
+ async def connect() -> AsyncSession:
85
+ async with self._get_async_engine() as self._temp_engine:
86
+ session_maker = async_sessionmaker(
87
+ bind=self._temp_engine,
88
+ class_=AsyncSession,
89
+ autoflush=self.autoflush,
90
+ expire_on_commit=self.expire_on_commit,
91
+ )
92
+ async with session_maker.begin() as self.session:
93
+ await self._test_connection_async(self.session)
94
+ self.is_connected = True
95
+ return self.session
96
+
97
+ return await retry_operation_async(connect, self.connection_retry_config, "async_connect", logger=self.logger)
98
+
99
+ async def __aexit__(
100
+ self,
101
+ exc_type: type[BaseException] | None,
102
+ exc_val: BaseException | None,
103
+ exc_tb: Any,
104
+ ) -> None:
105
+ if self.session:
106
+ await self.session.close()
107
+ if self._temp_engine:
108
+ await self._temp_engine.dispose()
109
+ self.is_connected = False
110
+ self.logger.debug("Disconnected")
111
+
112
+ @contextmanager
113
+ def _get_engine(self) -> Generator[Engine, None, None]:
114
+ _connection_url = URL.create(drivername=self.sync_driver, **self.connection_url)
115
+ _engine = create_engine(url=_connection_url, **self.engine_args)
116
+ yield _engine
117
+ _engine.dispose()
118
+
119
+ @asynccontextmanager
120
+ async def _get_async_engine(self) -> AsyncGenerator[AsyncEngine, None]:
121
+ _connection_url = URL.create(drivername=self.async_driver, **self.connection_url)
122
+ _engine = create_async_engine(url=_connection_url, **self.engine_args)
123
+ yield _engine
124
+ await _engine.dispose()
125
+
126
+ def _test_connection_sync(self, session: Session) -> None:
127
+ _connection_url_copy = self.connection_url.copy()
128
+ _connection_url_copy.pop("password", None)
129
+ _connection_url = URL.create(
130
+ **_connection_url_copy,
131
+ drivername=self.sync_driver,
132
+ )
133
+ test_connection = ConnectionTester(
134
+ sync_session=session,
135
+ host_url=_connection_url,
136
+ logger=self.logger,
137
+ )
138
+ test_connection.test_connection_sync()
139
+
140
+ async def _test_connection_async(self, session: AsyncSession) -> None:
141
+ _connection_url_copy = self.connection_url.copy()
142
+ _connection_url_copy.pop("password", None)
143
+ _connection_url = URL.create(
144
+ **_connection_url_copy,
145
+ drivername=self.async_driver,
146
+ )
147
+ test_connection = ConnectionTester(
148
+ async_session=session,
149
+ host_url=_connection_url,
150
+ logger=self.logger,
151
+ )
152
+ await test_connection.test_connection_async()
153
+
154
+
155
+ class ConnectionTester:
156
+ __slots__ = ("sync_session", "async_session", "host_url", "dt", "logger", "failed_msg")
157
+
158
+ def __init__(
159
+ self,
160
+ sync_session: Session | None = None,
161
+ async_session: AsyncSession | None = None,
162
+ host_url: URL | str = "",
163
+ logger: Any = None,
164
+ ) -> None:
165
+ self.sync_session = sync_session
166
+ self.async_session = async_session
167
+ self.host_url = host_url
168
+ self.dt = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
169
+ self.logger = logger if logger is not None else _logger
170
+ self.failed_msg = "Connection to database failed"
171
+
172
+ def test_connection_sync(self) -> bool:
173
+ try:
174
+ query_text = "SELECT 1 FROM dual" if "oracle" in str(self.sync_session.bind.url) else "SELECT 1"
175
+ self.sync_session.execute(sa.text(query_text))
176
+ return True
177
+ except Exception as e:
178
+ self.sync_session.close()
179
+ error_msg = f"[{self.dt}]:[ERROR]:{self.failed_msg} | {self.host_url} | {e!r}"
180
+ self.logger.error(error_msg)
181
+ raise ConnectionRefusedError(f"{self.failed_msg} | {e!r}") from e
182
+
183
+ async def test_connection_async(self) -> bool:
184
+ try:
185
+ query_text = "SELECT 1 FROM dual" if "oracle" in str(self.async_session.bind.url) else "SELECT 1"
186
+ await self.async_session.execute(sa.text(query_text))
187
+ return True
188
+ except Exception as e:
189
+ await self.async_session.close()
190
+ error_msg = f"[{self.dt}]:[ERROR]:{self.failed_msg} | {self.host_url} | {e!r}"
191
+ self.logger.error(error_msg)
192
+ raise ConnectionRefusedError(f"{self.failed_msg} | {e!r}") from e