agronholm / agronholm/typeguard
Add suport for numpy structured arrays
- 主要言語
- Python
- スター
- 1.8k
- フォーク
- 145
- 平均マージ
- 8日 12時間
- マージ済み PR(30日)
- 1
説明
### Things to check first
- [x] I have searched the existing issues and didn't find my feature already requested there
### Feature description
This a copy and paste of a question I made recently in [StackOverflow](https://stackoverflow.com/questions/79488914/how-to-use-typeguard-for-numpy-structured-arrays/79489633#79489633) and the solution I found with some help of AI.
Not sure if this would work with numpy records.
**Feature resquested**
I want to implement functions that act on specific numpy structured arrays, but typeguard doesn't seem to work properly:
```python
import numpy as np
from typeguard import typechecked
mytype2 = np.dtype([("type", int), ("pos", float, 2)])
mytype3 = np.dtype([("type", int), ("pos", float, 3)])
@typechecked
def process(data: mytype3) -> None: # Variable not allowed in type expression Pylance
print(data)
data = np.array([(1, [2, 3])], dtype=mytype2)
process(data)
```
That works fine, when it should raise an error.
**My solution**
```python
from typing import Any
import numpy as np
from typeguard import (
TypeCheckError, TypeCheckerCallable, TypeCheckMemo,
checker_lookup_functions, typechecked
)
def checker_dtype(
value: Any, origin_type: np.dtype, args: tuple[Any, ...], memo: TypeCheckMemo
) -> None:
# Check if the value is a NumPy array
if not isinstance(value, np.ndarray):
raise TypeCheckError("is not an instance of numpy.ndarray")
# Check if the array's dtype matches the expected dtype
if value.dtype != origin_type:
raise TypeCheckError(f"expected dtype {origin_type}, but got {value.dtype}")
def lookup_dtype(
origin_type: Any, args: tuple[Any, ...], extras: tuple[Any, ...]
) -> TypeCheckerCallable | None:
# Return the checker if the annotation is a numpy dtype instance
if isinstance(origin_type, np.dtype):
return checker_dtype
return None
# Register the custom checker lookup function
checker_lookup_functions.append(lookup_dtype)
# Example usage
MyDtype2 = np.dtype([("type", int), ("pos", float, 2)])
MyDtype3 = np.dtype([("type", int), ("pos", float, 3)])
@typechecked
def process(data: MyDtype3) -> None: # Pylance still shows an error
print(data)
data = np.array([(1, [2, 3])], dtype=MyDtype2)
try:
process(data) # Raises TypeCheckError due to dtype mismatch
except TypeCheckError as e:
print(e)
data = np.array([(1, [2, 3, 4])], dtype=MyDtype3)
process(data) # No error raised
```
### Use case
This is necessary for a consistent use of numpy structured arrays.
コントリビューションガイド
評価
この issue はまだ評価されていません。