@@ -762,9 +762,8 @@ def _is_kw_only(a_type, dataclasses):
762762 return a_type is dataclasses .KW_ONLY
763763
764764
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.
765+ def _get_type_from_annotation (annotation , cls ):
766+ # Loosely parse a string annotation and return its type.
768767
769768 # We can't perform a full type hint evaluation at the point where @dataclass
770769 # was invoked because class's module is not fully initialized yet. So we resort
@@ -773,9 +772,6 @@ def _is_type(annotation, cls, is_type_predicate, *is_type_predicate_args):
773772
774773 # - annotation is a string type annotation
775774 # - cls is the class that this annotation was found in
776- # - is_type_predicate is a function called with (obj, *is_type_predicate_args)
777- # that determines if obj is of the desired type.
778- # - is_type_predicate_args is additional arguments forwarded to is_type_predicate
779775
780776 # Since this test does not do a local namespace lookup (and
781777 # instead only a module (global) lookup), there are some things it
@@ -806,25 +802,21 @@ def _is_type(annotation, cls, is_type_predicate, *is_type_predicate_args):
806802 # https://github.com/python/cpython/issues/77634 for details.
807803 global _MODULE_IDENTIFIER_RE
808804 if _MODULE_IDENTIFIER_RE is None :
809- _MODULE_IDENTIFIER_RE = re .compile (r'(?: \s*(\w+) \s*\.)? \s*( \w+)' )
805+ _MODULE_IDENTIFIER_RE = re .compile (r'^ \s*(\w+(?: \s*\.\s*\w+)* )' )
810806
811807 match = _MODULE_IDENTIFIER_RE .prefixmatch (annotation )
812808 if not match :
813- return False
814-
815- module_name = match .group (1 )
816- type_name = match .group (2 )
809+ return None
817810
818- if not module_name :
819- # No module name, assume the class's module did
820- # "from dataclasses import InitVar".
821- ns = sys .modules .get (cls .__module__ )
822- else :
823- # Look up module_name in the class's module.
824- cls_module = sys .modules .get (cls .__module__ )
825- ns = cls_module .__dict__ .get (module_name )
811+ # Note: _MODULE_IDENTIFIER_RE guarantees that path is non-empty
812+ path = match .group (1 ).split ("." )
813+ root = sys .modules .get (cls .__module__ )
814+ for path_item in path :
815+ root = getattr (root , path_item .strip (), None )
816+ if root is None :
817+ return None
826818
827- return is_type_predicate ( getattr ( ns , type_name , None ), * is_type_predicate_args )
819+ return root
828820
829821
830822def _get_field (cls , a_name , a_type , default_kw_only ):
@@ -862,16 +854,18 @@ def _get_field(cls, a_name, a_type, default_kw_only):
862854 # is actually of the correct type.
863855
864856 # For the complete discussion, see https://bugs.python.org/issue33453
857+ if isinstance (a_type , str ):
858+ a_type_annotation = _get_type_from_annotation (a_type , cls )
859+ else :
860+ a_type_annotation = a_type
865861
866862 # If typing has not been imported, then it's impossible for any
867863 # annotation to be a ClassVar. So, only look for ClassVar if
868864 # typing has been imported by any module (not necessarily cls's
869865 # module).
870866 typing = sys .modules .get ('typing' )
871867 if typing :
872- if (_is_classvar (a_type , typing )
873- or (isinstance (f .type , str )
874- and _is_type (f .type , cls , _is_classvar , typing ))):
868+ if _is_classvar (a_type_annotation , typing ):
875869 f ._field_type = _FIELD_CLASSVAR
876870
877871 # If the type is InitVar, or if it's a matching string annotation,
@@ -880,9 +874,7 @@ def _get_field(cls, a_name, a_type, default_kw_only):
880874 # The module we're checking against is the module we're
881875 # currently in (dataclasses.py).
882876 dataclasses = sys .modules [__name__ ]
883- if (_is_initvar (a_type , dataclasses )
884- or (isinstance (f .type , str )
885- and _is_type (f .type , cls , _is_initvar , dataclasses ))):
877+ if _is_initvar (a_type_annotation , dataclasses ):
886878 f ._field_type = _FIELD_INITVAR
887879
888880 # Validations for individual fields. This is delayed until now,
@@ -1053,9 +1045,11 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
10531045 dataclasses = sys .modules [__name__ ]
10541046 for name , type in cls_annotations .items ():
10551047 # See if this is a marker to change the value of kw_only.
1056- if (_is_kw_only (type , dataclasses )
1057- or (isinstance (type , str )
1058- and _is_type (type , cls , _is_kw_only , dataclasses ))):
1048+ if isinstance (type , str ):
1049+ a_type_annotation = _get_type_from_annotation (type , cls )
1050+ else :
1051+ a_type_annotation = type
1052+ if _is_kw_only (a_type_annotation , dataclasses ):
10591053 # Switch the default to kw_only=True, and ignore this
10601054 # annotation: it's not a real field.
10611055 if KW_ONLY_seen :
0 commit comments