-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
TypeError for generic numpy.ndarray fields #155
Comments
@konradhalas Please let me ask for your opinion on how I should address this issue. As I wrote in the issue above, generic type annotations for Lines 25 to 36 in d2206b2
ndarray is now considered a generic collection as per the code in is_generic_collection() , where the "old" ndarray is not:
These are a number of assumptions that would all have to be addressed in order for Therefore I would like to suggest adding an exception specifically for --- a/dacite/types.py
+++ b/dacite/types.py
@@ -142,11 +142,15 @@ def is_generic_collection(type_: Type) -> bool:
return False
origin = extract_origin_collection(type_)
try:
- return bool(origin and issubclass(origin, Collection))
+ return bool(origin and issubclass(origin, Collection) and not skip_generic_conversion(origin))
except (TypeError, AttributeError):
return False
+def skip_generic_conversion(origin: Type) -> bool:
+ return origin.__module__ == "numpy" and origin.__qualname__ == "ndarray"
+
+
def extract_generic(type_: Type, defaults: Tuple = ()) -> tuple:
try:
if hasattr(type_, "_special") and type_._special: which makes the conversion work for both One issue that still happens with this is that the converted value fails the type check at the end:
which happens because in Line 135 in d2206b2
>>> isinstance(numpy.array([1,2,3]), numpy.typing.NDArray[numpy.float64])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/tgp/.envs/dacite/lib64/python3.8/site-packages/numpy/typing/_generic_alias.py", line 137, in __instancecheck__
raise TypeError("isinstance() argument 2 cannot be a "
TypeError: isinstance() argument 2 cannot be a parameterized generic I am not entirely sure how to address this best. I have tried to add a check like --- a/dacite/types.py
+++ b/dacite/types.py
@@ -127,6 +127,9 @@ def is_instance(value: Any, type_: Type) -> bool:
return is_instance(value, extract_init_var(type_))
elif is_type_generic(type_):
return is_subclass(value, extract_generic(type_)[0])
+ elif is_generic(type_):
+ origin = extract_origin_collection(type_)
+ return isinstance(value, origin)
else:
try:
# As described in PEP 484 - section: "The numeric tower" which does work, but it makes the I have a PR more or less ready, but I would like to check whether you have any opinion on the proposed changes. Please let me know any thoughts you have. |
Yes - this is a problem for me too :(
|
Since numpy 1.21 the
numpy.ndarray
class is generic formypy
and needs to be annotated with type parameters, and unfortunately this means that I cannot usedacite.from_dict
any more when one member of the dictionary is such an ndarray.Minimal example:
In the code above,
Foo
works fine, but creatingBar
fails withIf I add
config=dacite.Config(check_types=False)
to thefrom_dict()
call it does not work, either, and fails with the same error.If I change the type of
Bar.x
fromnpt.NDArray[np.float64]
to a plainnp.ndarray
then it works again, but mypy complainsI am not exactly sure what that error message means. Is there anything I can do to work around this?
The text was updated successfully, but these errors were encountered: