Skip to content

Conversation

cofin
Copy link
Member

@cofin cofin commented Sep 19, 2025

Complete Litestar session management implementation:

Core Components:

  • SQLSpecSessionBackend for Litestar middleware integration
  • SQLSpecSessionConfig with SQLSpec-specific options
  • SQLSpecSessionStore with async/sync interoperability
  • Migration support for session table creation

Session Table Migration:

  • Uses data_dictionary for optimal column types (JSON vs TEXT)
  • Supports all database adapters with appropriate type mapping
  • Configurable table and column names

Features:

  • Native Litestar middleware compatibility
  • JSON serialization with fallback support
  • Configurable session expiration and renewal
  • Store implementations for all 10 database adapters
  • Comprehensive test coverage and examples

Depends on: #81, #82

@cofin cofin force-pushed the litestar-session-store branch 3 times, most recently from 659c639 to 031af11 Compare September 26, 2025 15:07
Core infrastructure updates for async/sync interoperability:

- Enhanced sync_tools with thread-local state tracking
- Improved context manager wrapper for thread consistency
- Better error handling in await_ function for running loops
- Fixed type annotations across core modules

Migration infrastructure improvements:
- Added MigrationContext for runtime migration information
- Enhanced migration runners with extension support
- Updated migration commands with sync_tools integration
- Added comprehensive test coverage

These changes provide foundation for data dictionary and litestar session features.
Comprehensive data dictionary implementation for all adapters:

Core Components:
- VersionInfo class for database version tracking and comparison
- DataDictionaryMixin providing common functionality
- AsyncDataDictionaryBase and SyncDataDictionaryBase abstract classes
- Driver integration with data_dictionary property

Adapter-specific implementations for:
- ADBC, AIOSQLite, AsyncMy, AsyncPG, BigQuery
- DuckDB, OracleDB, psqlpy, Psycopg, SQLite

Features:
- Version detection and parsing
- Feature flag checking (JSON support, RETURNING, CTEs, etc.)
- Optimal type mapping for different type categories
- Database introspection capabilities (tables, columns, indexes)

All adapters now expose metadata querying capabilities through
a consistent interface while supporting database-specific optimizations.
Complete Litestar session management implementation:

Core Components:
- SQLSpecSessionBackend for Litestar middleware integration
- SQLSpecSessionConfig with SQLSpec-specific options
- SQLSpecSessionStore with async/sync interoperability
- Migration support for session table creation

Session Table Migration:
- Uses data_dictionary for optimal column types (JSON vs TEXT)
- Supports all database adapters with appropriate type mapping
- Configurable table and column names
- Extension-aware migration system

Adapter Integration:
- Store implementations for all 10 database adapters
- Leverages sync_tools for seamless async/sync operation
- Consistent API across all database backends
- Proper cleanup and expiration handling

Features:
- Native Litestar middleware compatibility
- JSON serialization with fallback support
- Configurable session expiration and renewal
- Comprehensive test coverage for all adapters
- Example implementations and documentation

Dependencies:
- Requires sync_tools for async/sync conversion
- Requires data_dictionary for optimal type selection
- Builds on migration infrastructure for table setup
@cofin cofin force-pushed the litestar-session-store branch from 031af11 to 1145175 Compare September 27, 2025 20:45
@cofin cofin changed the base branch from main to no-3.9 October 4, 2025 22:40
Base automatically changed from no-3.9 to main October 5, 2025 00:25
cofin added a commit that referenced this pull request Oct 5, 2025
BREAKING CHANGE: DatabaseConfig wrapper classes removed

## Summary

Eliminates DatabaseConfig wrapper pattern and separates async/sync handler
code paths for direct async operations. This combined PR merges the planned
PRs #2, #3, and #4 from the litestar-pr83-analysis into a single change.

## Architecture Changes

**Deleted**:
- `sqlspec/extensions/litestar/config.py` (292 lines) - DatabaseConfig wrapper
- `tests/unit/test_extensions/test_litestar/test_config.py` (482 lines)

**Created**:
- `sqlspec/extensions/litestar/handlers_async.py` (289 lines) - Pure async handlers
- `tests/unit/test_extensions/test_litestar/test_handlers_async.py` (290 lines)

**Modified**:
- `sqlspec/extensions/litestar/handlers.py` → `handlers_sync.py` (renamed)
- `sqlspec/extensions/litestar/plugin.py` (completely rewritten, 491 lines)
- `sqlspec/extensions/litestar/__init__.py` (updated exports)

## Plugin Now Accepts Core Configs Directly

**Before**:
```python
from sqlspec.extensions.litestar import SQLSpec, DatabaseConfig
asyncpg_config = AsyncpgConfig(pool_config={"dsn": "..."})
db_config = DatabaseConfig(config=asyncpg_config)  # Heavy wrapper!
plugin = SQLSpec(config=db_config)
```

**After**:
```python
from sqlspec import SQLSpec
from sqlspec.extensions.litestar import SQLSpec as SQLSpecPlugin
asyncpg_config = AsyncpgConfig(
    pool_config={"dsn": "..."},
    extension_config={"litestar": {"commit_mode": "autocommit"}}
)
sql = SQLSpec()
sql.add_config(asyncpg_config)
plugin = SQLSpecPlugin(config=asyncpg_config)  # No wrapper!
```

## Handler Routing

Plugin uses `config.is_async` ClassVar to route to appropriate handlers:
- **Async configs** → `handlers_async.py` (direct await, zero overhead)
- **Sync configs** → `handlers_sync.py` (minimal ensure_async_() wrapping)

## Test Results

- mypy: 0 errors across 7 source files
- ruff: All checks passed
- pytest: 14/14 unit tests passing
- Net change: -66 lines (901 additions, 967 deletions)

## Migration

Users should update to use extension_config pattern. The old DatabaseConfig
wrapper has been removed without deprecation as this PR combines multiple
planned changes into one.

Fixes performance issues identified in PR #83 analysis.
cofin added a commit that referenced this pull request Oct 5, 2025
* feat!: refactor Litestar extension.

BREAKING CHANGE: DatabaseConfig wrapper classes removed

## Summary

Eliminates DatabaseConfig wrapper pattern and separates async/sync handler
code paths for direct async operations. This combined PR merges the planned
PRs #2, #3, and #4 from the litestar-pr83-analysis into a single change.

## Architecture Changes

**Deleted**:
- `sqlspec/extensions/litestar/config.py` (292 lines) - DatabaseConfig wrapper
- `tests/unit/test_extensions/test_litestar/test_config.py` (482 lines)

**Created**:
- `sqlspec/extensions/litestar/handlers_async.py` (289 lines) - Pure async handlers
- `tests/unit/test_extensions/test_litestar/test_handlers_async.py` (290 lines)

**Modified**:
- `sqlspec/extensions/litestar/handlers.py` → `handlers_sync.py` (renamed)
- `sqlspec/extensions/litestar/plugin.py` (completely rewritten, 491 lines)
- `sqlspec/extensions/litestar/__init__.py` (updated exports)

## Plugin Now Accepts Core Configs Directly

**Before**:
```python
from sqlspec.extensions.litestar import SQLSpec, DatabaseConfig
asyncpg_config = AsyncpgConfig(pool_config={"dsn": "..."})
db_config = DatabaseConfig(config=asyncpg_config)  # Heavy wrapper!
plugin = SQLSpec(config=db_config)
```

**After**:
```python
from sqlspec import SQLSpec
from sqlspec.extensions.litestar import SQLSpec as SQLSpecPlugin
asyncpg_config = AsyncpgConfig(
    pool_config={"dsn": "..."},
    extension_config={"litestar": {"commit_mode": "autocommit"}}
)
sql = SQLSpec()
sql.add_config(asyncpg_config)
plugin = SQLSpecPlugin(config=asyncpg_config)  # No wrapper!
```

## Handler Routing

Plugin uses `config.is_async` ClassVar to route to appropriate handlers:
- **Async configs** → `handlers_async.py` (direct await, zero overhead)
- **Sync configs** → `handlers_sync.py` (minimal ensure_async_() wrapping)

## Test Results

- mypy: 0 errors across 7 source files
- ruff: All checks passed
- pytest: 14/14 unit tests passing
- Net change: -66 lines (901 additions, 967 deletions)

## Migration

Users should update to use extension_config pattern. The old DatabaseConfig
wrapper has been removed without deprecation as this PR combines multiple
planned changes into one.

Fixes performance issues identified in PR #83 analysis.

* fix: updated config

* fix: ensure tests use local handlers

* fix: cleanup

* fix: code quality updates
cofin added a commit that referenced this pull request Oct 5, 2025
…ndlers (#96)

## Summary

Major refactor of the Litestar extension that removes the `DatabaseConfig` wrapper class pattern, unifies duplicate handler files, and fixes type errors and test pollution issues.

## Breaking Changes

**BREAKING**: The `DatabaseConfig` wrapper class has been removed. 

### Before
```python
from sqlspec.extensions.litestar import DatabaseConfig, SQLSpecPlugin
from sqlspec.adapters.asyncpg import AsyncpgConfig

asyncpg_config = AsyncpgConfig(pool_config={"dsn": "..."})
db_config = DatabaseConfig(config=asyncpg_config)  # Wrapper!
plugin = SQLSpecPlugin(configs=[db_config])
```

### After
```python
from sqlspec import SQLSpec
from sqlspec.extensions.litestar import SQLSpecPlugin
from sqlspec.adapters.asyncpg import AsyncpgConfig

asyncpg_config = AsyncpgConfig(
    pool_config={"dsn": "..."},
    extension_config={"litestar": {"commit_mode": "autocommit"}}
)
sql = SQLSpec()
sql.add_config(asyncpg_config)
plugin = SQLSpecPlugin(sqlspec=sql)
```

## Migration Guide

1. **Remove `DatabaseConfig` wrapper**:
   - Pass core config classes directly to `SQLSpec`
   - Use `extension_config` field for Litestar-specific settings

2. **Update Litestar plugin initialization**:
   - Create `SQLSpec()` instance
   - Add configs with `sql.add_config()`
   - Pass `SQLSpec` instance to `SQLSpecPlugin(sqlspec=sql)`

3. **Move Litestar settings to `extension_config`**:
   ```python
   config = AsyncpgConfig(
       pool_config={"dsn": "..."},
       extension_config={
           "litestar": {
               "connection_key": "db_connection",
               "pool_key": "db_pool", 
               "session_key": "db_session",
               "commit_mode": "autocommit"
           }
       }
   )
   ```

## Changes

### Removed DatabaseConfig Wrapper Class
- **Deleted**: `sqlspec/extensions/litestar/config.py` (292 lines)
- **Deleted**: `tests/unit/test_extensions/test_litestar/test_config.py` (482 lines)
- Plugin now accepts `SQLSpec` instance directly
- All configs from `SQLSpec` are automatically included

### Added extension_config Infrastructure
- Added `extension_config` field to all core database config classes
- Added `LitestarConfig` TypedDict for type-safe Litestar configuration
- Configs read from `extension_config["litestar"]` namespace

### Unified Handler Implementation
- **Merged**: `handlers_async.py` + `handlers_sync.py` → `handlers.py`
- Single implementation with conditional `is_async` logic
- Direct `await` for async drivers, `ensure_async_()` for sync drivers
- Simplified plugin with single `_setup_handlers()` method

### Plugin Refactoring
- Rewritten to work directly with core configs
- Uses `config.is_async` to route to appropriate handlers
- Eliminated wrapper overhead and complexity
- Cleaner dependency injection setup

### Fixed Type Errors
- Removed dead `pool_type` code
- Fixed `"Never" is not awaitable` errors
- Removed redundant `get_config()` delegation
- All mypy and pyright errors resolved

### Fixed Test Database File Pollution
- Tests no longer create 30+ database files in project root
- Fixed SQLite URI mode handling (7 locations)
- Converted hardcoded paths to use pytest `tmp_path` (5 locations)
- Added defensive validation to SQLite config classes

### Code Quality Improvements
- Removed defensive programming anti-patterns
- Fixed nested import violations
- Enforced CLAUDE.md standards throughout
- All functions under 75-line limit

## Benefits

- **Simpler API**: No wrapper classes, direct config usage
- **Less Code**: Removed ~774 lines (wrapper + duplicate handlers)
- **Type Safety**: mypy and pyright clean
- **Better Architecture**: Plugin uses core configs directly
- **Cleaner Tests**: No file pollution, proper temp directories

## Test Results

```
✅ 14/14 Litestar handler tests passing
✅ 230/230 integration tests passing  
✅ mypy: 0 errors
✅ pyright: 0 errors
✅ ruff: all checks passed
```

## Files Changed

```
24 files changed, 808 insertions(+), 1118 deletions(-)
```

**Major changes**:
- Deleted wrapper class and duplicate handlers
- Refactored plugin to use `SQLSpec` directly
- Added `extension_config` infrastructure
- Fixed all type errors and test pollution
- Updated all examples and documentation

## Related

- Supersedes portions of PR #83
- Includes merged PR #97 (handler unification + fixes)
@cofin cofin closed this Oct 5, 2025
cofin added a commit that referenced this pull request Oct 6, 2025
Implements a complete set of methods to enable using any supported `sqlspec` driver as a session store in Litestar.

Replaces #83
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant