Skip to content

Commit f90ae37

Browse files
authored
feat: support multi-config (#5)
* feat: support multi-config * chore: bump version
1 parent 72a7710 commit f90ae37

File tree

12 files changed

+295
-193
lines changed

12 files changed

+295
-193
lines changed

examples/basic.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from litestar import Controller, Litestar, Request, get
66

7-
from litestar_oracledb import AsyncDatabaseConfig, AsyncPoolConfig, OracleDatabasePlugin
7+
from litestar_oracledb import AsyncOracleDatabaseConfig, AsyncOraclePoolConfig, OracleDatabasePlugin
88

99
if TYPE_CHECKING:
1010
from oracledb import AsyncConnection
@@ -24,8 +24,8 @@ async def sample_route(self, request: Request, db_connection: AsyncConnection) -
2424

2525

2626
oracledb = OracleDatabasePlugin(
27-
config=AsyncDatabaseConfig(
28-
pool_config=AsyncPoolConfig(user="system", password="super-secret", dsn="localhost:1513/FREEPDB1") # noqa: S106
27+
config=AsyncOracleDatabaseConfig(
28+
pool_config=AsyncOraclePoolConfig(user="system", password="super-secret", dsn="localhost:1513/FREEPDB1") # noqa: S106
2929
)
3030
)
3131
app = Litestar(plugins=[oracledb], route_handlers=[SampleController])

pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ license = { text = "MIT" }
2626
name = "litestar-oracledb"
2727
readme = "README.md"
2828
requires-python = ">=3.8"
29-
version = "0.1.3"
29+
version = "0.2.0"
3030

3131
[project.urls]
3232
Changelog = "https://litestar-org.github.io/litesatr-oracledb/latest/changelog"
@@ -184,7 +184,10 @@ type = "virtual"
184184

185185
# Lint environment
186186
[tool.hatch.envs.lint]
187+
detached = true
187188
extra-dependencies = [
189+
"litestar>=2.0.29",
190+
"oracledb > 2.1",
188191
# tests
189192
"anyio",
190193
"coverage[toml]>=6.2",
@@ -211,7 +214,6 @@ extra-dependencies = [
211214
"sphinx>=7.1.2",
212215
"sphinx-autobuild>=2021.3.14",
213216
"sphinx-copybutton>=0.5.2",
214-
"litestar-sphinx-theme @ git+https://github.com/litestar-org/litestar-sphinx-theme.git",
215217
"sphinx-click>=5.0.1",
216218
"sphinx-toolbox>=3.5.0",
217219
"sphinx-design>=0.5.0",
@@ -232,7 +234,7 @@ fix = [
232234
"pre-commit run --all-files",
233235
]
234236
style = ["echo \"VERSION: `ruff --version`\"", "ruff check {args:.}", "ruff format --check {args:.}"]
235-
typing = ["echo \"VERSION: `mypy --version`\"", "mypy --install-types --non-interactive {args}"]
237+
typing = ["echo \"VERSION: `mypy --version`\"", "mypy --install-types --non-interactive {args:.}"]
236238

237239

238240
#####################

src/litestar_oracledb/__init__.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
from __future__ import annotations
22

3-
from litestar_oracledb.config import AsyncDatabaseConfig, AsyncPoolConfig, SyncDatabaseConfig, SyncPoolConfig
3+
from litestar_oracledb import exceptions
4+
from litestar_oracledb.config import (
5+
AsyncOracleDatabaseConfig,
6+
AsyncOraclePoolConfig,
7+
SyncOracleDatabaseConfig,
8+
SyncOraclePoolConfig,
9+
)
410
from litestar_oracledb.plugin import OracleDatabasePlugin
511

6-
__all__ = ("SyncDatabaseConfig", "AsyncDatabaseConfig", "SyncPoolConfig", "AsyncPoolConfig", "OracleDatabasePlugin")
12+
__all__ = (
13+
"SyncOracleDatabaseConfig",
14+
"AsyncOracleDatabaseConfig",
15+
"SyncOraclePoolConfig",
16+
"AsyncOraclePoolConfig",
17+
"OracleDatabasePlugin",
18+
"exceptions",
19+
)
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
from __future__ import annotations
22

3-
from litestar_oracledb.config._asyncio import AsyncDatabaseConfig, AsyncPoolConfig
4-
from litestar_oracledb.config._common import GenericDatabaseConfig, GenericPoolConfig
5-
from litestar_oracledb.config._sync import SyncDatabaseConfig, SyncPoolConfig
3+
from litestar_oracledb.config._asyncio import AsyncOracleDatabaseConfig, AsyncOraclePoolConfig
4+
from litestar_oracledb.config._common import GenericOracleDatabaseConfig, GenericOraclePoolConfig
5+
from litestar_oracledb.config._sync import SyncOracleDatabaseConfig, SyncOraclePoolConfig
66

77
__all__ = (
8-
"SyncDatabaseConfig",
9-
"SyncPoolConfig",
10-
"AsyncDatabaseConfig",
11-
"AsyncPoolConfig",
12-
"GenericDatabaseConfig",
13-
"GenericPoolConfig",
8+
"SyncOracleDatabaseConfig",
9+
"SyncOraclePoolConfig",
10+
"AsyncOracleDatabaseConfig",
11+
"AsyncOraclePoolConfig",
12+
"GenericOracleDatabaseConfig",
13+
"GenericOraclePoolConfig",
1414
)

src/litestar_oracledb/config/_asyncio.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import TYPE_CHECKING, Optional, cast
66

77
from litestar.constants import HTTP_RESPONSE_START
8+
from litestar.di import Provide
89
from litestar.exceptions import ImproperlyConfiguredException
910
from litestar.utils.dataclass import simple_asdict
1011
from oracledb import create_pool_async as oracledb_create_pool
@@ -15,8 +16,8 @@
1516
from litestar_oracledb.config._common import (
1617
CONNECTION_SCOPE_KEY,
1718
SESSION_TERMINUS_ASGI_EVENTS,
18-
GenericDatabaseConfig,
19-
GenericPoolConfig,
19+
GenericOracleDatabaseConfig,
20+
GenericOraclePoolConfig,
2021
)
2122

2223
if TYPE_CHECKING:
@@ -120,15 +121,15 @@ async def handler(message: Message, scope: Scope) -> None:
120121

121122

122123
@dataclass
123-
class AsyncPoolConfig(GenericPoolConfig[AsyncConnectionPool, AsyncConnection]):
124+
class AsyncOraclePoolConfig(GenericOraclePoolConfig[AsyncConnectionPool, AsyncConnection]):
124125
"""Async Oracle Pool Config"""
125126

126127

127128
@dataclass
128-
class AsyncDatabaseConfig(GenericDatabaseConfig[AsyncConnectionPool, AsyncConnection]):
129+
class AsyncOracleDatabaseConfig(GenericOracleDatabaseConfig[AsyncConnectionPool, AsyncConnection]):
129130
"""Async Oracle database Configuration."""
130131

131-
pool_config: AsyncPoolConfig | None = None
132+
pool_config: AsyncOraclePoolConfig | None = None
132133
"""Oracle Pool configuration"""
133134

134135
def __post_init__(self) -> None:
@@ -168,6 +169,18 @@ def signature_namespace(self) -> dict[str, Any]:
168169
"AsyncConnectionPool": AsyncConnectionPool,
169170
}
170171

172+
@property
173+
def dependencies(self) -> dict[str, Any]:
174+
"""Return the plugin's signature namespace.
175+
176+
Returns:
177+
A string keyed dict of names to be added to the namespace for signature forward reference resolution.
178+
"""
179+
return {
180+
self.pool_dependency_key: Provide(self.provide_pool, sync_to_thread=False),
181+
self.connection_dependency_key: Provide(self.provide_connection),
182+
}
183+
171184
async def create_pool(self) -> AsyncConnectionPool:
172185
"""Return a pool. If none exists yet, create one.
173186
@@ -198,7 +211,7 @@ async def lifespan(
198211
try:
199212
yield
200213
finally:
201-
await db_pool.close()
214+
await db_pool.close(force=True)
202215

203216
async def provide_connection(
204217
self,
@@ -218,7 +231,9 @@ async def provide_connection(
218231
"Optional[AsyncConnection]",
219232
get_scope_state(scope, self.connection_scope_key),
220233
)
221-
if connection is None:
234+
if connection is not None:
235+
yield connection
236+
else:
222237
pool = cast("AsyncConnectionPool", state.get(self.pool_app_state_key))
223238

224239
async with pool.acquire() as connection:

src/litestar_oracledb/config/_common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929

3030
@dataclass
31-
class GenericPoolConfig(Generic[PoolT, ConnectionT]):
31+
class GenericOraclePoolConfig(Generic[PoolT, ConnectionT]):
3232
conn_class: type[ConnectionT] | EmptyType = Empty
3333
dsn: str | EmptyType = Empty
3434
pool: PoolT | EmptyType = Empty
@@ -79,7 +79,7 @@ class GenericPoolConfig(Generic[PoolT, ConnectionT]):
7979

8080

8181
@dataclass
82-
class GenericDatabaseConfig(Generic[PoolT, ConnectionT]):
82+
class GenericOracleDatabaseConfig(Generic[PoolT, ConnectionT]):
8383
"""Oracle database Configuration."""
8484

8585
pool_app_state_key: str = "db_pool"

src/litestar_oracledb/config/_sync.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import TYPE_CHECKING, Generator, Optional, cast
66

77
from litestar.constants import HTTP_RESPONSE_START
8+
from litestar.di import Provide
89
from litestar.exceptions import ImproperlyConfiguredException
910
from litestar.types import Empty
1011
from litestar.utils.dataclass import simple_asdict
@@ -16,8 +17,8 @@
1617
from litestar_oracledb.config._common import (
1718
CONNECTION_SCOPE_KEY,
1819
SESSION_TERMINUS_ASGI_EVENTS,
19-
GenericDatabaseConfig,
20-
GenericPoolConfig,
20+
GenericOracleDatabaseConfig,
21+
GenericOraclePoolConfig,
2122
)
2223

2324
if TYPE_CHECKING:
@@ -115,15 +116,15 @@ def handler(message: Message, scope: Scope) -> None:
115116

116117

117118
@dataclass
118-
class SyncPoolConfig(GenericPoolConfig[ConnectionPool, Connection]):
119+
class SyncOraclePoolConfig(GenericOraclePoolConfig[ConnectionPool, Connection]):
119120
"""Sync Oracle Pool Config"""
120121

121122

122123
@dataclass
123-
class SyncDatabaseConfig(GenericDatabaseConfig[ConnectionPool, Connection]):
124+
class SyncOracleDatabaseConfig(GenericOracleDatabaseConfig[ConnectionPool, Connection]):
124125
"""Oracle database Configuration."""
125126

126-
pool_config: SyncPoolConfig | None | EmptyType = Empty
127+
pool_config: SyncOraclePoolConfig | None | EmptyType = Empty
127128
"""Oracle Pool configuration"""
128129

129130
def __post_init__(self) -> None:
@@ -163,6 +164,18 @@ def signature_namespace(self) -> dict[str, Any]:
163164
"ConnectionPool": ConnectionPool,
164165
}
165166

167+
@property
168+
def dependencies(self) -> dict[str, Any]:
169+
"""Return the plugin's signature namespace.
170+
171+
Returns:
172+
A string keyed dict of names to be added to the namespace for signature forward reference resolution.
173+
"""
174+
return {
175+
self.pool_dependency_key: Provide(self.provide_pool, sync_to_thread=True),
176+
self.connection_dependency_key: Provide(self.provide_connection),
177+
}
178+
166179
def create_pool(self) -> ConnectionPool:
167180
"""Return a pool. If none exists yet, create one.
168181
@@ -193,7 +206,7 @@ async def lifespan(
193206
try:
194207
yield
195208
finally:
196-
db_pool.close()
209+
db_pool.close(force=True)
197210

198211
def provide_connection(
199212
self,
@@ -213,7 +226,9 @@ def provide_connection(
213226
"Optional[Connection]",
214227
get_scope_state(scope, self.connection_scope_key),
215228
)
216-
if connection is None:
229+
if connection is not None:
230+
yield connection
231+
else:
217232
pool = cast("ConnectionPool", state.get(self.pool_app_state_key))
218233

219234
with pool.acquire() as connection:
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from __future__ import annotations
2+
3+
from typing import Any
4+
5+
from litestar.exceptions import LitestarException
6+
7+
8+
class LitestarOracleException(LitestarException):
9+
"""Base exception class from which all Litestar Oracle database exceptions inherit."""
10+
11+
detail: str
12+
13+
def __init__(self, *args: Any, detail: str = "") -> None:
14+
"""Initialize ``AdvancedAlchemyException``.
15+
16+
Args:
17+
*args: args are converted to :class:`str` before passing to :class:`Exception`
18+
detail: detail of the exception.
19+
"""
20+
str_args = [str(arg) for arg in args if arg]
21+
if not detail:
22+
if str_args:
23+
detail, *str_args = str_args
24+
elif hasattr(self, "detail"):
25+
detail = self.detail
26+
self.detail = detail
27+
super().__init__(*str_args)
28+
29+
def __repr__(self) -> str:
30+
if self.detail:
31+
return f"{self.__class__.__name__} - {self.detail}"
32+
return self.__class__.__name__
33+
34+
def __str__(self) -> str:
35+
return " ".join((*self.args, self.detail)).strip()
36+
37+
38+
class ImproperConfigurationError(LitestarOracleException):
39+
"""Improper Configuration error.LitestarOracleException
40+
41+
This exception is raised only when a module depends on a dependency that has not been installed.
42+
"""

0 commit comments

Comments
 (0)