@@ -219,7 +219,7 @@ def __repr__(self):
219219# String regex that string annotations for ClassVar or InitVar must match.
220220# Allows "identifier.identifier[" or "identifier[".
221221# https://bugs.python.org/issue33453 for details.
222- _MODULE_IDENTIFIER_RE = re .compile (r'^(?: \s*(\w+) \s*\.)? \s*( \w+)' )
222+ _MODULE_IDENTIFIER_RE = re .compile (r'^\s*(\w+(?: \s*\.\s*\w+)* )' )
223223
224224# Atomic immutable types which don't require any recursive handling and for which deepcopy
225225# returns the same object. We can provide a fast-path for these types in asdict and astuple.
@@ -711,9 +711,8 @@ def _is_kw_only(a_type, dataclasses):
711711 return a_type is dataclasses .KW_ONLY
712712
713713
714- def _is_type (annotation , cls , is_type_predicate , * is_type_predicate_args ):
715- # Loosely parse a string annotation and pass the result to is_type_predicate,
716- # along with any additional arguments it might require.
714+ def _get_type_from_annotation (annotation , cls ):
715+ # Loosely parse a string annotation and return its type.
717716
718717 # We can't perform a full type hint evaluation at the point where @dataclass
719718 # was invoked because class's module is not fully initialized yet. So we resort
@@ -722,9 +721,6 @@ def _is_type(annotation, cls, is_type_predicate, *is_type_predicate_args):
722721
723722 # - annotation is a string type annotation
724723 # - cls is the class that this annotation was found in
725- # - is_type_predicate is a function called with (obj, *is_type_predicate_args)
726- # that determines if obj is of the desired type.
727- # - is_type_predicate_args is additional arguments forwarded to is_type_predicate
728724
729725 # Since this test does not do a local namespace lookup (and
730726 # instead only a module (global) lookup), there are some things it
@@ -754,19 +750,15 @@ def _is_type(annotation, cls, is_type_predicate, *is_type_predicate_args):
754750 if not match :
755751 return False
756752
757- module_name = match .group (1 )
758- type_name = match .group (2 )
753+ * module_path , type_name = match .group (1 ).split ("." )
759754
760- if not module_name :
761- # No module name, assume the class's module did
762- # "from dataclasses import InitVar".
763- ns = sys .modules .get (cls .__module__ )
764- else :
765- # Look up module_name in the class's module.
766- cls_module = sys .modules .get (cls .__module__ )
767- ns = cls_module .__dict__ .get (module_name )
755+ ns = sys .modules .get (cls .__module__ )
756+ for module_path_item in module_path :
757+ ns = getattr (ns , module_path_item .strip (), None )
758+ if ns is None :
759+ return False
768760
769- return is_type_predicate ( getattr (ns , type_name , None ), * is_type_predicate_args )
761+ return getattr (ns , type_name . strip ( ), None )
770762
771763
772764def _get_field (cls , a_name , a_type , default_kw_only ):
@@ -804,16 +796,18 @@ def _get_field(cls, a_name, a_type, default_kw_only):
804796 # is actually of the correct type.
805797
806798 # For the complete discussion, see https://bugs.python.org/issue33453
799+ if isinstance (a_type , str ):
800+ a_type_annotation = _get_type_from_annotation (a_type , cls )
801+ else :
802+ a_type_annotation = a_type
807803
808804 # If typing has not been imported, then it's impossible for any
809805 # annotation to be a ClassVar. So, only look for ClassVar if
810806 # typing has been imported by any module (not necessarily cls's
811807 # module).
812808 typing = sys .modules .get ('typing' )
813809 if typing :
814- if (_is_classvar (a_type , typing )
815- or (isinstance (f .type , str )
816- and _is_type (f .type , cls , _is_classvar , typing ))):
810+ if _is_classvar (a_type_annotation , typing ):
817811 f ._field_type = _FIELD_CLASSVAR
818812
819813 # If the type is InitVar, or if it's a matching string annotation,
@@ -822,9 +816,7 @@ def _get_field(cls, a_name, a_type, default_kw_only):
822816 # The module we're checking against is the module we're
823817 # currently in (dataclasses.py).
824818 dataclasses = sys .modules [__name__ ]
825- if (_is_initvar (a_type , dataclasses )
826- or (isinstance (f .type , str )
827- and _is_type (f .type , cls , _is_initvar , dataclasses ))):
819+ if _is_initvar (a_type_annotation , dataclasses ):
828820 f ._field_type = _FIELD_INITVAR
829821
830822 # Validations for individual fields. This is delayed until now,
@@ -995,9 +987,11 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen,
995987 dataclasses = sys .modules [__name__ ]
996988 for name , type in cls_annotations .items ():
997989 # See if this is a marker to change the value of kw_only.
998- if (_is_kw_only (type , dataclasses )
999- or (isinstance (type , str )
1000- and _is_type (type , cls , _is_kw_only , dataclasses ))):
990+ if isinstance (type , str ):
991+ a_type_annotation = _get_type_from_annotation (type , cls )
992+ else :
993+ a_type_annotation = type
994+ if _is_kw_only (a_type_annotation , dataclasses ):
1001995 # Switch the default to kw_only=True, and ignore this
1002996 # annotation: it's not a real field.
1003997 if KW_ONLY_seen :
0 commit comments