Skip to content

dperezcabrera/pico-pydantic

πŸ“¦ pico-pydantic

PyPI Ask DeepWiki License: MIT CI (tox matrix) codecov Quality Gate Status Duplicated Lines (%) Maintainability Rating Docs Interactive Lab

Pico-Pydantic

Pico-Pydantic integrates Pico-IoC with Pydantic, enabling declarative, aspect-oriented validation of method arguments within your service layer.

It uses Pico-IoC's MethodInterceptor system to perform validation based on Pydantic BaseModel type hints before your method's business logic runs. This is the ideal tool for ensuring arguments passed between IoC-managed services are structurally correct.

🐍 Requires Python 3.11+ 🧩 Works with Pydantic 2.0+ πŸ”„ Supports async and sync methods πŸ§ͺ Enables unit testing of validation separate from business logic


🎯 Why pico-pydantic

While web frameworks handle validation at the HTTP boundary, business services often need to guarantee input integrity internally, especially when components are called from CLI tools, workers, or other services.

Pico-Pydantic provides:

  • Declarative @validate boundaries for service methods.
  • Aspect-Oriented Programming (AOP) for argument validation.
  • Clear error handling with ValidationFailedError.
  • Centralized validation logic, decoupled from the core service code.
Concern Pico-IoC Default pico-pydantic
Argument checking Manual if/raise Declarative @validate
Schema definition None Pydantic BaseModel type hints
Handling errors Raw ValidationError Wrapped ValidationFailedError

🧱 Core Features

  • Method validation via @validate decorator.
  • ValidationInterceptor for AOP execution.
  • Seamless compatibility with BaseModel type annotations.
  • Correct handling of positional, keyword, and default arguments.
  • Zero coupling to web frameworks.

πŸ“¦ Installation

pip install pico-pydantic

πŸš€ Quick Example

1. Define the Data Model and Service:

from pydantic import BaseModel, Field
from pico_ioc import component
from pico_pydantic import validate

class ItemData(BaseModel):
    name: str = Field(min_length=3)
    price: float = Field(gt=0)

@component
class InventoryService:
    @validate
    async def add_item(self, data: ItemData) -> dict:
        # Validation happens BEFORE this line
        print(f"Adding item: {data.name}")
        return data.model_dump()

2. Full Example: Initialization, Success, and Failure Handling

import asyncio
from pico_boot import init
from pico_pydantic import ValidationFailedError

# 'components' is used here as the module containing InventoryService.
container = init(modules=["components"])

async def main():
    service = container.get(InventoryService)

    # --- Success: Validation Passes ---
    print("--- Testing Success ---")
    result = await service.add_item({"name": "Hammer", "price": 10.50})
    print(f"Result: {result}")
    
    # --- Failure: ValidationFailedError is thrown by the Interceptor ---
    print("\n--- Testing Failure ---")
    try:
        # Fails: 'price' is negative, violating Field(gt=0)
        await service.add_item({"name": "A", "price": -5})
    except ValidationFailedError as e:
        print(f"Validation failed for method '{e.method_name}'.")
        print(e.pydantic_error) # Shows the detailed Pydantic error
    
    await container.cleanup_all_async()
    container.shutdown()

if __name__ == "__main__":
    asyncio.run(main())

βš™οΈ How It Works

  • The @validate decorator attaches ValidationInterceptor to the method's AOP chain via @intercepted_by.
  • When the method is called:
  • The interceptor captures the call arguments.
  • It inspects the method signature for arguments with the BaseModel type hint.
  • It validates each argument using TypeAdapter.validate_python(value).
  • If validation fails, it wraps the error in ValidationFailedError and stops execution.
  • If successful, call_next is executed, and the original method runs.

No manual checks inside the service method. Logic stays clean.


πŸ’‘ Architecture Overview

                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚         Your App            β”‚
                 β”‚ (Service Layer)             β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                        @validate called
                                β”‚
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚          Pico-IoC            β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                    ValidationInterceptor (AOP)
                                β”‚
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚         pico-pydantic        β”‚
                 β”‚  Inspect & validate_python()  β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                             Pydantic 2.0+

AI Coding Skills

Install Claude Code or OpenAI Codex skills for AI-assisted development with pico-pydantic:

curl -sL https://raw.githubusercontent.com/dperezcabrera/pico-skills/main/install.sh | bash -s -- pydantic
Command Description
/add-validation Add Pydantic validation to component methods
/add-component Add components, factories, interceptors, settings
/add-tests Generate tests for pico-framework components

All skills: curl -sL https://raw.githubusercontent.com/dperezcabrera/pico-skills/main/install.sh | bash

See pico-skills for details.


πŸ“ License

MIT

About

A lightweight validation layer for Pico-IoC that turns Pydantic type hints into enforced contracts. Features automatic data transformation and support for complex types (List, Union, Optional).

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors