MoschittaFramework / moschitta-core

MIT License
0 stars 0 forks source link

Pydantic-like Validation module proposal #7

Open skyler-saville opened 4 months ago

skyler-saville commented 4 months ago

Moschitta Framework Module Proposal

Overview and Objectives

Module Name: moschitta-validation

Overview: The moschitta-validation module aims to provide robust data validation and serialization functionalities, similar to Pydantic. This module will allow developers to define data models with built-in validation, ensuring data integrity and consistency across the application.

Objectives:

Directory Structure

moschitta-validation/
├── LICENSE
├── README.md
├── pyproject.toml
├── moschitta_validation/
│   ├── __init__.py
│   └── validation.py
└── tests/
    └── test_validation.py

Implementation Details

Base Classes and OOP Design

The moschitta-validation module will use a base class BaseModel for all data models. This class will handle validation and serialization logic.

# moschitta_validation/validation.py

from typing import Any, Dict, Type, TypeVar, Union
import json

T = TypeVar('T', bound='BaseModel')

class BaseModel:
    def __init__(self, **data: Any):
        self.__dict__.update(data)
        self.validate()

    @classmethod
    def parse_obj(cls: Type[T], obj: Dict[str, Any]) -> T:
        return cls(**obj)

    @classmethod
    def parse_raw(cls: Type[T], raw_data: str) -> T:
        return cls.parse_obj(json.loads(raw_data))

    def json(self) -> str:
        return json.dumps(self.__dict__)

    def dict(self) -> Dict[str, Any]:
        return self.__dict__

    def validate(self) -> None:
        # Implement validation logic here
        pass

Decorators

Decorators will be provided to define fields and their validation rules.

# moschitta_validation/fields.py

def field(**kwargs):
    def decorator(func):
        func._field_metadata = kwargs
        return func
    return decorator

Type Hints and Docstrings

All classes and methods will include type hints and docstrings to ensure clear documentation and code readability.

# moschitta_validation/validation.py

class BaseModel:
    def __init__(self, **data: Any):
        """
        Initialize a new model instance with the given data.

        :param data: Key-value pairs representing the model fields.
        """
        self.__dict__.update(data)
        self.validate()

    @classmethod
    def parse_obj(cls: Type[T], obj: Dict[str, Any]) -> T:
        """
        Parse a dictionary into a model instance.

        :param obj: Dictionary containing data to be parsed.
        :return: An instance of the model.
        """
        return cls(**obj)

    @classmethod
    def parse_raw(cls: Type[T], raw_data: str) -> T:
        """
        Parse a JSON string into a model instance.

        :param raw_data: JSON string containing data to be parsed.
        :return: An instance of the model.
        """
        return cls.parse_obj(json.loads(raw_data))

    def json(self) -> str:
        """
        Serialize the model instance to a JSON string.

        :return: JSON string representation of the model.
        """
        return json.dumps(self.__dict__)

    def dict(self) -> Dict[str, Any]:
        """
        Convert the model instance to a dictionary.

        :return: Dictionary representation of the model.
        """
        return self.__dict__

    def validate(self) -> None:
        """
        Validate the model fields. Override this method to implement custom validation.
        """
        pass

Asynchronous Operations

While the core validation logic is synchronous, the module will support asynchronous validation where necessary, especially for fields that require asynchronous checks (e.g., database lookups).

# moschitta_validation/validation.py

import asyncio

class AsyncBaseModel(BaseModel):
    async def validate(self) -> None:
        """
        Asynchronously validate the model fields. Override this method to implement custom validation.
        """
        await asyncio.sleep(0)  # Simulate async validation

Example Usage

# example_usage.py

from moschitta_validation import BaseModel

class Item(BaseModel):
    name: str
    description: str
    price: float

item = Item(name="Sample Item", description="A sample item", price=19.99)
print(item.json())

Documentation and Testing

Documentation:

Testing:

# tests/test_validation.py

import pytest
from moschitta_validation import BaseModel

def test_model_initialization():
    class Item(BaseModel):
        name: str
        description: str
        price: float

    item = Item(name="Sample Item", description="A sample item", price=19.99)
    assert item.name == "Sample Item"
    assert item.description == "A sample item"
    assert item.price == 19.99

def test_model_serialization():
    class Item(BaseModel):
        name: str
        description: str
        price: float

    item = Item(name="Sample Item", description="A sample item", price=19.99)
    assert item.json() == '{"name": "Sample Item", "description": "A sample item", "price": 19.99}'

By following this proposal, the moschitta-validation module will provide a powerful, flexible, and easy-to-use data validation and serialization solution for the Moschitta Framework, ensuring consistency and reliability across applications.

skyler-saville commented 4 months ago

Critique of moschitta-validation Module Proposal

Title: Improvements Needed for moschitta-validation Module Proposal

Description: While the moschitta-validation module proposal outlines a solid foundation for data validation and serialization, several areas need enhancement to align with best practices and the overarching goals of the Moschitta Framework.

Issues:

  1. Validation Logic Needs Detail: The proposal mentions a validate method but does not provide concrete implementation details. We need to outline specific validation rules, error handling, and how custom validators can be integrated.

    Suggested Solution: Define a set of built-in validators (e.g., StringField, NumberField) with clear rules. Provide examples of custom validators and how they can be added to models.

  2. Lack of Comprehensive Error Handling: Error handling in the BaseModel class is vague. It's crucial to have a robust error management system to catch and report validation issues effectively.

    Suggested Solution: Introduce a ValidationError exception class. Ensure the validate method raises detailed exceptions that include the field name and error message.

  3. Asynchronous Validation Example Incomplete: The asynchronous validation example is minimal and does not demonstrate practical use cases. More detailed scenarios, especially involving I/O operations, should be provided.

    Suggested Solution: Provide an example where asynchronous validation involves checking data against a database or an external API.

  4. Decorator Functionality Not Fully Explained: The field decorator is introduced without a thorough explanation of its usage and purpose. More context is needed on how this integrates with the validation process.

    Suggested Solution: Enhance the documentation with examples of how the field decorator is used in defining model fields and specifying validation constraints.

  5. Serialization to Multiple Formats: The current implementation supports JSON, but modern applications often require serialization to other formats like XML or YAML.

    Suggested Solution: Implement and document support for additional serialization formats, providing flexibility for different use cases.

  6. Lack of Detailed Testing Strategy: The testing section lacks depth, especially regarding edge cases and integration tests.

    Suggested Solution: Expand the testing strategy to cover various scenarios, including boundary cases, invalid data, and integration with other Moschitta modules.

By addressing these issues, the moschitta-validation module can provide a more robust and comprehensive solution, enhancing its reliability and ease of use within the Moschitta Framework.