MilanStaffehl / numdantic

Typing support for numpy arrays and numpy array validation with pydantic.
MIT License
2 stars 0 forks source link

Write protocol class for `numpy.ndarray` #48

Open MilanStaffehl opened 3 months ago

MilanStaffehl commented 3 months ago

The numpy.ndarray class has an invariant shape parameter. While there is a PR at the numpy repo that will make it covariant, this change will probably not be backported, so we are still stuck with an invariant shape in all versions prior to this change.

As a result, assignements such as the following are causing type checking errors:

from numdantic import NDArray
import numpy as np

x: NDArray[tuple[int, int], np.int32] = ...
y: NDArray[tuple[int, ...], np.int32] = x  # <-- error: Incompatible types in assignment

This is despite the fact that tuple[int, int] is a valid subtype of tuple[int, ...], but since the shape parameter is invariant, the assignment is still rejected. The "easiest" way I see to circumvent this problem is to create a protocol class for the numpy.ndarray class which has a covariant shape as type parameter.

To perfectly mimic the entire interface of the class, this would require a lot of boilerplate. However, this would ensure that types behave as intended and would get rid of the problem of being unable to mix int, Literal and named axes in shapes, while maintaining the type safety that using ndarray directly has.

MilanStaffehl commented 2 months ago

The numpy PR for making shape covariant has been merged and is scheduled to be released with numpy 2.1.0, so this can be included immediately as well.