@@ -1194,6 +1194,25 @@ class RaisesAttributeError:
11941194            },
11951195        )
11961196
1197+     def  test_raises_error_from_value (self ):
1198+         # test that if VALUE is the only supported format, but raises an error 
1199+         # that error is propagated from get_annotations 
1200+         class  DemoException (Exception ): ...
1201+ 
1202+         def  annotate (format , / ):
1203+             if  format  ==  Format .VALUE :
1204+                 raise  DemoException ()
1205+             else :
1206+                 raise  NotImplementedError (format )
1207+ 
1208+         def  f (): ...
1209+ 
1210+         f .__annotate__  =  annotate 
1211+ 
1212+         for  fmt  in  [Format .VALUE , Format .FORWARDREF , Format .STRING ]:
1213+             with  self .assertRaises (DemoException ):
1214+                 get_annotations (f , format = fmt )
1215+ 
11971216
11981217class  TestCallEvaluateFunction (unittest .TestCase ):
11991218    def  test_evaluation (self ):
@@ -1214,6 +1233,163 @@ def evaluate(format, exc=NotImplementedError):
12141233        )
12151234
12161235
1236+ class  TestCallAnnotateFunction (unittest .TestCase ):
1237+     # Tests for user defined annotate functions. 
1238+ 
1239+     # Format and NotImplementedError are provided as arguments so they exist in 
1240+     # the fake globals namespace. 
1241+     # This avoids non-matching conditions passing by being converted to stringifiers. 
1242+     # See: https://github.com/python/cpython/issues/138764 
1243+ 
1244+     def  test_user_annotate_value (self ):
1245+         def  annotate (format , / ):
1246+             if  format  ==  Format .VALUE :
1247+                 return  {"x" : str }
1248+             else :
1249+                 raise  NotImplementedError (format )
1250+ 
1251+         annotations  =  annotationlib .call_annotate_function (
1252+             annotate ,
1253+             Format .VALUE ,
1254+         )
1255+ 
1256+         self .assertEqual (annotations , {"x" : str })
1257+ 
1258+     def  test_user_annotate_forwardref_supported (self ):
1259+         # If Format.FORWARDREF is supported prefer it over Format.VALUE 
1260+         def  annotate (format , / , __Format = Format , __NotImplementedError = NotImplementedError ):
1261+             if  format  ==  __Format .VALUE :
1262+                 return  {'x' : str }
1263+             elif  format  ==  __Format .VALUE_WITH_FAKE_GLOBALS :
1264+                 return  {'x' : int }
1265+             elif  format  ==  __Format .FORWARDREF :
1266+                 return  {'x' : float }
1267+             else :
1268+                 raise  __NotImplementedError (format )
1269+ 
1270+         annotations  =  annotationlib .call_annotate_function (
1271+             annotate ,
1272+             Format .FORWARDREF 
1273+         )
1274+ 
1275+         self .assertEqual (annotations , {"x" : float })
1276+ 
1277+     def  test_user_annotate_forwardref_fakeglobals (self ):
1278+         # If Format.FORWARDREF is not supported, use Format.VALUE_WITH_FAKE_GLOBALS 
1279+         # before falling back to Format.VALUE 
1280+         def  annotate (format , / , __Format = Format , __NotImplementedError = NotImplementedError ):
1281+             if  format  ==  __Format .VALUE :
1282+                 return  {'x' : str }
1283+             elif  format  ==  __Format .VALUE_WITH_FAKE_GLOBALS :
1284+                 return  {'x' : int }
1285+             else :
1286+                 raise  __NotImplementedError (format )
1287+ 
1288+         annotations  =  annotationlib .call_annotate_function (
1289+             annotate ,
1290+             Format .FORWARDREF 
1291+         )
1292+ 
1293+         self .assertEqual (annotations , {"x" : int })
1294+ 
1295+     def  test_user_annotate_forwardref_value_fallback (self ):
1296+         # If Format.FORWARDREF and Format.VALUE_WITH_FAKE_GLOBALS are not supported 
1297+         # use Format.VALUE 
1298+         def  annotate (format , / , __Format = Format , __NotImplementedError = NotImplementedError ):
1299+             if  format  ==  __Format .VALUE :
1300+                 return  {"x" : str }
1301+             else :
1302+                 raise  __NotImplementedError (format )
1303+ 
1304+         annotations  =  annotationlib .call_annotate_function (
1305+             annotate ,
1306+             Format .FORWARDREF ,
1307+         )
1308+ 
1309+         self .assertEqual (annotations , {"x" : str })
1310+ 
1311+     def  test_user_annotate_string_supported (self ):
1312+         # If Format.STRING is supported prefer it over Format.VALUE 
1313+         def  annotate (format , / , __Format = Format , __NotImplementedError = NotImplementedError ):
1314+             if  format  ==  __Format .VALUE :
1315+                 return  {'x' : str }
1316+             elif  format  ==  __Format .VALUE_WITH_FAKE_GLOBALS :
1317+                 return  {'x' : int }
1318+             elif  format  ==  __Format .STRING :
1319+                 return  {'x' : "float" }
1320+             else :
1321+                 raise  __NotImplementedError (format )
1322+ 
1323+         annotations  =  annotationlib .call_annotate_function (
1324+             annotate ,
1325+             Format .STRING ,
1326+         )
1327+ 
1328+         self .assertEqual (annotations , {"x" : "float" })
1329+ 
1330+     def  test_user_annotate_string_fakeglobals (self ):
1331+         # If Format.STRING is not supported but Format.VALUE_WITH_FAKE_GLOBALS is 
1332+         # prefer that over Format.VALUE 
1333+         def  annotate (format , / , __Format = Format , __NotImplementedError = NotImplementedError ):
1334+             if  format  ==  __Format .VALUE :
1335+                 return  {'x' : str }
1336+             elif  format  ==  __Format .VALUE_WITH_FAKE_GLOBALS :
1337+                 return  {'x' : int }
1338+             else :
1339+                 raise  __NotImplementedError (format )
1340+ 
1341+         annotations  =  annotationlib .call_annotate_function (
1342+             annotate ,
1343+             Format .STRING ,
1344+         )
1345+ 
1346+         self .assertEqual (annotations , {"x" : "int" })
1347+ 
1348+     def  test_user_annotate_string_value_fallback (self ):
1349+         # If Format.STRING and Format.VALUE_WITH_FAKE_GLOBALS are not 
1350+         # supported fall back to Format.VALUE and convert to strings 
1351+         def  annotate (format , / , __Format = Format , __NotImplementedError = NotImplementedError ):
1352+             if  format  ==  __Format .VALUE :
1353+                 return  {"x" : str }
1354+             else :
1355+                 raise  __NotImplementedError (format )
1356+ 
1357+         annotations  =  annotationlib .call_annotate_function (
1358+             annotate ,
1359+             Format .STRING ,
1360+         )
1361+ 
1362+         self .assertEqual (annotations , {"x" : "str" })
1363+ 
1364+     def  test_condition_not_stringified (self ):
1365+         # Make sure the first condition isn't evaluated as True by being converted 
1366+         # to a _Stringifier 
1367+         def  annotate (format , / ):
1368+             if  format  ==  Format .FORWARDREF :
1369+                 return  {"x" : str }
1370+             else :
1371+                 raise  NotImplementedError (format )
1372+ 
1373+         with  self .assertRaises (NotImplementedError ):
1374+             annotationlib .call_annotate_function (annotate , Format .STRING )
1375+ 
1376+     def  test_error_from_value_raised (self ):
1377+         # Test that the error from format.VALUE is raised 
1378+         # if all formats fail 
1379+ 
1380+         class  DemoException (Exception ): ...
1381+ 
1382+         def  annotate (format , / ):
1383+             if  format  ==  Format .VALUE :
1384+                 raise  DemoException ()
1385+             else :
1386+                 raise  NotImplementedError (format )
1387+ 
1388+         for  fmt  in  [Format .VALUE , Format .FORWARDREF , Format .STRING ]:
1389+             with  self .assertRaises (DemoException ):
1390+                 annotationlib .call_annotate_function (annotate , format = fmt )
1391+ 
1392+ 
12171393class  MetaclassTests (unittest .TestCase ):
12181394    def  test_annotated_meta (self ):
12191395        class  Meta (type ):
0 commit comments