@@ -762,22 +762,20 @@ def _is_kw_only(a_type, dataclasses):
762762 return a_type is dataclasses .KW_ONLY
763763
764764
765- def _is_type (annotation , cls , a_module , a_type , is_type_predicate ):
766- # Given a type annotation string, does it refer to a_type in
767- # a_module? For example, when checking that annotation denotes a
768- # ClassVar, then a_module is typing, and a_type is
769- # typing.ClassVar.
765+ def _is_type (annotation , cls , is_type_predicate , * is_type_predicate_args ):
766+ # Loosely parse a string annotation and pass the result to is_type_predicate,
767+ # along with any additional arguments it might require.
770768
771- # It's possible to look up a_module given a_type, but it involves
772- # looking in sys.modules (again!), and seems like a waste since
773- # the caller already knows a_module.
769+ # We can't perform a full type hint evaluation at the point where @dataclass
770+ # was invoked because class's module is not fully initialized yet. So we resort
771+ # to parsing string annotation using regexp, and extracting a type before
772+ # the first square bracket.
774773
775774 # - annotation is a string type annotation
776775 # - cls is the class that this annotation was found in
777- # - a_module is the module we want to match
778- # - a_type is the type in that module we want to match
779- # - is_type_predicate is a function called with (obj, a_module)
776+ # - is_type_predicate is a function called with (obj, *is_type_predicate_args)
780777 # that determines if obj is of the desired type.
778+ # - is_type_predicate_args is additional arguments forwarded to is_type_predicate
781779
782780 # Since this test does not do a local namespace lookup (and
783781 # instead only a module (global) lookup), there are some things it
@@ -814,30 +812,19 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate):
814812 if not match :
815813 return False
816814
817- ns = None
818815 module_name = match .group (1 )
819816 type_name = match .group (2 )
820817
821818 if not module_name :
822819 # No module name, assume the class's module did
823820 # "from dataclasses import InitVar".
824- ns = sys .modules .get (cls .__module__ ). __dict__
821+ ns = sys .modules .get (cls .__module__ )
825822 else :
826823 # Look up module_name in the class's module.
827824 cls_module = sys .modules .get (cls .__module__ )
828- if not cls_module :
829- return False
825+ ns = cls_module .__dict__ .get (module_name )
830826
831- a_type_module = cls_module .__dict__ .get (module_name )
832- if (
833- isinstance (a_type_module , types .ModuleType )
834- # Handle cases when a_type is not defined in
835- # the referenced module, e.g. 'dataclasses.ClassVar[int]'
836- and a_type_module .__dict__ .get (type_name ) is a_type
837- ):
838- ns = sys .modules .get (a_type .__module__ ).__dict__
839-
840- return ns and is_type_predicate (ns .get (type_name ), a_module )
827+ return is_type_predicate (getattr (ns , type_name , None ), * is_type_predicate_args )
841828
842829
843830def _get_field (cls , a_name , a_type , default_kw_only ):
@@ -884,8 +871,7 @@ def _get_field(cls, a_name, a_type, default_kw_only):
884871 if typing :
885872 if (_is_classvar (a_type , typing )
886873 or (isinstance (f .type , str )
887- and _is_type (f .type , cls , typing , typing .ClassVar ,
888- _is_classvar ))):
874+ and _is_type (f .type , cls , _is_classvar , typing ))):
889875 f ._field_type = _FIELD_CLASSVAR
890876
891877 # If the type is InitVar, or if it's a matching string annotation,
@@ -896,8 +882,7 @@ def _get_field(cls, a_name, a_type, default_kw_only):
896882 dataclasses = sys .modules [__name__ ]
897883 if (_is_initvar (a_type , dataclasses )
898884 or (isinstance (f .type , str )
899- and _is_type (f .type , cls , dataclasses , dataclasses .InitVar ,
900- _is_initvar ))):
885+ and _is_type (f .type , cls , _is_initvar , dataclasses ))):
901886 f ._field_type = _FIELD_INITVAR
902887
903888 # Validations for individual fields. This is delayed until now,
@@ -1070,8 +1055,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
10701055 # See if this is a marker to change the value of kw_only.
10711056 if (_is_kw_only (type , dataclasses )
10721057 or (isinstance (type , str )
1073- and _is_type (type , cls , dataclasses , dataclasses .KW_ONLY ,
1074- _is_kw_only ))):
1058+ and _is_type (type , cls , _is_kw_only , dataclasses ))):
10751059 # Switch the default to kw_only=True, and ignore this
10761060 # annotation: it's not a real field.
10771061 if KW_ONLY_seen :
0 commit comments