@@ -885,15 +885,15 @@ def _structure_optional(self, obj, union):
885885 # We can't actually have a Union of a Union, so this is safe.
886886 return self ._structure_func .dispatch (other )(obj , other )
887887
888- def _structure_tuple (self , obj : Any , tup : type [T ]) -> T :
888+ def _structure_tuple (self , obj : Iterable , tup : type [T ]) -> T :
889889 """Deal with structuring into a tuple."""
890890 tup_params = None if tup in (Tuple , tuple ) else tup .__args__
891891 has_ellipsis = tup_params and tup_params [- 1 ] is Ellipsis
892892 if tup_params is None or (has_ellipsis and tup_params [0 ] in ANIES ):
893893 # Just a Tuple. (No generic information.)
894894 return tuple (obj )
895895 if has_ellipsis :
896- # We're dealing with a homogenous tuple, Tuple [int, ...]
896+ # We're dealing with a homogenous tuple, tuple [int, ...]
897897 tup_type = tup_params [0 ]
898898 conv = self ._structure_func .dispatch (tup_type )
899899 if self .detailed_validation :
@@ -920,13 +920,6 @@ def _structure_tuple(self, obj: Any, tup: type[T]) -> T:
920920
921921 # We're dealing with a heterogenous tuple.
922922 exp_len = len (tup_params )
923- try :
924- len_obj = len (obj )
925- except TypeError :
926- pass # most likely an unsized iterator, eg generator
927- else :
928- if len_obj > exp_len :
929- exp_len = len_obj
930923 if self .detailed_validation :
931924 errors = []
932925 res = []
@@ -940,8 +933,8 @@ def _structure_tuple(self, obj: Any, tup: type[T]) -> T:
940933 )
941934 exc .__notes__ = [* getattr (exc , "__notes__" , []), msg ]
942935 errors .append (exc )
943- if len (res ) < exp_len :
944- problem = "Not enough" if len (res ) < len ( tup_params ) else "Too many"
936+ if len (obj ) != exp_len :
937+ problem = "Not enough" if len (res ) < exp_len else "Too many"
945938 exc = ValueError (f"{ problem } values in { obj !r} to structure as { tup !r} " )
946939 msg = f"Structuring { tup } "
947940 exc .__notes__ = [* getattr (exc , "__notes__" , []), msg ]
@@ -950,13 +943,12 @@ def _structure_tuple(self, obj: Any, tup: type[T]) -> T:
950943 raise IterableValidationError (f"While structuring { tup !r} " , errors , tup )
951944 return tuple (res )
952945
953- res = tuple (
946+ if len (obj ) != exp_len :
947+ problem = "Not enough" if len (obj ) < len (tup_params ) else "Too many"
948+ raise ValueError (f"{ problem } values in { obj !r} to structure as { tup !r} " )
949+ return tuple (
954950 [self ._structure_func .dispatch (t )(e , t ) for t , e in zip (tup_params , obj )]
955951 )
956- if len (res ) < exp_len :
957- problem = "Not enough" if len (res ) < len (tup_params ) else "Too many"
958- raise ValueError (f"{ problem } values in { obj !r} to structure as { tup !r} " )
959- return res
960952
961953 def _get_dis_func (
962954 self ,
@@ -971,11 +963,10 @@ def _get_dis_func(
971963 # logic.
972964 union_types = tuple (e for e in union_types if e is not NoneType )
973965
974- # TODO: technically both disambiguators could support TypedDicts and
975- # dataclasses...
966+ # TODO: technically both disambiguators could support TypedDicts too
976967 if not all (has (get_origin (e ) or e ) for e in union_types ):
977968 raise StructureHandlerNotFoundError (
978- "Only unions of attrs classes supported "
969+ "Only unions of attrs classes and dataclasses supported "
979970 "currently. Register a structure hook manually." ,
980971 type_ = union ,
981972 )
0 commit comments