fastapi-redis-utils


Namefastapi-redis-utils JSON
Version 1.0.8 PyPI version JSON
download
home_pageNone
SummaryFast and easy Redis integration for FastAPI applications.
upload_time2025-08-07 04:41:50
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseMIT
keywords async connection-pool dependency-injection fastapi redis utils
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # FastAPI Redis Utils

[![CI/CD](https://img.shields.io/github/actions/workflow/status/serafinovsky/fastapi-redis-utils/ci.yml)](https://github.com/serafinovsky/fastapi-redis-utils/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/serafinovsky/fastapi-redis-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/serafinovsky/fastapi-redis-utils)
[![PyPI](https://img.shields.io/pypi/v/fastapi-redis-utils.svg)](https://pypi.org/project/fastapi-redis-utils/)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/serafinovsky/fastapi-redis-utils)](https://github.com/serafinovsky/fastapi-redis-utils/releases)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-redis-utils)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![Type checked with mypy](https://img.shields.io/badge/mypy-checked-blue.svg)](http://mypy-lang.org/)
[![Security: bandit](https://img.shields.io/badge/security-bandit-green.svg)](https://github.com/PyCQA/bandit)

**Fast and easy Redis integration for FastAPI applications.**

This library provides everything you need to quickly integrate Redis with FastAPI:

- **RedisManager** - Async Redis manager with connection pooling and retry mechanism
- **FastAPI Dependencies** - Ready-to-use dependencies for Redis injection into your endpoints
- **BaseRepository** - CRUD operations with Pydantic models for rapid development

Perfect for caching, session storage, and data persistence in FastAPI applications.

## Features

- 🔌 **FastAPI Integration** - Ready-to-use dependencies for Redis injection
- 🏃 **Async Support** - Full async/await capabilities
- 📦 **Connection Management** - Efficient connection pooling
- 🔄 **Auto-retry** - Automatic retry on connection failures
- 🏥 **Monitoring** - Built-in connection health checks
- 🛡️ **Type Hints** - Complete typing support
- 📝 **Pydantic Models** - Base repository with Pydantic support

## Documentation

- 📖 **[Usage Guide](https://github.com/serafinovsky/fastapi-redis-utils/blob/main/USAGE.md)** - Detailed usage examples and advanced features
- 🚀 **[FastAPI Integration Example](https://github.com/serafinovsky/fastapi-redis-utils/blob/main/examples/fastapi_integration.py)** - Complete FastAPI application with Redis integration

## Installation

### From PyPI

```bash
uv add fastapi-redis-utils
```

### From Git repository

```bash
uv add git+https://github.com/serafinovsky/fastapi-redis-utils.git
```

### For development

```bash
git clone https://github.com/serafinovsky/fastapi-redis-utils.git
cd fastapi-redis-utils
uv sync --dev
```

## Quick Start

### Basic Usage

```python
import asyncio
from fastapi_redis_utils import RedisManager

async def main():
    # Create manager
    redis_manager = RedisManager(
        dsn="redis://localhost:6379",
        max_connections=20,
        retry_attempts=3
    )

    # Connect
    await redis_manager.connect()

    # Use
    client = redis_manager.get_client()
    await client.set("key", "value")
    value = await client.get("key")

    # Close
    await redis_manager.close()

asyncio.run(main())
```

### FastAPI Integration

```python
from fastapi import FastAPI, Depends
from fastapi_redis_utils import RedisManager, create_redis_client_dependencies
import redis.asyncio as redis

app = FastAPI()

# Create Redis manager
redis_manager = RedisManager(
    dsn="redis://localhost:6379"
)

# Create FastAPI dependency
get_redis_client = create_redis_client_dependencies(redis_manager)

@app.on_event("startup")
async def startup_event():
    """Connect to Redis on application startup"""
    await redis_manager.connect()

@app.on_event("shutdown")
async def shutdown_event():
    """Close connection on application shutdown"""
    await redis_manager.close()

@app.get("/cache/{key}")
async def get_cached_data(key: str, redis_client: redis.Redis = Depends(get_redis_client)):
    """Get data from cache"""
    value = await redis_client.get(key)
    return {"key": key, "value": value}

@app.post("/cache/{key}")
async def set_cached_data(
    key: str,
    value: str,
    redis_client: redis.Redis = Depends(get_redis_client)
):
    """Save data to cache"""
    await redis_client.set(key, value)
    return {"key": key, "value": value, "status": "saved"}

@app.get("/health")
async def health_check():
    """Check Redis connection status"""
    is_healthy = await redis_manager.health_check()
    return {"redis_healthy": is_healthy}
```

### Using BaseRepository with Separate Create and Update Schemas

```python
import uuid
from uuid import UUID
from fastapi import HTTPException, status
from pydantic import BaseModel
from typing import Optional
from datetime import datetime
from fastapi_redis_utils import BaseRepository, RedisManager, BaseResultModel

class CreateDemoSchema(BaseModel):
    field1: str
    field2: str


class UpdateDemoSchema(BaseModel):
    field1: str | None = None
    field2: str | None = None


class DemoSchema(BaseResultModel):
    id: str | None = None
    field1: str
    field2: str

    def set_id(self, id: str) -> None:
        self.id = id


class DemoRepository(BaseRepository[CreateDemoSchema, UpdateDemoSchema, DemoSchema]):
    pass


demo_crud = DemoRepository(redis_manager, CreateDemoSchema, UpdateDemoSchema, DemoSchema)


@app.post("/repo/", response_model=DemoSchema, status_code=status.HTTP_201_CREATED)
async def create_demo(demo_model: CreateDemoSchema) -> DemoSchema:
    """Create a new demo record."""
    demo_id = str(uuid.uuid4())
    return await demo_crud.create(demo_id, demo_model)


@app.get("/repo/{demo_id}", response_model=DemoSchema)
async def get_demo(demo_id: UUID) -> DemoSchema:
    """Get a demo record by ID."""
    demo = await demo_crud.get(str(demo_id))
    if demo is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Demo record with ID '{demo_id}' not found",
        )

    return demo


@app.get("/repo/", response_model=list[DemoSchema])
async def list_demos(limit: int = 100) -> list[DemoSchema]:
    """List all demo records"""
    return await demo_crud.list(limit=limit)


@app.put("/repo/{demo_id}", response_model=DemoSchema)
async def update_demo(demo_id: UUID, demo_update: UpdateDemoSchema) -> DemoSchema:
    """Update a demo record."""
    updated_demo = await demo_crud.update(str(demo_id), demo_update)
    if updated_demo is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Demo record with ID '{demo_id}' not found",
        )
    return updated_demo


@app.delete("/repo/{demo_id}")
async def delete_demo(demo_id: UUID) -> dict[str, UUID]:
    """Delete a demo record."""
    deleted = await demo_crud.delete(str(demo_id))
    if not deleted:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Demo record with ID '{demo_id}' not found",
        )
    return {"id": demo_id}


@app.get("/repo/{demo_id}/exists")
async def check_demo_exists(demo_id: UUID) -> dict[str, UUID | bool]:
    """Check if a demo record exists."""
    exists = await demo_crud.exists(str(demo_id))
    return {"id": demo_id, "exists": exists}
```

### Executing Operations with Retry

```python
async def complex_operation():
    async def operation():
        client = redis_manager.get_client()
        # Complex Redis operation
        result = await client.execute_command("COMPLEX_COMMAND")
        return result

    # Automatic retries on failures
    result = await redis_manager.execute_with_retry(operation)
    return result
```

## Configuration

### RedisManager Parameters

| Parameter                | Type  | Default | Description                           |
| ------------------------ | ----- | ------- | ------------------------------------- |
| `dsn`                    | str   | `-`     | DSN for Redis connection              |
| `max_connections`        | int   | `20`    | Maximum number of connections in pool |
| `retry_attempts`         | int   | `3`     | Number of reconnection attempts       |
| `retry_delay`            | float | `1.0`   | Base delay between attempts (seconds) |
| `socket_connect_timeout` | int   | `5`     | Socket connection timeout (seconds)   |
| `socket_timeout`         | int   | `5`     | Socket operation timeout (seconds)    |

## API Reference

### RedisManager

Main class for managing Redis connections.

#### Methods

- `connect()` - Connect to Redis with retry mechanism
- `ensure_connection()` - Ensure connection availability
- `close()` - Close connection and cleanup resources
- `health_check()` - Check connection status
- `get_client()` - Get Redis client
- `execute_with_retry()` - Execute operations with retry

### create_redis_client_dependencies

Creates FastAPI dependency for getting Redis client.

### BaseRepository

Base repository class for working with Pydantic models in Redis. Supports separate schemas for create, update, and result operations with partial updates.

#### Generic Parameters

- `CreateSchemaType` - Pydantic model for create operations
- `UpdateSchemaType` - Pydantic model for update operations (all fields optional)
- `ResultSchemaType` - Pydantic model for result operations (must inherit from BaseResultModel)

#### Core Methods

- `create(key, data: CreateSchemaType, ttl=None)` - Create record
- `get(key)` - Get record (returns ResultSchemaType)
- `update(key, data: UpdateSchemaType, ttl=None)` - Update record with partial update (only set fields)
- `delete(key)` - Delete record
- `exists(key)` - Check record existence
- `list(pattern="*", limit=None)` - Get list of records
- `count(pattern="*")` - Count records
- `set_ttl(key, ttl)` - Set TTL
- `get_ttl(key)` - Get TTL
- `clear(pattern="*")` - Clear records

#### Partial Update Feature

The `update` method performs partial updates - only fields that are set in the update schema will be modified. Fields with `None` values are ignored.

## Development

### Install development dependencies

```bash
uv sync --dev
```

### Run tests

```bash
uv run pytest
```

### Code checks

```bash
uv run ruff check .
uv run mypy .
```

### Build package

```bash
uv run build
```

### Makefile Commands

The project includes convenient Makefile commands for development:

```bash
# Main commands
make install          # Install development dependencies
make test            # Run tests
make lint            # Check code with linters
make format          # Format code
make build           # Build package
make clean           # Clean temporary files

# Version management
make version         # Show current version

# Publishing
make publish         # Create and push git tag with current version
make publish-dry-run # Show what would be done without creating tag
make release         # Full release: build, test, tag and push

# Additional commands
make tags            # List all git tags
make check           # Full pre-commit check
make example-fastapi # Run FastAPI example
```

### Release Workflow

1. Update version in `fastapi_redis_utils/__init__.py`
2. Run full release: `make release`
3. Or step by step:

```bash
make test          # Run tests
make build         # Build package
make publish       # Create and push tag
```

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fastapi-redis-utils",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "async, connection-pool, dependency-injection, fastapi, redis, utils",
    "author": null,
    "author_email": "Mark Serafinovsky <m.serafinovsky@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/e5/47/16a22c9ac539ba2c15adb583302dd84ab562edfa2cd0378c020e9c73a2af/fastapi_redis_utils-1.0.8.tar.gz",
    "platform": null,
    "description": "# FastAPI Redis Utils\n\n[![CI/CD](https://img.shields.io/github/actions/workflow/status/serafinovsky/fastapi-redis-utils/ci.yml)](https://github.com/serafinovsky/fastapi-redis-utils/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/serafinovsky/fastapi-redis-utils/branch/main/graph/badge.svg)](https://codecov.io/gh/serafinovsky/fastapi-redis-utils)\n[![PyPI](https://img.shields.io/pypi/v/fastapi-redis-utils.svg)](https://pypi.org/project/fastapi-redis-utils/)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/serafinovsky/fastapi-redis-utils)](https://github.com/serafinovsky/fastapi-redis-utils/releases)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n![Python Versions](https://img.shields.io/pypi/pyversions/fastapi-redis-utils)\n[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)\n[![Type checked with mypy](https://img.shields.io/badge/mypy-checked-blue.svg)](http://mypy-lang.org/)\n[![Security: bandit](https://img.shields.io/badge/security-bandit-green.svg)](https://github.com/PyCQA/bandit)\n\n**Fast and easy Redis integration for FastAPI applications.**\n\nThis library provides everything you need to quickly integrate Redis with FastAPI:\n\n- **RedisManager** - Async Redis manager with connection pooling and retry mechanism\n- **FastAPI Dependencies** - Ready-to-use dependencies for Redis injection into your endpoints\n- **BaseRepository** - CRUD operations with Pydantic models for rapid development\n\nPerfect for caching, session storage, and data persistence in FastAPI applications.\n\n## Features\n\n- \ud83d\udd0c **FastAPI Integration** - Ready-to-use dependencies for Redis injection\n- \ud83c\udfc3 **Async Support** - Full async/await capabilities\n- \ud83d\udce6 **Connection Management** - Efficient connection pooling\n- \ud83d\udd04 **Auto-retry** - Automatic retry on connection failures\n- \ud83c\udfe5 **Monitoring** - Built-in connection health checks\n- \ud83d\udee1\ufe0f **Type Hints** - Complete typing support\n- \ud83d\udcdd **Pydantic Models** - Base repository with Pydantic support\n\n## Documentation\n\n- \ud83d\udcd6 **[Usage Guide](https://github.com/serafinovsky/fastapi-redis-utils/blob/main/USAGE.md)** - Detailed usage examples and advanced features\n- \ud83d\ude80 **[FastAPI Integration Example](https://github.com/serafinovsky/fastapi-redis-utils/blob/main/examples/fastapi_integration.py)** - Complete FastAPI application with Redis integration\n\n## Installation\n\n### From PyPI\n\n```bash\nuv add fastapi-redis-utils\n```\n\n### From Git repository\n\n```bash\nuv add git+https://github.com/serafinovsky/fastapi-redis-utils.git\n```\n\n### For development\n\n```bash\ngit clone https://github.com/serafinovsky/fastapi-redis-utils.git\ncd fastapi-redis-utils\nuv sync --dev\n```\n\n## Quick Start\n\n### Basic Usage\n\n```python\nimport asyncio\nfrom fastapi_redis_utils import RedisManager\n\nasync def main():\n    # Create manager\n    redis_manager = RedisManager(\n        dsn=\"redis://localhost:6379\",\n        max_connections=20,\n        retry_attempts=3\n    )\n\n    # Connect\n    await redis_manager.connect()\n\n    # Use\n    client = redis_manager.get_client()\n    await client.set(\"key\", \"value\")\n    value = await client.get(\"key\")\n\n    # Close\n    await redis_manager.close()\n\nasyncio.run(main())\n```\n\n### FastAPI Integration\n\n```python\nfrom fastapi import FastAPI, Depends\nfrom fastapi_redis_utils import RedisManager, create_redis_client_dependencies\nimport redis.asyncio as redis\n\napp = FastAPI()\n\n# Create Redis manager\nredis_manager = RedisManager(\n    dsn=\"redis://localhost:6379\"\n)\n\n# Create FastAPI dependency\nget_redis_client = create_redis_client_dependencies(redis_manager)\n\n@app.on_event(\"startup\")\nasync def startup_event():\n    \"\"\"Connect to Redis on application startup\"\"\"\n    await redis_manager.connect()\n\n@app.on_event(\"shutdown\")\nasync def shutdown_event():\n    \"\"\"Close connection on application shutdown\"\"\"\n    await redis_manager.close()\n\n@app.get(\"/cache/{key}\")\nasync def get_cached_data(key: str, redis_client: redis.Redis = Depends(get_redis_client)):\n    \"\"\"Get data from cache\"\"\"\n    value = await redis_client.get(key)\n    return {\"key\": key, \"value\": value}\n\n@app.post(\"/cache/{key}\")\nasync def set_cached_data(\n    key: str,\n    value: str,\n    redis_client: redis.Redis = Depends(get_redis_client)\n):\n    \"\"\"Save data to cache\"\"\"\n    await redis_client.set(key, value)\n    return {\"key\": key, \"value\": value, \"status\": \"saved\"}\n\n@app.get(\"/health\")\nasync def health_check():\n    \"\"\"Check Redis connection status\"\"\"\n    is_healthy = await redis_manager.health_check()\n    return {\"redis_healthy\": is_healthy}\n```\n\n### Using BaseRepository with Separate Create and Update Schemas\n\n```python\nimport uuid\nfrom uuid import UUID\nfrom fastapi import HTTPException, status\nfrom pydantic import BaseModel\nfrom typing import Optional\nfrom datetime import datetime\nfrom fastapi_redis_utils import BaseRepository, RedisManager, BaseResultModel\n\nclass CreateDemoSchema(BaseModel):\n    field1: str\n    field2: str\n\n\nclass UpdateDemoSchema(BaseModel):\n    field1: str | None = None\n    field2: str | None = None\n\n\nclass DemoSchema(BaseResultModel):\n    id: str | None = None\n    field1: str\n    field2: str\n\n    def set_id(self, id: str) -> None:\n        self.id = id\n\n\nclass DemoRepository(BaseRepository[CreateDemoSchema, UpdateDemoSchema, DemoSchema]):\n    pass\n\n\ndemo_crud = DemoRepository(redis_manager, CreateDemoSchema, UpdateDemoSchema, DemoSchema)\n\n\n@app.post(\"/repo/\", response_model=DemoSchema, status_code=status.HTTP_201_CREATED)\nasync def create_demo(demo_model: CreateDemoSchema) -> DemoSchema:\n    \"\"\"Create a new demo record.\"\"\"\n    demo_id = str(uuid.uuid4())\n    return await demo_crud.create(demo_id, demo_model)\n\n\n@app.get(\"/repo/{demo_id}\", response_model=DemoSchema)\nasync def get_demo(demo_id: UUID) -> DemoSchema:\n    \"\"\"Get a demo record by ID.\"\"\"\n    demo = await demo_crud.get(str(demo_id))\n    if demo is None:\n        raise HTTPException(\n            status_code=status.HTTP_404_NOT_FOUND,\n            detail=f\"Demo record with ID '{demo_id}' not found\",\n        )\n\n    return demo\n\n\n@app.get(\"/repo/\", response_model=list[DemoSchema])\nasync def list_demos(limit: int = 100) -> list[DemoSchema]:\n    \"\"\"List all demo records\"\"\"\n    return await demo_crud.list(limit=limit)\n\n\n@app.put(\"/repo/{demo_id}\", response_model=DemoSchema)\nasync def update_demo(demo_id: UUID, demo_update: UpdateDemoSchema) -> DemoSchema:\n    \"\"\"Update a demo record.\"\"\"\n    updated_demo = await demo_crud.update(str(demo_id), demo_update)\n    if updated_demo is None:\n        raise HTTPException(\n            status_code=status.HTTP_404_NOT_FOUND,\n            detail=f\"Demo record with ID '{demo_id}' not found\",\n        )\n    return updated_demo\n\n\n@app.delete(\"/repo/{demo_id}\")\nasync def delete_demo(demo_id: UUID) -> dict[str, UUID]:\n    \"\"\"Delete a demo record.\"\"\"\n    deleted = await demo_crud.delete(str(demo_id))\n    if not deleted:\n        raise HTTPException(\n            status_code=status.HTTP_404_NOT_FOUND,\n            detail=f\"Demo record with ID '{demo_id}' not found\",\n        )\n    return {\"id\": demo_id}\n\n\n@app.get(\"/repo/{demo_id}/exists\")\nasync def check_demo_exists(demo_id: UUID) -> dict[str, UUID | bool]:\n    \"\"\"Check if a demo record exists.\"\"\"\n    exists = await demo_crud.exists(str(demo_id))\n    return {\"id\": demo_id, \"exists\": exists}\n```\n\n### Executing Operations with Retry\n\n```python\nasync def complex_operation():\n    async def operation():\n        client = redis_manager.get_client()\n        # Complex Redis operation\n        result = await client.execute_command(\"COMPLEX_COMMAND\")\n        return result\n\n    # Automatic retries on failures\n    result = await redis_manager.execute_with_retry(operation)\n    return result\n```\n\n## Configuration\n\n### RedisManager Parameters\n\n| Parameter                | Type  | Default | Description                           |\n| ------------------------ | ----- | ------- | ------------------------------------- |\n| `dsn`                    | str   | `-`     | DSN for Redis connection              |\n| `max_connections`        | int   | `20`    | Maximum number of connections in pool |\n| `retry_attempts`         | int   | `3`     | Number of reconnection attempts       |\n| `retry_delay`            | float | `1.0`   | Base delay between attempts (seconds) |\n| `socket_connect_timeout` | int   | `5`     | Socket connection timeout (seconds)   |\n| `socket_timeout`         | int   | `5`     | Socket operation timeout (seconds)    |\n\n## API Reference\n\n### RedisManager\n\nMain class for managing Redis connections.\n\n#### Methods\n\n- `connect()` - Connect to Redis with retry mechanism\n- `ensure_connection()` - Ensure connection availability\n- `close()` - Close connection and cleanup resources\n- `health_check()` - Check connection status\n- `get_client()` - Get Redis client\n- `execute_with_retry()` - Execute operations with retry\n\n### create_redis_client_dependencies\n\nCreates FastAPI dependency for getting Redis client.\n\n### BaseRepository\n\nBase repository class for working with Pydantic models in Redis. Supports separate schemas for create, update, and result operations with partial updates.\n\n#### Generic Parameters\n\n- `CreateSchemaType` - Pydantic model for create operations\n- `UpdateSchemaType` - Pydantic model for update operations (all fields optional)\n- `ResultSchemaType` - Pydantic model for result operations (must inherit from BaseResultModel)\n\n#### Core Methods\n\n- `create(key, data: CreateSchemaType, ttl=None)` - Create record\n- `get(key)` - Get record (returns ResultSchemaType)\n- `update(key, data: UpdateSchemaType, ttl=None)` - Update record with partial update (only set fields)\n- `delete(key)` - Delete record\n- `exists(key)` - Check record existence\n- `list(pattern=\"*\", limit=None)` - Get list of records\n- `count(pattern=\"*\")` - Count records\n- `set_ttl(key, ttl)` - Set TTL\n- `get_ttl(key)` - Get TTL\n- `clear(pattern=\"*\")` - Clear records\n\n#### Partial Update Feature\n\nThe `update` method performs partial updates - only fields that are set in the update schema will be modified. Fields with `None` values are ignored.\n\n## Development\n\n### Install development dependencies\n\n```bash\nuv sync --dev\n```\n\n### Run tests\n\n```bash\nuv run pytest\n```\n\n### Code checks\n\n```bash\nuv run ruff check .\nuv run mypy .\n```\n\n### Build package\n\n```bash\nuv run build\n```\n\n### Makefile Commands\n\nThe project includes convenient Makefile commands for development:\n\n```bash\n# Main commands\nmake install          # Install development dependencies\nmake test            # Run tests\nmake lint            # Check code with linters\nmake format          # Format code\nmake build           # Build package\nmake clean           # Clean temporary files\n\n# Version management\nmake version         # Show current version\n\n# Publishing\nmake publish         # Create and push git tag with current version\nmake publish-dry-run # Show what would be done without creating tag\nmake release         # Full release: build, test, tag and push\n\n# Additional commands\nmake tags            # List all git tags\nmake check           # Full pre-commit check\nmake example-fastapi # Run FastAPI example\n```\n\n### Release Workflow\n\n1. Update version in `fastapi_redis_utils/__init__.py`\n2. Run full release: `make release`\n3. Or step by step:\n\n```bash\nmake test          # Run tests\nmake build         # Build package\nmake publish       # Create and push tag\n```\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Contributing\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Fast and easy Redis integration for FastAPI applications.",
    "version": "1.0.8",
    "project_urls": {
        "Documentation": "https://github.com/serafinovsky/fastapi-redis-utils#readme",
        "Homepage": "https://github.com/serafinovsky/fastapi-redis-utils",
        "Issues": "https://github.com/serafinovsky/fastapi-redis-utils/issues",
        "Repository": "https://github.com/serafinovsky/fastapi-redis-utils"
    },
    "split_keywords": [
        "async",
        " connection-pool",
        " dependency-injection",
        " fastapi",
        " redis",
        " utils"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "706218c02c00ae9b3146882ef4523a0472259155ffe9b7c9cbe2b115649a6135",
                "md5": "089ebaf0465fc795d40075ac8f4e4564",
                "sha256": "3875161f25a85aa75e28ca9038dbab78699548e3fec12c7e32b9e03a94e7fc6e"
            },
            "downloads": -1,
            "filename": "fastapi_redis_utils-1.0.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "089ebaf0465fc795d40075ac8f4e4564",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 10063,
            "upload_time": "2025-08-07T04:41:49",
            "upload_time_iso_8601": "2025-08-07T04:41:49.484704Z",
            "url": "https://files.pythonhosted.org/packages/70/62/18c02c00ae9b3146882ef4523a0472259155ffe9b7c9cbe2b115649a6135/fastapi_redis_utils-1.0.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e54716a22c9ac539ba2c15adb583302dd84ab562edfa2cd0378c020e9c73a2af",
                "md5": "6119e8e872cb3115e19d3362d1497bd4",
                "sha256": "5e993d125f3334f30a5b9ce19f65df8c7ba23f7d75de1d8b898b5748789e677c"
            },
            "downloads": -1,
            "filename": "fastapi_redis_utils-1.0.8.tar.gz",
            "has_sig": false,
            "md5_digest": "6119e8e872cb3115e19d3362d1497bd4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 79569,
            "upload_time": "2025-08-07T04:41:50",
            "upload_time_iso_8601": "2025-08-07T04:41:50.787303Z",
            "url": "https://files.pythonhosted.org/packages/e5/47/16a22c9ac539ba2c15adb583302dd84ab562edfa2cd0378c020e9c73a2af/fastapi_redis_utils-1.0.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-07 04:41:50",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "serafinovsky",
    "github_project": "fastapi-redis-utils#readme",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "fastapi-redis-utils"
}
        
Elapsed time: 1.68908s