@@ -51,47 +51,39 @@ def dataclass_array_container(cls: type) -> type:
5151
5252 Attributes that are not array containers are allowed. In order to decide
5353 whether an attribute is an array container, the declared attribute type
54- is checked by the criteria from :func:`is_array_container_type`.
54+ is checked by the criteria from :func:`is_array_container_type`. This
55+ includes some support for type annotations:
56+
57+ * :class:`typing.Union` of array containers is allowed.
58+ * other type annotations, e.g. :class:`typing.Optional`, are not considered
59+ array containers, even if they wrap one.
5560 """
5661 from dataclasses import is_dataclass , Field
5762 assert is_dataclass (cls )
5863
59- def is_array_field ( f : Field ) -> bool :
64+ def is_array_type ( tp : type ) -> bool :
6065 from arraycontext import Array
66+ return tp is Array or is_array_container_type (tp )
6167
62- origin = get_origin (f .type )
63- if origin is Union :
64- if not all (
65- arg is Array or is_array_container_type (arg )
66- for arg in get_args (f .type )):
67- raise TypeError (
68- f"Field '{ f .name } ' union contains non-array container "
69- "arguments. All arguments must be array containers." )
70- else :
71- return True
72-
68+ def is_array_field (f : Field ) -> bool :
7369 if __debug__ :
7470 if not f .init :
7571 raise ValueError (
76- f"'init=False' field not allowed: '{ f .name } '" )
72+ f"Fields with 'init=False' not allowed: '{ f .name } '" )
7773
7874 if isinstance (f .type , str ):
7975 raise TypeError (
80- f"string annotation on field '{ f .name } ' not supported" )
76+ f"String annotation on field '{ f .name } ' not supported" )
8177
82- from typing import _SpecialForm
83- if isinstance (f .type , _SpecialForm ):
84- # NOTE: anything except a Union is not allowed
85- raise TypeError (
86- f"typing annotation not supported on field '{ f .name } ': "
87- f"'{ f .type !r} '" )
78+ origin = get_origin (f .type )
79+ if origin is Union :
80+ return all (is_array_type (arg ) for arg in get_args (f .type ))
8881
89- if not isinstance (f .type , type ):
90- raise TypeError (
91- f"field '{ f .name } ' not an instance of 'type': "
92- f"'{ f .type !r} '" )
82+ from typing import _GenericAlias , _SpecialForm
83+ if isinstance (f .type , (_GenericAlias , _SpecialForm )):
84+ return False
9385
94- return f . type is Array or is_array_container_type (f .type )
86+ return is_array_type (f .type )
9587
9688 from pytools import partition
9789 array_fields , non_array_fields = partition (is_array_field , fields (cls ))
0 commit comments