@@ -2470,10 +2470,13 @@ def __init__(self, a):
24702470
24712471 self .assertEqual (D (5 ).a , 10 )
24722472
2473+
2474+ class TestInitAnnotate (unittest .TestCase ):
2475+ # Tests for the generated __annotate__ function for __init__
2476+ # See: https://github.com/python/cpython/issues/137530
2477+
24732478 def test_annotate_function (self ):
2474- # Test that the __init__ function has correct annotate function
2475- # See: https://github.com/python/cpython/issues/137530
2476- # With no forward references
2479+ # No forward references
24772480 @dataclass
24782481 class A :
24792482 a : int
@@ -2486,6 +2489,9 @@ class A:
24862489 self .assertEqual (forwardref_annos , {'a' : int , 'return' : None })
24872490 self .assertEqual (string_annos , {'a' : 'int' , 'return' : 'None' })
24882491
2492+ self .assertTrue (getattr (A .__init__ .__annotate__ , "_generated_by_dataclasses" ))
2493+
2494+ def test_annotate_function_forwardref (self ):
24892495 # With forward references
24902496 @dataclass
24912497 class B :
@@ -2512,26 +2518,53 @@ class B:
25122518 self .assertEqual (forwardref_annos , {'b' : int , 'return' : None })
25132519 self .assertEqual (string_annos , {'b' : 'undefined' , 'return' : 'None' })
25142520
2515- del undefined # Remove so we can use the name in later examples
2516-
2521+ def test_annotate_function_init_false (self ):
25172522 # Check `init=False` attributes don't get into the annotations of the __init__ function
25182523 @dataclass
25192524 class C :
25202525 c : str = field (init = False )
25212526
25222527 self .assertEqual (annotationlib .get_annotations (C .__init__ ), {'return' : None })
25232528
2524-
2529+ def test_annotate_function_contains_forwardref ( self ):
25252530 # Check string annotations on objects containing a ForwardRef
25262531 @dataclass
25272532 class D :
25282533 d : list [undefined ]
25292534
2535+ with self .assertRaises (NameError ):
2536+ annotationlib .get_annotations (D .__init__ )
2537+
2538+ self .assertEqual (
2539+ annotationlib .get_annotations (D .__init__ , format = annotationlib .Format .FORWARDREF ),
2540+ {"d" : list [support .EqualToForwardRef ("undefined" , is_class = True , owner = D )], "return" : None }
2541+ )
2542+
2543+ self .assertEqual (
2544+ annotationlib .get_annotations (D .__init__ , format = annotationlib .Format .STRING ),
2545+ {"d" : "list[undefined]" , "return" : "None" }
2546+ )
2547+
2548+ # Now test when it is defined
2549+ undefined = str
2550+
2551+ # VALUE should now resolve
2552+ self .assertEqual (
2553+ annotationlib .get_annotations (D .__init__ ),
2554+ {"d" : list [str ], "return" : None }
2555+ )
2556+
2557+ self .assertEqual (
2558+ annotationlib .get_annotations (D .__init__ , format = annotationlib .Format .FORWARDREF ),
2559+ {"d" : list [str ], "return" : None }
2560+ )
2561+
25302562 self .assertEqual (
25312563 annotationlib .get_annotations (D .__init__ , format = annotationlib .Format .STRING ),
25322564 {"d" : "list[undefined]" , "return" : "None" }
25332565 )
25342566
2567+ def test_annotate_function_not_replaced (self ):
25352568 # Check that __annotate__ is not replaced on non-generated __init__ functions
25362569 @dataclass (slots = True )
25372570 class E :
@@ -2543,6 +2576,26 @@ def __init__(self, x: int) -> None:
25432576 annotationlib .get_annotations (E .__init__ ), {"x" : int , "return" : None }
25442577 )
25452578
2579+ self .assertFalse (hasattr (E .__init__ .__annotate__ , "_generated_by_dataclasses" ))
2580+
2581+ def test_init_false_forwardref (self ):
2582+ # Currently this raises a NameError even though the ForwardRef
2583+ # is not in the __init__ method
2584+
2585+ @dataclass
2586+ class F :
2587+ not_in_init : list [undefined ] = field (init = False , default = None )
2588+ in_init : int
2589+
2590+ annos = annotationlib .get_annotations (F .__init__ , format = annotationlib .Format .FORWARDREF )
2591+ self .assertEqual (
2592+ annos ,
2593+ {"in_init" : int , "return" : None },
2594+ )
2595+
2596+ with self .assertRaises (NameError ):
2597+ annos = annotationlib .get_annotations (F .__init__ ) # NameError on not_in_init
2598+
25462599
25472600class TestRepr (unittest .TestCase ):
25482601 def test_repr (self ):
0 commit comments