-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in 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: