p2p-ld / numpydantic

Type annotations for specifying, validating, and serializing arrays with arbitrary backends in Pydantic (and beyond)
https://numpydantic.readthedocs.io/
MIT License
66 stars 1 forks source link

Make NDArray callable as a functional validator #8

Closed sneakers-the-rat closed 3 months ago

sneakers-the-rat commented 3 months ago

Problem, when you use a numpydantic "wrap" validator, it gives the annotation as a handler function.

So this is effectively what happens

@field_validator("*", mode="wrap")
@classmethod
def cast_specified_columns(
    cls, val: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo
) -> Any:
    # where handler is the callable here
    # so 
    # return handler(val)

    return NDArray[Any, Any](val)

where Any, Any is whatever you had put in there.

So this makes it so you can use an annotation as a functional validator. it looks a little bit whacky but idk it makes sense as a PARAMETERIZED TYPE

>>> from numpydantic import NDArray, Shape
>>> import numpy as np

>>> array = np.array([1,2,3], dtype=int)
>>> validated = NDArray[Shape["3"], int](array)
>>> assert validated is array
True

>>> bad_array = np.array([1,2,3,4], dtype=int)
>>> _ = NDArray[Shape["3"], int](bad_array)
    175 """
    176 Raise a ShapeError if the shape is invalid.
    177 
    178 Raises:
    179     :class:`~numpydantic.exceptions.ShapeError`
    180 """
    181 if not valid:
--> 182     raise ShapeError(
    183         f"Invalid shape! expected shape {self.shape.prepared_args}, "
    184         f"got shape {shape}"
    185     )

ShapeError: Invalid shape! expected shape ['3'], got shape (4,)
sneakers-the-rat commented 3 months ago

looks good, me