Skip to content

Commit

Permalink
feat: support multi-config (#5)
Browse files Browse the repository at this point in the history
* feat: support multi-config

* chore: bump version
  • Loading branch information
cofin authored Sep 4, 2024
1 parent 72a7710 commit f90ae37
Show file tree
Hide file tree
Showing 12 changed files with 295 additions and 193 deletions.
6 changes: 3 additions & 3 deletions examples/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from litestar import Controller, Litestar, Request, get

from litestar_oracledb import AsyncDatabaseConfig, AsyncPoolConfig, OracleDatabasePlugin
from litestar_oracledb import AsyncOracleDatabaseConfig, AsyncOraclePoolConfig, OracleDatabasePlugin

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


oracledb = OracleDatabasePlugin(
config=AsyncDatabaseConfig(
pool_config=AsyncPoolConfig(user="system", password="super-secret", dsn="localhost:1513/FREEPDB1") # noqa: S106
config=AsyncOracleDatabaseConfig(
pool_config=AsyncOraclePoolConfig(user="system", password="super-secret", dsn="localhost:1513/FREEPDB1") # noqa: S106
)
)
app = Litestar(plugins=[oracledb], route_handlers=[SampleController])
8 changes: 5 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ license = { text = "MIT" }
name = "litestar-oracledb"
readme = "README.md"
requires-python = ">=3.8"
version = "0.1.3"
version = "0.2.0"

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

# Lint environment
[tool.hatch.envs.lint]
detached = true
extra-dependencies = [
"litestar>=2.0.29",
"oracledb > 2.1",
# tests
"anyio",
"coverage[toml]>=6.2",
Expand All @@ -211,7 +214,6 @@ extra-dependencies = [
"sphinx>=7.1.2",
"sphinx-autobuild>=2021.3.14",
"sphinx-copybutton>=0.5.2",
"litestar-sphinx-theme @ git+https://github.com/litestar-org/litestar-sphinx-theme.git",
"sphinx-click>=5.0.1",
"sphinx-toolbox>=3.5.0",
"sphinx-design>=0.5.0",
Expand All @@ -232,7 +234,7 @@ fix = [
"pre-commit run --all-files",
]
style = ["echo \"VERSION: `ruff --version`\"", "ruff check {args:.}", "ruff format --check {args:.}"]
typing = ["echo \"VERSION: `mypy --version`\"", "mypy --install-types --non-interactive {args}"]
typing = ["echo \"VERSION: `mypy --version`\"", "mypy --install-types --non-interactive {args:.}"]


#####################
Expand Down
17 changes: 15 additions & 2 deletions src/litestar_oracledb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
from __future__ import annotations

from litestar_oracledb.config import AsyncDatabaseConfig, AsyncPoolConfig, SyncDatabaseConfig, SyncPoolConfig
from litestar_oracledb import exceptions
from litestar_oracledb.config import (
AsyncOracleDatabaseConfig,
AsyncOraclePoolConfig,
SyncOracleDatabaseConfig,
SyncOraclePoolConfig,
)
from litestar_oracledb.plugin import OracleDatabasePlugin

__all__ = ("SyncDatabaseConfig", "AsyncDatabaseConfig", "SyncPoolConfig", "AsyncPoolConfig", "OracleDatabasePlugin")
__all__ = (
"SyncOracleDatabaseConfig",
"AsyncOracleDatabaseConfig",
"SyncOraclePoolConfig",
"AsyncOraclePoolConfig",
"OracleDatabasePlugin",
"exceptions",
)
18 changes: 9 additions & 9 deletions src/litestar_oracledb/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from __future__ import annotations

from litestar_oracledb.config._asyncio import AsyncDatabaseConfig, AsyncPoolConfig
from litestar_oracledb.config._common import GenericDatabaseConfig, GenericPoolConfig
from litestar_oracledb.config._sync import SyncDatabaseConfig, SyncPoolConfig
from litestar_oracledb.config._asyncio import AsyncOracleDatabaseConfig, AsyncOraclePoolConfig
from litestar_oracledb.config._common import GenericOracleDatabaseConfig, GenericOraclePoolConfig
from litestar_oracledb.config._sync import SyncOracleDatabaseConfig, SyncOraclePoolConfig

__all__ = (
"SyncDatabaseConfig",
"SyncPoolConfig",
"AsyncDatabaseConfig",
"AsyncPoolConfig",
"GenericDatabaseConfig",
"GenericPoolConfig",
"SyncOracleDatabaseConfig",
"SyncOraclePoolConfig",
"AsyncOracleDatabaseConfig",
"AsyncOraclePoolConfig",
"GenericOracleDatabaseConfig",
"GenericOraclePoolConfig",
)
29 changes: 22 additions & 7 deletions src/litestar_oracledb/config/_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING, Optional, cast

from litestar.constants import HTTP_RESPONSE_START
from litestar.di import Provide
from litestar.exceptions import ImproperlyConfiguredException
from litestar.utils.dataclass import simple_asdict
from oracledb import create_pool_async as oracledb_create_pool
Expand All @@ -15,8 +16,8 @@
from litestar_oracledb.config._common import (
CONNECTION_SCOPE_KEY,
SESSION_TERMINUS_ASGI_EVENTS,
GenericDatabaseConfig,
GenericPoolConfig,
GenericOracleDatabaseConfig,
GenericOraclePoolConfig,
)

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


@dataclass
class AsyncPoolConfig(GenericPoolConfig[AsyncConnectionPool, AsyncConnection]):
class AsyncOraclePoolConfig(GenericOraclePoolConfig[AsyncConnectionPool, AsyncConnection]):
"""Async Oracle Pool Config"""


@dataclass
class AsyncDatabaseConfig(GenericDatabaseConfig[AsyncConnectionPool, AsyncConnection]):
class AsyncOracleDatabaseConfig(GenericOracleDatabaseConfig[AsyncConnectionPool, AsyncConnection]):
"""Async Oracle database Configuration."""

pool_config: AsyncPoolConfig | None = None
pool_config: AsyncOraclePoolConfig | None = None
"""Oracle Pool configuration"""

def __post_init__(self) -> None:
Expand Down Expand Up @@ -168,6 +169,18 @@ def signature_namespace(self) -> dict[str, Any]:
"AsyncConnectionPool": AsyncConnectionPool,
}

@property
def dependencies(self) -> dict[str, Any]:
"""Return the plugin's signature namespace.
Returns:
A string keyed dict of names to be added to the namespace for signature forward reference resolution.
"""
return {
self.pool_dependency_key: Provide(self.provide_pool, sync_to_thread=False),
self.connection_dependency_key: Provide(self.provide_connection),
}

async def create_pool(self) -> AsyncConnectionPool:
"""Return a pool. If none exists yet, create one.
Expand Down Expand Up @@ -198,7 +211,7 @@ async def lifespan(
try:
yield
finally:
await db_pool.close()
await db_pool.close(force=True)

async def provide_connection(
self,
Expand All @@ -218,7 +231,9 @@ async def provide_connection(
"Optional[AsyncConnection]",
get_scope_state(scope, self.connection_scope_key),
)
if connection is None:
if connection is not None:
yield connection
else:
pool = cast("AsyncConnectionPool", state.get(self.pool_app_state_key))

async with pool.acquire() as connection:
Expand Down
4 changes: 2 additions & 2 deletions src/litestar_oracledb/config/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@


@dataclass
class GenericPoolConfig(Generic[PoolT, ConnectionT]):
class GenericOraclePoolConfig(Generic[PoolT, ConnectionT]):
conn_class: type[ConnectionT] | EmptyType = Empty
dsn: str | EmptyType = Empty
pool: PoolT | EmptyType = Empty
Expand Down Expand Up @@ -79,7 +79,7 @@ class GenericPoolConfig(Generic[PoolT, ConnectionT]):


@dataclass
class GenericDatabaseConfig(Generic[PoolT, ConnectionT]):
class GenericOracleDatabaseConfig(Generic[PoolT, ConnectionT]):
"""Oracle database Configuration."""

pool_app_state_key: str = "db_pool"
Expand Down
29 changes: 22 additions & 7 deletions src/litestar_oracledb/config/_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING, Generator, Optional, cast

from litestar.constants import HTTP_RESPONSE_START
from litestar.di import Provide
from litestar.exceptions import ImproperlyConfiguredException
from litestar.types import Empty
from litestar.utils.dataclass import simple_asdict
Expand All @@ -16,8 +17,8 @@
from litestar_oracledb.config._common import (
CONNECTION_SCOPE_KEY,
SESSION_TERMINUS_ASGI_EVENTS,
GenericDatabaseConfig,
GenericPoolConfig,
GenericOracleDatabaseConfig,
GenericOraclePoolConfig,
)

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


@dataclass
class SyncPoolConfig(GenericPoolConfig[ConnectionPool, Connection]):
class SyncOraclePoolConfig(GenericOraclePoolConfig[ConnectionPool, Connection]):
"""Sync Oracle Pool Config"""


@dataclass
class SyncDatabaseConfig(GenericDatabaseConfig[ConnectionPool, Connection]):
class SyncOracleDatabaseConfig(GenericOracleDatabaseConfig[ConnectionPool, Connection]):
"""Oracle database Configuration."""

pool_config: SyncPoolConfig | None | EmptyType = Empty
pool_config: SyncOraclePoolConfig | None | EmptyType = Empty
"""Oracle Pool configuration"""

def __post_init__(self) -> None:
Expand Down Expand Up @@ -163,6 +164,18 @@ def signature_namespace(self) -> dict[str, Any]:
"ConnectionPool": ConnectionPool,
}

@property
def dependencies(self) -> dict[str, Any]:
"""Return the plugin's signature namespace.
Returns:
A string keyed dict of names to be added to the namespace for signature forward reference resolution.
"""
return {
self.pool_dependency_key: Provide(self.provide_pool, sync_to_thread=True),
self.connection_dependency_key: Provide(self.provide_connection),
}

def create_pool(self) -> ConnectionPool:
"""Return a pool. If none exists yet, create one.
Expand Down Expand Up @@ -193,7 +206,7 @@ async def lifespan(
try:
yield
finally:
db_pool.close()
db_pool.close(force=True)

def provide_connection(
self,
Expand All @@ -213,7 +226,9 @@ def provide_connection(
"Optional[Connection]",
get_scope_state(scope, self.connection_scope_key),
)
if connection is None:
if connection is not None:
yield connection
else:
pool = cast("ConnectionPool", state.get(self.pool_app_state_key))

with pool.acquire() as connection:
Expand Down
42 changes: 42 additions & 0 deletions src/litestar_oracledb/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from __future__ import annotations

from typing import Any

from litestar.exceptions import LitestarException


class LitestarOracleException(LitestarException):
"""Base exception class from which all Litestar Oracle database exceptions inherit."""

detail: str

def __init__(self, *args: Any, detail: str = "") -> None:
"""Initialize ``AdvancedAlchemyException``.
Args:
*args: args are converted to :class:`str` before passing to :class:`Exception`
detail: detail of the exception.
"""
str_args = [str(arg) for arg in args if arg]
if not detail:
if str_args:
detail, *str_args = str_args
elif hasattr(self, "detail"):
detail = self.detail
self.detail = detail
super().__init__(*str_args)

def __repr__(self) -> str:
if self.detail:
return f"{self.__class__.__name__} - {self.detail}"
return self.__class__.__name__

def __str__(self) -> str:
return " ".join((*self.args, self.detail)).strip()


class ImproperConfigurationError(LitestarOracleException):
"""Improper Configuration error.LitestarOracleException
This exception is raised only when a module depends on a dependency that has not been installed.
"""
Loading

0 comments on commit f90ae37

Please sign in to comment.