Source code for structum_lab.plugins.database
# Structum Database Plugin
# SPDX-License-Identifier: Apache-2.0
"""
Database plugin for Structum Lab.
Provides production-ready database connectivity with support for:
- SQLAlchemy 2.0+ (PostgreSQL, MySQL, SQLite, etc.)
- psycopg3 (direct PostgreSQL, high performance)
Quick Start:
>>> from structum_lab.plugins.database import SQLAlchemyDatabase
>>>
>>> # Direct configuration
>>> db = SQLAlchemyDatabase(url="postgresql://user:pass@localhost/mydb")
>>>
>>> # Or using config provider (Factory Pattern)
>>> db = SQLAlchemyDatabase.from_config()
>>>
>>> with db.transaction() as conn:
... conn.execute("SELECT * FROM users")
... users = conn.fetchall()
Installation:
pip install structum-database[sqlalchemy] # SQLAlchemy backend
pip install structum-database[postgres] # psycopg3 backend
pip install structum-database[all] # Both backends
"""
from structum_lab.database.interfaces import (
ConnectionInterface,
DatabaseInterface,
HealthCheckResult,
HealthStatus,
TransactionInterface,
)
from .base import BaseDatabase
# Backends are imported lazily to avoid import errors if dependencies not installed
__all__ = [
# Interfaces (from core)
"DatabaseInterface",
"ConnectionInterface",
"TransactionInterface",
"HealthCheckResult",
"HealthStatus",
# Base class
"BaseDatabase",
# Backends (lazy loaded)
"SQLAlchemyDatabase",
"PostgresDatabase",
]
[docs]
def __getattr__(name: str):
"""Lazy loading of backends to handle optional dependencies."""
if name == "SQLAlchemyDatabase":
try:
from .sqlalchemy import SQLAlchemyDatabase
return SQLAlchemyDatabase
except ImportError as e:
raise ImportError(
"SQLAlchemy backend requires 'sqlalchemy' package. "
"Install with: pip install structum-database[sqlalchemy]"
) from e
if name == "PostgresDatabase":
try:
from .postgres import PostgresDatabase
return PostgresDatabase
except ImportError as e:
raise ImportError(
"PostgreSQL backend requires 'psycopg' package. "
"Install with: pip install structum-database[postgres]"
) from e
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")