# Skuf 
![Python](https://img.shields.io/badge/python-3.9%2B-blue?logo=python&logoColor=white)![Version](https://img.shields.io/badge/version-0.3.0-green)

Minimal Dependency Injection & Configuration Framework for Python

## 🚀 Features

- ⚡️ Lightweight and zero-dependency
- 🧩 Simple Dependency Injection container
- 🔄 Context Manager support for Unit of Work patterns
- ⚡️ Async Context Manager support
- 🔐 Type-safe `.env`-based configuration loader (like `pydantic.BaseSettings`)
- 🧱 Suitable for scripts, CLI tools, microservices

## 📦 Installation

```bash
pip install skuf
```

## 🧰 Dependency Injection
```python
from skuf import Dependency

# Define a Logger
class Logger:
    def log(self, msg: str):
        print(msg)

# Register the class
Dependency.register(Logger)

# Use with decorator for automatic injection
@Dependency.inject
def test_func(logger: Dependency[Logger]):
    logger.log("Hello, World! From a function!")

# Or resolve manually
logger = Dependency.resolve(Logger)
logger.log("Hello, World!")
test_func()

# Output:
# Hello, World!
# Hello, World! From a function!
```

## 🔄 Unit of Work with Automatic Context Management
```python
from skuf import Dependency

# Define a Unit of Work with context manager
class UnitOfWork:
    def __init__(self):
        self.operations = []
    
    def add_operation(self, op: str):
        self.operations.append(op)
    
    def __enter__(self):
        print("🚀 Starting transaction...")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            print(f"✅ Committing: {self.operations}")
        else:
            print(f"❌ Rolling back: {self.operations}")

# Register context manager
def create_uow():
    return UnitOfWork()

Dependency.register(UnitOfWork, factory=create_uow)

# Use with automatic context management (like FastAPI)
@Dependency.inject
def business_logic(uow: Dependency[UnitOfWork]):
    uow.add_operation("Create user")
    uow.add_operation("Send email")
    # Context automatically managed by decorator

business_logic()  # Auto-commit on success, rollback on exception
```

## ⚡ Async Unit of Work
```python
import asyncio
from skuf import Dependency

class AsyncUnitOfWork:
    def __init__(self):
        self.operations = []
    
    def add_operation(self, op: str):
        self.operations.append(op)
    
    async def __aenter__(self):
        print("🚀 Starting async transaction...")
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            print(f"✅ Committing async: {self.operations}")
        else:
            print(f"❌ Rolling back async: {self.operations}")

# Register async context manager
def create_async_uow():
    return AsyncUnitOfWork()

Dependency.register(AsyncUnitOfWork, async_context_manager=create_async_uow)

# Use in async business logic
@Dependency.inject
async def async_business_logic(uow: Dependency[AsyncUnitOfWork]):
    uow.add_operation("Async create user")
    uow.add_operation("Async send email")
    # Context automatically managed by decorator

asyncio.run(async_business_logic())
```

## 🔄 Async Generator UoW with @asynccontextmanager
```python
import asyncio
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from skuf import Dependency

class IUnitOfWork:
    def __init__(self):
        self.operations = []
    
    def add_operation(self, op: str):
        self.operations.append(op)

@asynccontextmanager
async def get_uow() -> AsyncGenerator[IUnitOfWork, None]:
    logger.debug('🚀 UnitOfWork started')
    uow = IUnitOfWork()
    try:
        yield uow
        logger.debug('✅ UnitOfWork completed successfully')
    except Exception as e:
        logger.error(f'❌ UnitOfWork failed: {e}')
        raise

# Register async generator factory
Dependency.register(IUnitOfWork, async_generator_factory=get_uow)

# Use in business logic
@Dependency.inject
async def business_logic(uow: Dependency[IUnitOfWork]):
    uow.add_operation("Create user")
    uow.add_operation("Send email")
    # Context automatically managed by decorator

asyncio.run(business_logic())
```


## ⚙️ Environment Settings
```python
# .env
API_KEY=supersecret
TIMEOUT=5
DEBUG=true
RETRIES=3
ADMINS=123,456

# settings.py
from skuf import BaseSettings
from typing import List

class Settings(BaseSettings):
    api_key: str
    timeout: int
    debug: bool
    retries: int
    admins: List[int]

settings = Settings()

print(settings.api_key)   # supersecret
print(settings.timeout)   # 5
print(settings.debug)     # True
print(settings.admins)    # [123, 456]
```

✅ Supports types:
* str, int, float, bool
* List[str], List[int], List[float] (via comma-separated values like A,B,C)
