@@ -573,22 +573,6 @@ def _get_field(cls, a_name, a_type):
573573 return f
574574
575575
576- def _find_fields (cls ):
577- # Return a list of Field objects, in order, for this class (and no
578- # base classes). Fields are found from the class dict's
579- # __annotations__ (which is guaranteed to be ordered). Default
580- # values are from class attributes, if a field has a default. If
581- # the default value is a Field(), then it contains additional
582- # info beyond (and possibly including) the actual default value.
583- # Pseudo-fields ClassVars and InitVars are included, despite the
584- # fact that they're not real fields. That's dealt with later.
585-
586- # If __annotations__ isn't present, then this class adds no new
587- # annotations.
588- annotations = cls .__dict__ .get ('__annotations__' , {})
589- return [_get_field (cls , name , type ) for name , type in annotations .items ()]
590-
591-
592576def _set_new_attribute (cls , name , value ):
593577 # Never overwrites an existing attribute. Returns True if the
594578 # attribute already exists.
@@ -663,10 +647,25 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
663647 if getattr (b , _PARAMS ).frozen :
664648 any_frozen_base = True
665649
650+ # Annotations that are defined in this class (not in base
651+ # classes). If __annotations__ isn't present, then this class
652+ # adds no new annotations. We use this to compute fields that
653+ # are added by this class.
654+ # Fields are found from cls_annotations, which is guaranteed to be
655+ # ordered. Default values are from class attributes, if a field
656+ # has a default. If the default value is a Field(), then it
657+ # contains additional info beyond (and possibly including) the
658+ # actual default value. Pseudo-fields ClassVars and InitVars are
659+ # included, despite the fact that they're not real fields.
660+ # That's dealt with later.
661+ cls_annotations = cls .__dict__ .get ('__annotations__' , {})
662+
666663 # Now find fields in our class. While doing so, validate some
667664 # things, and set the default values (as class attributes)
668665 # where we can.
669- for f in _find_fields (cls ):
666+ cls_fields = [_get_field (cls , name , type )
667+ for name , type in cls_annotations .items ()]
668+ for f in cls_fields :
670669 fields [f .name ] = f
671670
672671 # If the class attribute (which is the default value for
@@ -685,6 +684,11 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
685684 else :
686685 setattr (cls , f .name , f .default )
687686
687+ # Do we have any Field members that don't also have annotations?
688+ for name , value in cls .__dict__ .items ():
689+ if isinstance (value , Field ) and not name in cls_annotations :
690+ raise TypeError (f'{ name !r} is a field but has no type annotation' )
691+
688692 # Check rules that apply if we are derived from any dataclasses.
689693 if has_dataclass_bases :
690694 # Raise an exception if any of our bases are frozen, but we're not.
0 commit comments