From c9ca51c0e7e428df984db2711339cd99c99dbc16 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Thu, 1 Oct 2026 17:05:07 +0100 Subject: [PATCH] [3.15] gh-142349: Simplify lazy import resolution (GH-158282) Backport the shared lazy import resolver to Python 3.15, regenerate interpreter files, and update the ABI snapshot. Co-authored-by: Petr Viktorin Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- Doc/data/python3.15.abi | 16518 ++++++++-------- Include/internal/pycore_dict.h | 9 +- Include/internal/pycore_import.h | 14 +- Include/internal/pycore_interp_structs.h | 5 +- Include/internal/pycore_lazyimportobject.h | 24 +- Include/internal/pycore_opcode_metadata.h | 3 +- Include/internal/pycore_tstate.h | 3 + Include/internal/pycore_uop_metadata.h | 15 + Lib/test/test_lazy_import/__init__.py | 32 +- .../data/broken_module_chained_cause.py | 3 + .../data/broken_module_chained_context.py | 5 + .../data/broken_module_chained_suppressed.py | 2 + Modules/_testinternalcapi/test_cases.c.h | 112 +- Objects/dictobject.c | 122 +- Objects/lazyimportobject.c | 463 +- Objects/moduleobject.c | 133 +- Python/bytecodes.c | 83 +- Python/ceval.c | 91 +- Python/clinic/import.c.h | 4 +- Python/executor_cases.c.h | 88 +- Python/generated_cases.c.h | 112 +- Python/import.c | 484 +- Python/optimizer_cases.c.h | 7 +- Python/pystate.c | 4 + 24 files changed, 9212 insertions(+), 9124 deletions(-) create mode 100644 Lib/test/test_lazy_import/data/broken_module_chained_cause.py create mode 100644 Lib/test/test_lazy_import/data/broken_module_chained_context.py create mode 100644 Lib/test/test_lazy_import/data/broken_module_chained_suppressed.py diff --git a/Doc/data/python3.15.abi b/Doc/data/python3.15.abi index d769d6a764c62e..162c4e4857f247 100644 --- a/Doc/data/python3.15.abi +++ b/Doc/data/python3.15.abi @@ -1257,7 +1257,6 @@ - @@ -1277,6 +1276,7 @@ + @@ -1346,6 +1346,8 @@ + + @@ -1380,8 +1382,8 @@ - + @@ -1573,6 +1575,7 @@ + @@ -1996,7 +1999,7 @@ - + @@ -2019,7 +2022,7 @@ - + @@ -2034,7 +2037,7 @@ - + @@ -2070,7 +2073,7 @@ - + @@ -2086,10 +2089,10 @@ - + - + @@ -2177,11 +2180,11 @@ - + - + @@ -2193,14 +2196,14 @@ - + - + @@ -2219,7 +2222,7 @@ - + @@ -2247,7 +2250,7 @@ - + @@ -2289,7 +2292,7 @@ - + @@ -2306,7 +2309,7 @@ - + @@ -2334,43 +2337,43 @@ - - + + - + - + - + - + - + - + - + - + - + - + @@ -2378,7 +2381,7 @@ - + @@ -2425,7 +2428,7 @@ - + @@ -2458,7 +2461,7 @@ - + @@ -2483,7 +2486,7 @@ - + @@ -2527,7 +2530,7 @@ - + @@ -2961,11 +2964,11 @@ - + - + @@ -2988,30 +2991,30 @@ - + - + - + - + - - + + - - - + + + - - - + + + @@ -3838,7 +3841,7 @@ - + @@ -3892,7 +3895,7 @@ - + @@ -3935,20 +3938,20 @@ - - + + - + - + - + - + @@ -4007,7 +4010,7 @@ - + @@ -4017,7 +4020,7 @@ - + @@ -4096,9 +4099,9 @@ - - - + + + @@ -4118,14 +4121,14 @@ - + - + - + @@ -4140,7 +4143,7 @@ - + @@ -4183,24 +4186,24 @@ - + - + - + - + - + @@ -4218,7 +4221,7 @@ - + @@ -4246,7 +4249,7 @@ - + @@ -4294,24 +4297,24 @@ - - + + - + - - - - + + + + - + - - + + @@ -4335,31 +4338,31 @@ - + - - + + - - - - + + + + - - - + + + - - + + - - + + @@ -4378,7 +4381,7 @@ - + @@ -4467,7 +4470,7 @@ - + @@ -4504,10 +4507,10 @@ - + - + @@ -4522,25 +4525,25 @@ - - - - - - - + - + - + - + + + + + + + @@ -4558,21 +4561,21 @@ - + - - - + + + - - - + + + - + @@ -4710,12 +4713,12 @@ - + - + @@ -4728,13 +4731,13 @@ - + - + @@ -5355,7 +5358,7 @@ - + @@ -5399,7 +5402,7 @@ - + @@ -5601,11 +5604,11 @@ - + - + @@ -5724,41 +5727,35 @@ - - - - - - - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - + @@ -5816,7 +5813,7 @@ - + @@ -5902,111 +5899,111 @@ - - - + + + - - + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + @@ -6030,7 +6027,7 @@ - + @@ -6075,7 +6072,7 @@ - + @@ -6091,7 +6088,7 @@ - + @@ -6108,7 +6105,7 @@ - + @@ -6257,7 +6254,7 @@ - + @@ -6332,7 +6329,7 @@ - + @@ -6354,7 +6351,7 @@ - + @@ -6432,7 +6429,7 @@ - + @@ -6463,152 +6460,152 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + @@ -6786,205 +6783,205 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -7100,7 +7097,7 @@ - + @@ -7298,7 +7295,7 @@ - + @@ -7351,6 +7348,10 @@ + + + + @@ -7366,18 +7367,18 @@ - + - + - + @@ -7432,13 +7433,13 @@ - - + + - - - + + + @@ -7448,7 +7449,7 @@ - + @@ -7469,47 +7470,47 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -7538,25 +7539,21 @@ - + - + - + - - - - - + @@ -7574,295 +7571,289 @@ - - - + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - + + + - - - - + + + + + - - - - - - - - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - - - + + + + + + - - + + @@ -7871,7 +7862,7 @@ - + @@ -7880,7 +7871,7 @@ - + @@ -7922,10 +7913,6 @@ - - - - @@ -7942,7 +7929,7 @@ - + @@ -8116,129 +8103,129 @@ - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - - - - + + + + + + + - - - + + + - + @@ -8327,7 +8314,7 @@ - + @@ -8493,41 +8480,41 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - + @@ -8596,7 +8583,7 @@ - + @@ -8629,82 +8616,82 @@ - - + + - - - - - + + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + @@ -8727,83 +8714,90 @@ - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + - + + + + + + + + @@ -8841,7 +8835,7 @@ - + @@ -8940,7 +8934,7 @@ - + @@ -8949,15 +8943,15 @@ - + - + - + @@ -8994,54 +8988,54 @@ - - + + - - + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + @@ -9082,7 +9076,7 @@ - + @@ -9092,7 +9086,7 @@ - + @@ -9101,26 +9095,124 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + - + @@ -9133,7 +9225,7 @@ - + @@ -9197,13 +9289,13 @@ - - + + - - - + + + @@ -9212,7 +9304,7 @@ - + @@ -9496,81 +9588,81 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - + - + - - - + + + - + - + - + + + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - + @@ -9598,7 +9690,7 @@ - + @@ -9625,56 +9717,56 @@ - + - + - - + + - + - - + + - + - + - + - + - + - + - - + + - + - + - + @@ -9689,11 +9781,11 @@ - + - - + + @@ -9710,13 +9802,13 @@ - - + + - + @@ -9725,8 +9817,8 @@ - - + + @@ -9734,9 +9826,9 @@ - + - + @@ -9751,7 +9843,7 @@ - + @@ -9760,10 +9852,10 @@ - + - + @@ -9771,12 +9863,12 @@ - - - - - - + + + + + + @@ -9784,23 +9876,23 @@ - + - + - + - + - + @@ -9812,31 +9904,24 @@ - - - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + - + @@ -9849,22 +9934,33 @@ - + + + + + + + - + - + - + + + + + + @@ -9872,28 +9968,28 @@ - - - + + + - + - + - + - + - + @@ -9928,11 +10024,11 @@ - + - + @@ -9944,18 +10040,18 @@ - + - + - + @@ -9965,7 +10061,7 @@ - + @@ -10007,7 +10103,7 @@ - + @@ -10017,11 +10113,11 @@ - + - + @@ -10038,15 +10134,15 @@ - + - + - + - - + + @@ -10075,24 +10171,24 @@ - + - + - - + + - - - + + + @@ -10109,17 +10205,17 @@ - + - + - + @@ -10140,7 +10236,7 @@ - + @@ -10159,28 +10255,28 @@ - + - + - + - - - - + + + + @@ -10190,11 +10286,11 @@ - + - + @@ -10205,7 +10301,7 @@ - + @@ -10250,10 +10346,10 @@ - + - + @@ -10263,7 +10359,7 @@ - + @@ -10272,7 +10368,7 @@ - + @@ -10397,163 +10493,163 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - - + + + - + - - - + + + - - + + - - + + - + - + - - + + - + - - - - - - - + + + + + + + - + - + @@ -10561,8 +10657,8 @@ - - + + @@ -10591,7 +10687,7 @@ - + @@ -10600,7 +10696,7 @@ - + @@ -10609,41 +10705,41 @@ - + - + - + - + - - - - - - + + + + + + - + - + - - + + - + - + @@ -10652,31 +10748,31 @@ - - + + - + - + - + - + - + - + - + @@ -10688,7 +10784,7 @@ - + @@ -10703,7 +10799,7 @@ - + @@ -10717,8 +10813,8 @@ - - + + @@ -10726,109 +10822,109 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - - + + - + @@ -10843,17 +10939,17 @@ - + - + - + - - + + @@ -10861,22 +10957,22 @@ - + - + - + - + - + - + @@ -10884,26 +10980,26 @@ - - + + - - + + - - + + - + - + @@ -10911,209 +11007,209 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - + - - - - - + + + + + @@ -11131,17 +11227,17 @@ - + - - + + - + @@ -11166,7 +11262,7 @@ - + @@ -11244,58 +11340,54 @@ - + - - + + - + - - - + + + - - - + + + - - + + - - + + - - - - - - - + + + - - + + - - + + - + - + @@ -11305,48 +11397,48 @@ - + - + - + - + - + - + - - - - + + + + - - - + + + - + @@ -11361,8 +11453,8 @@ - - + + @@ -11376,10 +11468,10 @@ - - + + - + @@ -11396,7 +11488,7 @@ - + @@ -11405,11 +11497,11 @@ - - - + + + - + @@ -11417,8 +11509,8 @@ - - + + @@ -11432,7 +11524,7 @@ - + @@ -11441,16 +11533,16 @@ - + - - - - + + + + @@ -11465,34 +11557,25 @@ - + - - - + + + - - + + - - - - - - - - - - - + + - + @@ -11519,8 +11602,8 @@ - - + + @@ -11534,12 +11617,12 @@ - + - - - + + + @@ -11551,11 +11634,11 @@ - + - + @@ -11581,7 +11664,7 @@ - + @@ -11593,13 +11676,13 @@ - - - + + + - + @@ -11625,25 +11708,25 @@ - - - + + + - - - - + + + + - - - + + + - - + + @@ -11654,24 +11737,24 @@ - + - + - + - + - + - + @@ -11683,7 +11766,7 @@ - + @@ -11695,18 +11778,15 @@ - + - - - - - - - - - + + + + + + @@ -11740,70 +11820,70 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + @@ -11837,220 +11917,220 @@ - + - - + + - - + + - - + + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - - - - - + - - - + + + - - - - + + + + + + + + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - + - - + + - - - - - + + + + + - + @@ -12059,7 +12139,7 @@ - + @@ -12103,14 +12183,14 @@ - - - + + + - - + + @@ -12184,7 +12264,7 @@ - + @@ -12196,7 +12276,7 @@ - + @@ -12209,10 +12289,10 @@ - + - + @@ -12221,7 +12301,7 @@ - + @@ -12259,7 +12339,7 @@ - + @@ -12317,20 +12397,20 @@ - + - - - + + + - + - + - + @@ -12342,11 +12422,11 @@ - - - - - + + + + + @@ -12367,7 +12447,7 @@ - + @@ -12394,7 +12474,7 @@ - + @@ -12403,33 +12483,33 @@ - + - - - - + + + + - + - + - + - + @@ -12464,22 +12544,22 @@ - + - + - + - + @@ -12512,7 +12592,7 @@ - + @@ -12524,323 +12604,307 @@ - - - - - - - - + + + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - - - - - - - - - - - - + + + + + - - - - - - + + + + + + - - - - - - - - - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + @@ -12856,20 +12920,20 @@ - - - - + + + + - - - + + + - - - + + + @@ -12878,42 +12942,42 @@ - - + + - - - + + + - - + + - - + + - + - - + + - - + + - + - + @@ -12927,8 +12991,8 @@ - - + + @@ -12942,53 +13006,53 @@ - + - + - - + + - + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + @@ -13008,34 +13072,34 @@ - - + + - + - + - + - + - + - + - + - - + + @@ -13043,11 +13107,11 @@ - + - - + + @@ -13058,17 +13122,17 @@ - - - - - - - - - - - + + + + + + + + + + + @@ -13076,11 +13140,11 @@ - + - - + + @@ -13088,11 +13152,11 @@ - + - - + + @@ -13100,11 +13164,11 @@ - + - - + + @@ -13112,11 +13176,11 @@ - + - - + + @@ -13124,11 +13188,11 @@ - + - - + + @@ -13136,11 +13200,11 @@ - + - - + + @@ -13148,11 +13212,11 @@ - + - - + + @@ -13160,66 +13224,66 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -13250,12 +13314,12 @@ - + - + - + @@ -13270,269 +13334,269 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -13541,21 +13605,21 @@ - + - + - + - + - + - + @@ -13570,28 +13634,28 @@ - + - + - + - + - + - + - + - + - + @@ -13606,26 +13670,26 @@ - + - + - + - + - + - + - + - + @@ -13636,12 +13700,12 @@ - + - + - + @@ -13656,117 +13720,117 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -13781,59 +13845,59 @@ - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -13864,252 +13928,270 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + + + + - - - - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - + - - + + - + - - + + - + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - + + + + + + + + + - - - + + + - - + + - - + + - - + + - - - + + + + + + + + + + + + + + + + + + + + + @@ -14128,36 +14210,42 @@ + + + + + + - - + + - + - + - + - + - + - + @@ -14188,13 +14276,13 @@ - + - + @@ -14202,24 +14290,24 @@ - + - + - + - - + + @@ -14227,21 +14315,21 @@ - - + + - - - - + + + + - + @@ -14257,11 +14345,11 @@ - + - + @@ -14273,11 +14361,7 @@ - - - - - + @@ -14285,7 +14369,7 @@ - + @@ -14301,18 +14385,18 @@ - + - + - - + + @@ -14320,8 +14404,8 @@ - - + + @@ -14334,71 +14418,71 @@ - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - - + + @@ -14406,8 +14490,8 @@ - - + + @@ -14415,613 +14499,613 @@ - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + - - - + + + + - - - + + - + - - + + - + - - + + + - - + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - - + + + + + - - + + - - - - - + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - + - - + + - + - - + + - + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - - - + + + + - - - - - + + + + + - + - - + + - + - - + + - + - - + + - - - + + + - - + + - - - - + + + + - - + + - + - - + + - - + + - - + + - + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + @@ -15032,490 +15116,490 @@ - + - + - + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - - + - - - + + + + + - + - - + + - - + + - - - + + + - + - - - - + + + + - - - - - + + + + + - - + + - - + + - - + + + + + + + - - + + + - + - - - - - + + + + - - - - + + + + - - - + + + + - - - - - - - - - - - - - - - - + + + + + - - - - + + + + - - - - - + + + + - - - - + + + + + - - - - + + + + - - - - + - + + - + + - - - + + + - - - - - + + + + - + + - - - - - - - - + - + - - + - - - + + + + + + - - + - + + + - + + + + - - - + - - + + + + + + + + + + + - - + + - - - - - - + + + + + + - - + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + - + + - - + - + + - - + - + + - - - + + + - - + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + - - + + + - - + - + + - - + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - + + + + + + - - + + - - - - + + + + - - - + + + - - + + - + - - - + + + - - + + - + - - + + - - + + @@ -15523,15 +15607,15 @@ - - + + - + @@ -15541,194 +15625,194 @@ - - + + - + - + - + - - - + + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - - + + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - + - + - - - + + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -15742,7 +15826,7 @@ - + @@ -15778,178 +15862,181 @@ - - + + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - - + + - - + + - - + + - - - + + + - + - - + + - + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + - - + + - + - + @@ -15960,8 +16047,8 @@ - - + + @@ -15975,7 +16062,7 @@ - + @@ -16083,14 +16170,14 @@ - + - - - + + + @@ -16098,14 +16185,14 @@ - - + + - - - + + + @@ -16114,10 +16201,10 @@ - - - - + + + + @@ -16173,8 +16260,8 @@ - - + + @@ -16183,17 +16270,17 @@ - - - + + + - + - + @@ -16201,8 +16288,8 @@ - - + + @@ -16234,8 +16321,8 @@ - - + + @@ -16303,16 +16390,16 @@ - + - + - + - + @@ -16402,7 +16489,7 @@ - + @@ -16450,37 +16537,37 @@ - + - + - + - - + + - + - + - - + + - + @@ -16489,7 +16576,7 @@ - + @@ -16510,188 +16597,188 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - - - + + + - + - + - + - + - - + + - + - + - - + + @@ -16705,49 +16792,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -16762,16 +16849,16 @@ - + - + - + @@ -16789,25 +16876,25 @@ - + - + - + - + - + - + @@ -16828,13 +16915,13 @@ - + - + @@ -16846,31 +16933,31 @@ - + - - + + - - - + + + - + - + - - + + @@ -16896,54 +16983,54 @@ - - - + + + - - + + - + - + - + - + - - - + + + - + - - + + - + - - + + - + @@ -16955,8 +17042,8 @@ - - + + @@ -16970,7 +17057,7 @@ - + @@ -17009,100 +17096,103 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + + + + - + @@ -17128,28 +17218,28 @@ - + - + - + - + - - + + - + - + @@ -17160,8 +17250,8 @@ - - + + @@ -17178,7 +17268,7 @@ - + @@ -17189,13 +17279,13 @@ - + - - + + - + @@ -17204,18 +17294,18 @@ - - - - + + + + - + - + @@ -17224,7 +17314,7 @@ - + @@ -17241,10 +17331,10 @@ - - - - + + + + @@ -17252,25 +17342,25 @@ - + - - - + + + - - + + - - + + @@ -17286,20 +17376,20 @@ - - + + - - - - - - + + + + + + @@ -17307,11 +17397,11 @@ - + - - + + @@ -17319,11 +17409,11 @@ - + - - + + @@ -17331,11 +17421,11 @@ - + - - + + @@ -17343,11 +17433,11 @@ - + - - + + @@ -17379,12 +17469,12 @@ - + - + - + @@ -17399,349 +17489,349 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -17756,12 +17846,12 @@ - + - + - + @@ -17776,9 +17866,9 @@ - + - + @@ -18528,16 +18618,16 @@ - + - - - - - + + + + + @@ -18548,43 +18638,43 @@ - + - + - - - - + + + + - + - + - - - + + + - + - - + + - + - + - + - + @@ -18595,7 +18685,7 @@ - + @@ -18603,13 +18693,13 @@ - - + + - + - + @@ -18621,11 +18711,11 @@ - + - - + + @@ -18633,21 +18723,21 @@ - + - + - - + + - + - + - + @@ -18656,70 +18746,70 @@ - + - + - - - - + - + - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -18730,7 +18820,7 @@ - + @@ -18780,7 +18870,7 @@ - + @@ -18803,306 +18893,309 @@ - + - + - + - + - + - + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + @@ -19111,8 +19204,8 @@ - - + + @@ -19129,7 +19222,7 @@ - + @@ -19138,15 +19231,15 @@ - + - + - + - + @@ -19155,7 +19248,7 @@ - + @@ -19178,7 +19271,7 @@ - + @@ -19213,7 +19306,7 @@ - + @@ -19221,75 +19314,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -19303,2883 +19396,2909 @@ - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - - - - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - + - + - + - + - + - - + + - + - + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - - + + - - + + - - + + - + - + - + - + - - + + - + - - + + - + - + - + - + - + - - + + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + @@ -22188,22 +22307,22 @@ - - - - - - - + + + + + + + - + - + - - + + @@ -22211,78 +22330,78 @@ - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - + - + - + - + - - + + - + @@ -22291,12 +22410,12 @@ - + - + @@ -22308,7 +22427,7 @@ - + @@ -22317,19 +22436,19 @@ - + - - + + - + - + @@ -22344,17 +22463,17 @@ - + - + - + - + - + @@ -22363,10 +22482,10 @@ - + - + @@ -22375,7 +22494,7 @@ - + @@ -22384,7 +22503,7 @@ - + @@ -22392,28 +22511,28 @@ - + - + - - + + - + - + - + @@ -22421,19 +22540,19 @@ - + - - + + - + - + @@ -22441,10 +22560,10 @@ - - + + - + @@ -22453,7 +22572,7 @@ - + @@ -22479,31 +22598,31 @@ - + - + - + - + - + - + - + - + @@ -22511,13 +22630,13 @@ - + - + - + @@ -22541,32 +22660,32 @@ - + - + - + - + - + - + - + - + @@ -22598,312 +22717,309 @@ - + - + - - - - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -22915,408 +23031,408 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - - + + - + - - + + - - + + - + - + - + - + - + - + - - + + - + - + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + - - - - + - + - + - + - + - + - + - + - + @@ -23354,26 +23470,26 @@ - + - + - + - + - + - - + + - + @@ -23382,114 +23498,114 @@ - - + + - - + + - + - + - + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -23504,7 +23620,7 @@ - + @@ -23512,26 +23628,26 @@ - - + + - + - + - + - + - + - - + + - + @@ -23540,7 +23656,7 @@ - + @@ -23548,48 +23664,48 @@ - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + @@ -23610,18 +23726,18 @@ - + - + - + - + @@ -23629,7 +23745,7 @@ - + @@ -23638,30 +23754,30 @@ - + - + - + - + - - + + - + - + - + @@ -23670,243 +23786,243 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - - - - + - + - + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - - + + - - + + - + - + - - + + - + - - + + - - + + - + - + - - + + + + + - + - + @@ -23918,7 +24034,7 @@ - + @@ -23926,25 +24042,25 @@ - + - + - + - + - + - + - + @@ -23959,7 +24075,7 @@ - + @@ -23967,32 +24083,32 @@ - + - + - + - - + + - + - + @@ -24000,19 +24116,19 @@ - - + + - - + + - + @@ -24021,8 +24137,8 @@ - - + + @@ -24033,16 +24149,16 @@ - + - + - + @@ -24051,153 +24167,156 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - + - + - + - + - + - + - + + + + - + - - + + + + + - + - - - - + + + + - + - + - - - + + + - + - - - + + + @@ -24211,26 +24330,26 @@ - + - + - + - + - + @@ -24241,7 +24360,7 @@ - + @@ -24249,30 +24368,30 @@ - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -24280,22 +24399,22 @@ - - - - - - - - - + + + + + + + + + - - + + @@ -24330,37 +24449,37 @@ - - - + + + - - + + - - - - - - - + + + + + + + - - + + - + - + - + - + @@ -24368,44 +24487,44 @@ - - + + - + - - - + + + - + - + - - + + - + - + - - + + - + @@ -24417,22 +24536,22 @@ - + - + - + - - - - - - - - + + + + + + + + @@ -24455,30 +24574,30 @@ - + - + - + - + - - + + - + - + - + - + @@ -24487,33 +24606,33 @@ - + - - - - - - - + + + + + + + - + - - - + + + - + - - + + @@ -24521,9 +24640,9 @@ - - - + + + @@ -24537,36 +24656,36 @@ - + - + - + - + - + - + - + - + - + - + - + @@ -24574,7 +24693,7 @@ - + @@ -24582,10 +24701,10 @@ - + - + @@ -24593,10 +24712,10 @@ - + - + @@ -24613,7 +24732,7 @@ - + @@ -24621,18 +24740,18 @@ - + - + - + - + - + @@ -24640,7 +24759,7 @@ - + @@ -24648,7 +24767,7 @@ - + @@ -24659,8 +24778,8 @@ - - + + @@ -24671,9 +24790,9 @@ - - - + + + @@ -24711,10 +24830,10 @@ - + - + @@ -24723,31 +24842,31 @@ - + - + - + - + - + - + @@ -24759,25 +24878,25 @@ - + - - + + - - + + - + - + @@ -24803,19 +24922,19 @@ - + - + - + - + @@ -24848,175 +24967,175 @@ - + - + - - - - + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - - + + - - + + - - + + - - + + - + @@ -25027,11 +25146,11 @@ - + - - + + @@ -25054,14 +25173,14 @@ - + - - + + @@ -25069,10 +25188,10 @@ - - + + - + @@ -25081,7 +25200,7 @@ - + @@ -25089,8 +25208,8 @@ - - + + @@ -25104,13 +25223,13 @@ - - + + - + - + @@ -25122,10 +25241,10 @@ - + - + @@ -25161,10 +25280,10 @@ - + - + @@ -25176,184 +25295,184 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - - - + + + + + + @@ -25398,32 +25517,32 @@ - - + + - - + + - - + + - - + + - + - + @@ -25578,45 +25697,41 @@ - - + + - - + + - - + + - - + + - + - - - - - - + + - - + + - - + + @@ -25626,302 +25741,306 @@ - - + + - - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - - + + - - + + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -25937,12 +26056,6 @@ - - - - - - @@ -25968,18 +26081,13 @@ - - - - - - + @@ -25988,7 +26096,7 @@ - + @@ -26039,15 +26147,15 @@ - - - + + + - + - - + + @@ -26064,10 +26172,10 @@ - - + + - + @@ -26078,7 +26186,7 @@ - + @@ -26163,100 +26271,99 @@ - + - + - + - - - - - - - + + - + - + - + - + - + - + - - - - - + + + + + - + - - + + - + - + - - + + - + - + - + + + + + + + + + + + + - - - - - - - - - - - + + + + - - + + @@ -26270,7 +26377,7 @@ - + @@ -26293,13 +26400,13 @@ - + - + @@ -26312,8 +26419,8 @@ - - + + @@ -26325,11 +26432,7 @@ - - - - - + @@ -26400,8 +26503,8 @@ - - + + @@ -26451,7 +26554,7 @@ - + @@ -26462,8 +26565,8 @@ - - + + @@ -26471,10 +26574,10 @@ - + - + @@ -26483,13 +26586,13 @@ - - + + - + @@ -26510,11 +26613,11 @@ - + - - + + @@ -26528,17 +26631,17 @@ - - - - - + + + + + - + - + @@ -26547,7 +26650,7 @@ - + @@ -26559,8 +26662,8 @@ - - + + @@ -26574,40 +26677,30 @@ - - + + - + - + - + - - - - - - - - - + - - - - + + @@ -26652,21 +26745,21 @@ - + - + - + - + @@ -26676,20 +26769,20 @@ - + - + - + - + @@ -26698,7 +26791,7 @@ - + @@ -26709,7 +26802,7 @@ - + @@ -26721,19 +26814,19 @@ - + - + - + - + @@ -26741,7 +26834,7 @@ - + @@ -26758,13 +26851,13 @@ - + - + @@ -26808,42 +26901,42 @@ - - - + + + - - + + - + - - + + - + - - + + - + - - + + - + - + - - - + + + @@ -26854,33 +26947,33 @@ - - - + + + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -26889,8 +26982,8 @@ - - + + @@ -26901,25 +26994,25 @@ - + - + - + - + @@ -26927,11 +27020,11 @@ - - - - - + + + + + @@ -27041,19 +27134,14 @@ - + - - - - - - + @@ -27113,24 +27201,20 @@ - + - + - + - - - - @@ -27157,7 +27241,7 @@ - + @@ -27166,11 +27250,11 @@ - + - + @@ -27191,23 +27275,23 @@ - + - + - - + + - + @@ -27217,356 +27301,343 @@ - - + + - - - - + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - + + - - - + + + - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - + - + - + - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - + + + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - + - + @@ -27574,25 +27645,25 @@ - - + + - + - - - - - + + + + + - - - - + + + + @@ -27602,7 +27673,7 @@ - + @@ -27637,38 +27708,38 @@ - - + + - + - + - + - + - + - - + + - - + + @@ -27693,7 +27764,7 @@ - + @@ -27709,7 +27780,7 @@ - + @@ -27718,7 +27789,7 @@ - + @@ -27730,7 +27801,7 @@ - + @@ -27741,81 +27812,81 @@ - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - + @@ -27823,10 +27894,10 @@ - + - + @@ -27838,7 +27909,7 @@ - + @@ -27853,22 +27924,22 @@ - - + + - + - - + + - - + + - + - + @@ -27906,16 +27977,16 @@ - - + + - - + + @@ -27932,25 +28003,25 @@ - + - + - + - + - + - - + + @@ -27961,17 +28032,17 @@ - + - - + + - - + + @@ -27982,17 +28053,17 @@ - + - + - + - + @@ -28001,15 +28072,15 @@ - + - + - + - + @@ -28019,8 +28090,8 @@ - - + + @@ -28028,25 +28099,25 @@ - - + + - + - - + + - + - + @@ -28064,10 +28135,10 @@ - + - + @@ -28096,7 +28167,7 @@ - + @@ -28114,7 +28185,7 @@ - + @@ -28162,203 +28233,203 @@ - + - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - - - - + + + + - - + + - - + + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - - - - + + + + - - - + + + - - + + - + - + - + @@ -28368,15 +28439,15 @@ - - + + - - + + @@ -28386,76 +28457,76 @@ - + - + - + - - + + - + - + - + - + - - - - - - + + + + + + - + - + - + - + - + - - - + + + - - - - + + + + - + @@ -28476,10 +28547,10 @@ - + - + @@ -28491,28 +28562,28 @@ - + - + - - - - - + + + + + - + - - + + @@ -28522,33 +28593,33 @@ - + - - + + - - + + - - - + + + - + - + @@ -28557,23 +28628,23 @@ - - + + - - + + - + - + - + @@ -28583,20 +28654,20 @@ - - + + - - + + - + - + @@ -28606,9 +28677,9 @@ - + - + @@ -28617,213 +28688,213 @@ - + - + - + - - - - - - + + + + + + - - + + - - - - + + + + - - - - - + + + + + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - + - - + + - + - + - - - - + + + + - + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - + + - - + + @@ -28846,9 +28917,9 @@ - - - + + + @@ -28856,10 +28927,10 @@ - - + + - + @@ -28868,7 +28939,7 @@ - + @@ -28882,8 +28953,8 @@ - - + + @@ -28896,10 +28967,10 @@ - - - - + + + + @@ -28907,56 +28978,56 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + @@ -28973,11 +29044,11 @@ - - + + - + @@ -28987,10 +29058,10 @@ - + - + @@ -29037,12 +29108,12 @@ - + - + @@ -29083,31 +29154,31 @@ - + - + - + - + - + - + - + - + @@ -29118,151 +29189,151 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - - + + + - - - - - + + + + + - - - + + + - - + + - - - - - + + + + + - - - - + + + + @@ -29282,18 +29353,18 @@ - + - + - + @@ -29303,53 +29374,53 @@ - + - + - + - + - - - + + + - + - + - + - + - + @@ -29399,13 +29470,6 @@ - - - - - - - @@ -29474,28 +29538,28 @@ - - + + - + - + - + - - - - - + + + + + @@ -29539,7 +29603,7 @@ - + @@ -29592,15 +29656,15 @@ - + - - + + - + @@ -29617,28 +29681,28 @@ - - - - + + + + - - - - + + + + - - - + + + - - - - - + + + + + @@ -29653,8 +29717,8 @@ - - + + @@ -29668,25 +29732,25 @@ - + - + - + - - - - - - - - - + + + + + + + + + - + @@ -29745,8 +29809,8 @@ - - + + @@ -29776,30 +29840,30 @@ - - - + + + - - + + - - - + + + - - + + - + - + @@ -29841,7 +29905,7 @@ - + @@ -29861,7 +29925,7 @@ - + @@ -29869,7 +29933,7 @@ - + @@ -29877,7 +29941,7 @@ - + @@ -29889,21 +29953,21 @@ - + - + - - - + + + - + @@ -29912,61 +29976,61 @@ - - - + + + - + - + - - + + - + - - + + - - + + - - + + - - + + - + - + - + @@ -29983,41 +30047,41 @@ - + - + - + - + - + - + - + - + - + - + @@ -30027,10 +30091,10 @@ - - - - + + + + @@ -30038,66 +30102,56 @@ - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - + - + - + - + - + - + - - + + - - - + + + @@ -30112,7 +30166,7 @@ - + @@ -30132,7 +30186,7 @@ - + @@ -30145,148 +30199,142 @@ - - - - - - - + - - - + + + - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - + + + - + - + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - + + - - + + - - - + + + - - + + - + - - + + - + - - + + - - + + @@ -30298,16 +30346,16 @@ - + - - + + - + - + @@ -30322,48 +30370,48 @@ - - + + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - - + + - - + + - + @@ -30399,7 +30447,7 @@ - + @@ -30408,7 +30456,7 @@ - + @@ -30431,13 +30479,13 @@ - + - - + + @@ -30462,21 +30510,21 @@ - + - + - + - + @@ -30485,7 +30533,7 @@ - + @@ -30499,7 +30547,7 @@ - + @@ -30508,7 +30556,7 @@ - + @@ -30539,7 +30587,7 @@ - + @@ -30566,191 +30614,191 @@ - + - + - + - - + + - - + + - - + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - + + - + - - - + + + - + - - + + @@ -30758,211 +30806,211 @@ - - + + - - - - - + + + + + - + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - + - + - + - + - + - - + + - + - - + + - + - - - + + + - + - - + + - + - - - - - + + + + + - - - + + + @@ -31007,21 +31055,21 @@ - + - + - - - + + + @@ -31030,53 +31078,53 @@ - + - + - + - - + + - + - - - + + + - + - - + + - + - - - - - - + + + + + + @@ -31092,7 +31140,7 @@ - + @@ -31101,20 +31149,20 @@ - + - + - + - + @@ -31132,89 +31180,89 @@ - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - + - - - + + + - + - + - + @@ -31232,13 +31280,13 @@ - + - + - + @@ -31250,16 +31298,16 @@ - + - + - - - - + + + + @@ -31269,7 +31317,7 @@ - + @@ -31284,27 +31332,27 @@ - - + + - - + + - - + + - - + + - + - + @@ -31362,7 +31410,7 @@ - + @@ -31371,22 +31419,22 @@ - - + + - - - - + + + + - + - + @@ -31395,34 +31443,34 @@ - + - + - + - + - + - + @@ -31483,15 +31531,15 @@ - - - + + + - + @@ -31499,27 +31547,27 @@ - + - - + + - - + + - - + + - - + + @@ -31531,23 +31579,23 @@ - - + + - + - + - + @@ -31568,11 +31616,11 @@ - + - + @@ -31585,66 +31633,66 @@ - + - + - - + + - + - - - - + + + + - - + + - - + + - + - + - + - + - - + + - + - + - + - + - + - + @@ -31652,7 +31700,7 @@ - + @@ -31660,60 +31708,60 @@ - + - + - + - + - + - - - - - - + + + + + + - + - + - - + + - + - + - - - + + + - - - - - - - + + + + + + + @@ -31841,59 +31889,59 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -31925,7 +31973,7 @@ - + @@ -31960,7 +32008,7 @@ - + @@ -32143,37 +32191,37 @@ - + - + - + - + - + - + - + - + @@ -32206,10 +32254,10 @@ - + - + @@ -32283,7 +32331,7 @@ - + @@ -32292,12 +32340,12 @@ - - + + - + @@ -32308,79 +32356,79 @@ - - - - + + + + - - + + - - + + - + - + - + - + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - + - - - - - - - - + + + + + + + + @@ -32400,14 +32448,14 @@ - + - + - + @@ -32436,8 +32484,8 @@ - - + + @@ -32463,7 +32511,7 @@ - + @@ -32474,7 +32522,7 @@ - + @@ -32493,158 +32541,158 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - + + - + - - + + - - + + - - - + + + - + - + - - + + - - + + - + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - + + - + - + @@ -32658,8 +32706,8 @@ - - + + @@ -32669,9 +32717,9 @@ - + - + @@ -32682,8 +32730,8 @@ - - + + @@ -32695,8 +32743,8 @@ - - + + @@ -32713,151 +32761,151 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - - - - - + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - + + + - - + + @@ -32871,7 +32919,7 @@ - + @@ -32907,23 +32955,23 @@ - - - - - + + + + + - + - - + + - - + + @@ -33040,8 +33088,8 @@ - - + + @@ -33050,11 +33098,8 @@ - - - - - + + @@ -33074,14 +33119,14 @@ - - - + + + - + - - + + @@ -33173,23 +33218,23 @@ - + - - + + - - + + - + @@ -33206,18 +33251,18 @@ - - + + - + - + @@ -33225,31 +33270,31 @@ - + - - - - - - - - - - - + + + + + + + + - - + + + + + - - - + + + @@ -33267,39 +33312,39 @@ - + - + - + - - + + - + - + - + - + @@ -33331,7 +33376,7 @@ - + @@ -33340,34 +33385,34 @@ - + - + - + - + - - + + - + - + - + @@ -33397,29 +33442,29 @@ - + - + - + - + - + - - + + @@ -33433,8 +33478,8 @@ - - + + @@ -33447,7 +33492,7 @@ - + @@ -33482,21 +33527,30 @@ - - - - - + + + + + + + + + + + + + + - - - + + + - - - + + + diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index ff6588b3e9718c..37916fdf822ac0 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -23,6 +23,11 @@ PyAPI_FUNC(int) _PyDict_DelItemIf(PyObject *mp, PyObject *key, int (*predicate)(PyObject *value, void *arg), void *arg); +// Atomically replace an existing value if it is expected (by identity). +// Return 1 if replaced, 0 if absent or different, or -1 on error. +extern int _PyDict_ReplaceItemIf(PyObject *dict, PyObject *key, + PyObject *expected, PyObject *replacement); + // "KnownHash" variants // Export for '_asyncio' shared extension PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, @@ -146,8 +151,8 @@ PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyOb */ PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version); PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key); -PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); -PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *); +// Return the borrowed source dictionary, or NULL if absent or on error. +PyAPI_FUNC(PyObject *) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *); // Loads the __builtins__ object from the globals dict. Returns a new reference. extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals); diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h index 669e328c266d00..81448e23787fb3 100644 --- a/Include/internal/pycore_import.h +++ b/Include/internal/pycore_import.h @@ -32,20 +32,16 @@ extern int _PyImport_FixupBuiltin( PyObject *modules ); -extern PyObject * _PyImport_ResolveName( - PyThreadState *tstate, PyObject *name, PyObject *globals, int level); extern PyObject * _PyImport_GetAbsName( PyThreadState *tstate, PyObject *name, PyObject *globals, int level); // Symbol is exported for the JIT on Windows builds. PyAPI_FUNC(PyObject *) _PyImport_LoadLazyImportTstate( PyThreadState *tstate, PyObject *lazy_import); -typedef enum { - _Py_LAZY_SUBMODULE_ERROR = -1, - _Py_LAZY_SUBMODULE_NOT_FOUND = 0, - _Py_LAZY_SUBMODULE_LOADED = 1, -} _PyLazySubmoduleImportResult; -extern _PyLazySubmoduleImportResult _PyImport_TryLoadLazySubmodule( - PyObject *mod_name, PyObject *attr_name, PyObject **result); +// Bind a pending child on module before removing its registration. Return a +// new reference, NULL without an exception if absent, or NULL on error. +// Set recheck_dict if a concurrent lookup may have already bound the child. +extern PyObject * _PyImport_TryLoadLazySubmodule( + PyObject *module, PyObject *attr_name, int *recheck_dict); extern PyObject * _PyImport_LazyImportModuleLevelObject( PyThreadState *tstate, PyObject *name, PyObject *builtins, PyObject *globals, PyObject *locals, PyObject *fromlist, int level); diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index d8e83cf2ff5c9a..72270b9d12a02c 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -348,15 +348,12 @@ struct _import_state { PyObject *lazy_import_func; int lazy_imports_mode; PyObject *lazy_imports_filter; - PyObject *lazy_importing_modules; // The set stored in sys.lazy_modules if values that have been // lazily imported. This value is only for debugging/introspection // purposes and is not used by the runtime. PyObject *lazy_modules; // A dict mapping package names to a set of submodule names that - // have been imported lazily from packages which have been imported - // lazily. When the package is reified we need to add a - // LazyImportObject which refers to the submodule on the module. + // may need to be imported when an attribute is missing on the package. PyObject *lazy_pending_submodules; #ifdef Py_GIL_DISABLED PyMutex lazy_mutex; diff --git a/Include/internal/pycore_lazyimportobject.h b/Include/internal/pycore_lazyimportobject.h index b81e4211b08ff3..c3f8417c089316 100644 --- a/Include/internal/pycore_lazyimportobject.h +++ b/Include/internal/pycore_lazyimportobject.h @@ -14,20 +14,18 @@ extern "C" { PyAPI_DATA(PyTypeObject) PyLazyImport_Type; #define PyLazyImport_CheckExact(op) Py_IS_TYPE((op), &PyLazyImport_Type) -typedef struct { - PyObject_HEAD - PyObject *lz_builtins; - PyObject *lz_from; - PyObject *lz_attr; - // Frame information for the original import location. - PyCodeObject *lz_code; // Code object where the lazy import was created. - int lz_instr_offset; // Instruction offset where the lazy import was created. -} PyLazyImportObject; - - -PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import); PyAPI_FUNC(PyObject *) _PyLazyImport_New( - struct _PyInterpreterFrame *frame, PyObject *import_func, PyObject *from, PyObject *attr); + struct _PyInterpreterFrame *frame, PyObject *builtins, + PyObject *name, PyObject *fromlist); + +extern int _PyLazyImport_IsResolving(PyThreadState *tstate, PyObject *op); + +// Resolve a placeholder and replace its binding if it is unchanged or holds +// the child module published by the normal importer during resolution. +// namespace is the source captured during lookup, before resolution runs. +PyAPI_FUNC(PyObject *) _PyLazyImport_Reify( + PyThreadState *tstate, PyObject *placeholder, + PyObject *name, PyObject *ns); #ifdef __cplusplus } diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index d2e29a1b95ede2..7d9babf358971d 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1268,7 +1268,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG }, [LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG }, [LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_GLOBAL] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, @@ -1494,6 +1494,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_FAST_CHECK] = { .nuops = 1, .uops = { { _LOAD_FAST_CHECK, OPARG_SIMPLE, 0 } } }, [LOAD_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { _LOAD_FAST, OPARG_TOP, 0 }, { _LOAD_FAST, OPARG_BOTTOM, 0 } } }, [LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_DEREF, OPARG_SIMPLE, 0 } } }, + [LOAD_FROM_DICT_OR_GLOBALS] = { .nuops = 1, .uops = { { _LOAD_FROM_DICT_OR_GLOBALS, OPARG_SIMPLE, 0 } } }, [LOAD_GLOBAL] = { .nuops = 2, .uops = { { _LOAD_GLOBAL, OPARG_SIMPLE, 3 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 3 } } }, [LOAD_GLOBAL_BUILTIN] = { .nuops = 4, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_BUILTINS, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, OPERAND1_1, 3 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 4 } } }, [LOAD_GLOBAL_MODULE] = { .nuops = 4, .uops = { { _NOP, OPARG_SIMPLE, 1 }, { _LOAD_GLOBAL_MODULE, 1, 1 }, { _LOAD_GLOBAL_MODULE, OPERAND1_1, 3 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 4 } } }, diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index eb2b0c84acdc7c..58dd66b69efc9d 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -51,6 +51,9 @@ typedef struct _PyThreadStateImpl { PyObject *asyncio_running_loop; // Strong reference PyObject *asyncio_running_task; // Strong reference + // Reused for the thread's lifetime; owns placeholders while they resolve. + PyObject *lazy_imports; + // Distinguishes between yield and return from PyEval_EvalFrame(). // See gen_send_ex2() in Objects/genobject.c enum { diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 55b7f516020168..a61df9c29769d0 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -192,6 +192,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_STORE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_DELETE_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_LOAD_LOCALS] = HAS_ERROR_FLAG, + [_LOAD_FROM_DICT_OR_GLOBALS] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_LOAD_NAME] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_LOAD_GLOBAL] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_PUSH_NULL_CONDITIONAL] = HAS_ARG_FLAG, @@ -1862,6 +1863,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_LOAD_FROM_DICT_OR_GLOBALS] = { + .best = { 1, 1, 1, 1 }, + .entries = { + { -1, -1, -1 }, + { 1, 1, _LOAD_FROM_DICT_OR_GLOBALS_r11 }, + { -1, -1, -1 }, + { -1, -1, -1 }, + }, + }, [_LOAD_NAME] = { .best = { 0, 0, 0, 0 }, .entries = { @@ -4345,6 +4355,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_LOAD_LOCALS_r01] = _LOAD_LOCALS, [_LOAD_LOCALS_r12] = _LOAD_LOCALS, [_LOAD_LOCALS_r23] = _LOAD_LOCALS, + [_LOAD_FROM_DICT_OR_GLOBALS_r11] = _LOAD_FROM_DICT_OR_GLOBALS, [_LOAD_NAME_r01] = _LOAD_NAME, [_LOAD_GLOBAL_r00] = _LOAD_GLOBAL, [_PUSH_NULL_CONDITIONAL_r00] = _PUSH_NULL_CONDITIONAL, @@ -5868,6 +5879,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_FAST_CHECK_r23] = "_LOAD_FAST_CHECK_r23", [_LOAD_FROM_DICT_OR_DEREF] = "_LOAD_FROM_DICT_OR_DEREF", [_LOAD_FROM_DICT_OR_DEREF_r11] = "_LOAD_FROM_DICT_OR_DEREF_r11", + [_LOAD_FROM_DICT_OR_GLOBALS] = "_LOAD_FROM_DICT_OR_GLOBALS", + [_LOAD_FROM_DICT_OR_GLOBALS_r11] = "_LOAD_FROM_DICT_OR_GLOBALS_r11", [_LOAD_GLOBAL] = "_LOAD_GLOBAL", [_LOAD_GLOBAL_r00] = "_LOAD_GLOBAL_r00", [_LOAD_GLOBAL_BUILTINS] = "_LOAD_GLOBAL_BUILTINS", @@ -6538,6 +6551,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _LOAD_LOCALS: return 0; + case _LOAD_FROM_DICT_OR_GLOBALS: + return 1; case _LOAD_NAME: return 0; case _LOAD_GLOBAL: diff --git a/Lib/test/test_lazy_import/__init__.py b/Lib/test/test_lazy_import/__init__.py index 94e25597980fac..d92020abc7a565 100644 --- a/Lib/test/test_lazy_import/__init__.py +++ b/Lib/test/test_lazy_import/__init__.py @@ -13,7 +13,7 @@ import contextlib from test import support -from test.support.script_helper import assert_python_ok +from test.support.script_helper import assert_python_ok, assert_python_failure try: import _testcapi @@ -625,6 +625,14 @@ def test_dunder_lazy_import_invalid_arguments(self): with self.assertRaises(TypeError): __lazy_import__("sys", globals=1) + code = textwrap.dedent(""" + __lazy_import__("sys", fromlist=(1, 2, 3)) + """) + result = assert_python_failure("-c", code, NO_COLOR='y') + self.assertIn( + b"TypeError: Item in ``from list'' must be str, not int", + result.err) + def test_dunder_lazy_import_builtins(self): """__lazy_import__ should use module's __builtins__ for __import__.""" from test.test_lazy_import.data import dunder_lazy_import_builtins @@ -774,6 +782,28 @@ def test_missing_lazy_from_import_shows_chained_traceback(self): """) assert_python_ok("-c", code) + @support.subTests('name', ( + 'test.test_lazy_import.data.broken_module_chained_cause', + 'test.test_lazy_import.data.broken_module_chained_context', + 'test.test_lazy_import.data.broken_module_chained_suppressed', + )) + def test_chained_exception_import_shows_notes(self, name): + """Accessing missing attribute from lazy from-import should chain errors.""" + code = textwrap.dedent(f""" + lazy import {name} + + try: + _ = test + except ValueError as e: + assert any( + note.startswith("lazy import of '{name}' declared in ") + for note in e.__notes__ + ), e.__notes__ + else: + raise AssertionError("ImportError was not raised") + """) + assert_python_ok("-c", code) + def test_reification_retries_on_failure(self): """Failed reification should allow retry on subsequent access. diff --git a/Lib/test/test_lazy_import/data/broken_module_chained_cause.py b/Lib/test/test_lazy_import/data/broken_module_chained_cause.py new file mode 100644 index 00000000000000..786607b7bb557e --- /dev/null +++ b/Lib/test/test_lazy_import/data/broken_module_chained_cause.py @@ -0,0 +1,3 @@ +# Module that raises an exception with explicit cause during import +cause = ValueError("Cause of failure") +raise ValueError("This module always fails to import") from cause diff --git a/Lib/test/test_lazy_import/data/broken_module_chained_context.py b/Lib/test/test_lazy_import/data/broken_module_chained_context.py new file mode 100644 index 00000000000000..82640856e3e2d8 --- /dev/null +++ b/Lib/test/test_lazy_import/data/broken_module_chained_context.py @@ -0,0 +1,5 @@ +# Module that raises an exception with context during import +try: + raise ValueError("Cause of failure") +except: + raise ValueError("This module always fails to import") diff --git a/Lib/test/test_lazy_import/data/broken_module_chained_suppressed.py b/Lib/test/test_lazy_import/data/broken_module_chained_suppressed.py new file mode 100644 index 00000000000000..5c34654afc13bf --- /dev/null +++ b/Lib/test/test_lazy_import/data/broken_module_chained_suppressed.py @@ -0,0 +1,2 @@ +# Module that raises an exception with suppressed context during import +raise ValueError("This module always fails to import") from None diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index c51ed3c812523a..3e909c21e44044 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -9520,6 +9520,15 @@ JUMP_TO_LABEL(error); } } + else if (PyLazyImport_CheckExact(value_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(value_o, _PyLazyImport_Reify( + tstate, value_o, name, class_dict)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (value_o == NULL) { + JUMP_TO_LABEL(error); + } + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -9544,10 +9553,19 @@ _PyStackRef v; mod_or_class_dict = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *namespace = PyStackRef_AsPyObjectBorrow(mod_or_class_dict); int err; _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *v_o = _PyMapping_GetOptionalItem2(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &err); + PyObject *v_o = _PyMapping_GetOptionalItem2(namespace, name, &err); stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o != NULL && PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(v_o, _PyLazyImport_Reify(tstate, v_o, name, namespace)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + err = -1; + } + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -9557,68 +9575,16 @@ JUMP_TO_LABEL(error); } if (v_o == NULL) { - if (PyDict_CheckExact(GLOBALS()) - && PyDict_CheckExact(BUILTINS())) - { - _PyFrame_SetStackPointer(frame, stack_pointer); - v_o = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), - (PyDictObject *)BUILTINS(), - name); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - JUMP_TO_LABEL(error); - } - if (PyLazyImport_CheckExact(v_o)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - JUMP_TO_LABEL(error); - } - } - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - v_o = _PyMapping_GetOptionalItem2(GLOBALS(), name, &err); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - JUMP_TO_LABEL(error); - } - if (v_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - v_o = _PyMapping_GetOptionalItem2(BUILTINS(), name, &err); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - JUMP_TO_LABEL(error); - } - if (v_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - } - if (PyLazyImport_CheckExact(v_o)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - JUMP_TO_LABEL(error); - } - } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, &v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsNull(v)) { + JUMP_TO_LABEL(error); } } - v = PyStackRef_FromPyObjectSteal(v_o); + else { + v = PyStackRef_FromPyObjectSteal(v_o); + } stack_pointer[0] = v; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -9868,30 +9834,6 @@ if (v_o == NULL) { JUMP_TO_LABEL(error); } - if (PyLazyImport_CheckExact(v_o)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (l_v == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(v_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = PyDict_SetItem(GLOBALS(), name, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(v_o); - Py_DECREF(l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - } v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[0] = v; stack_pointer += 1; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index b31cb8f14ebc70..116a6d304e0796 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1958,6 +1958,35 @@ _PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ss ASSERT_CONSISTENT(mp); } +// Replace a value at an existing entry. Steals the new value reference. +static void +replace_value(PyDictObject *mp, PyObject *key, Py_ssize_t ix, + PyObject *old_value, PyObject *value) +{ + assert(can_modify_dict(mp)); + assert(old_value != NULL); + + if (old_value != value) { + _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, mp, key, value); + if (DK_IS_UNICODE(mp->ma_keys)) { + if (_PyDict_HasSplitTable(mp)) { + STORE_SPLIT_VALUE(mp, ix, value); + } + else { + PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix]; + STORE_VALUE(ep, value); + } + } + else { + PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix]; + STORE_VALUE(ep, value); + } + } + Py_DECREF(old_value); /* which **CAN** re-enter (see gh-66843) */ + + ASSERT_CONSISTENT(mp); +} + /* Internal routine to insert a new item into the table. Used both by the internal resize routine and by the public insert routine. @@ -2005,25 +2034,7 @@ insertdict(PyDictObject *mp, return 0; } - if (old_value != value) { - _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, mp, key, value); - assert(old_value != NULL); - if (DK_IS_UNICODE(mp->ma_keys)) { - if (_PyDict_HasSplitTable(mp)) { - STORE_SPLIT_VALUE(mp, ix, value); - } - else { - PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix]; - STORE_VALUE(ep, value); - } - } - else { - PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix]; - STORE_VALUE(ep, value); - } - } - Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */ - ASSERT_CONSISTENT(mp); + replace_value(mp, key, ix, old_value, value); Py_DECREF(key); return 0; @@ -2649,44 +2660,7 @@ _PyDict_GetItemStringWithError(PyObject *v, const char *key) return rv; } -/* Fast version of global value lookup (LOAD_GLOBAL). - * Lookup in globals, then builtins. - * - * - * - * - * Raise an exception and return NULL if an error occurred (ex: computing the - * key hash failed, key comparison failed, ...). Return NULL if the key doesn't - * exist. Return the value if the key exists. - * - * Returns a new reference. - */ PyObject * -_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) -{ - Py_ssize_t ix; - Py_hash_t hash; - PyObject *value; - - hash = _PyObject_HashFast(key); - if (hash == -1) { - return NULL; - } - - /* namespace 1: globals */ - ix = _Py_dict_lookup_threadsafe(globals, key, hash, &value); - if (ix == DKIX_ERROR) - return NULL; - if (ix != DKIX_EMPTY && value != NULL) - return value; - - /* namespace 2: builtins */ - ix = _Py_dict_lookup_threadsafe(builtins, key, hash, &value); - assert(ix >= 0 || value == NULL); - return value; -} - -void _PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObject *key, _PyStackRef *res) { Py_ssize_t ix; @@ -2695,21 +2669,22 @@ _PyDict_LoadGlobalStackRef(PyDictObject *globals, PyDictObject *builtins, PyObje hash = _PyObject_HashFast(key); if (hash == -1) { *res = PyStackRef_NULL; - return; + return NULL; } /* namespace 1: globals */ ix = _Py_dict_lookup_threadsafe_stackref(globals, key, hash, res); if (ix == DKIX_ERROR) { - return; + return NULL; } if (ix != DKIX_EMPTY && !PyStackRef_IsNull(*res)) { - return; + return (PyObject *)globals; } /* namespace 2: builtins */ ix = _Py_dict_lookup_threadsafe_stackref(builtins, key, hash, res); assert(ix >= 0 || PyStackRef_IsNull(*res)); + return PyStackRef_IsNull(*res) ? NULL : (PyObject *)builtins; } PyObject * @@ -3054,6 +3029,35 @@ _PyDict_DelItemIf(PyObject *op, PyObject *key, return res; } +int +_PyDict_ReplaceItemIf(PyObject *op, PyObject *key, + PyObject *expected, PyObject *replacement) +{ + assert(PyDict_Check(op)); + assert(expected != NULL); + assert(replacement != NULL); + + Py_hash_t hash = PyObject_Hash(key); + if (hash == -1) { + return -1; + } + int result = 0; + Py_BEGIN_CRITICAL_SECTION(op); + PyDictObject *mp = (PyDictObject *)op; + PyObject *current; + Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, ¤t); + if (ix == DKIX_ERROR) { + result = -1; + } + else if (current == expected) { + // Do not look up the key again: equality can execute Python code. + replace_value(mp, key, ix, current, Py_NewRef(replacement)); + result = 1; + } + Py_END_CRITICAL_SECTION(); + return result; +} + static void clear_embedded_values(PyDictValues *values, Py_ssize_t nentries) { diff --git a/Objects/lazyimportobject.c b/Objects/lazyimportobject.c index e008c076352ebb..e4a949a5456cfd 100644 --- a/Objects/lazyimportobject.c +++ b/Objects/lazyimportobject.c @@ -2,18 +2,39 @@ #include "Python.h" #include "pycore_ceval.h" -#include "pycore_frame.h" +#include "pycore_dict.h" +#include "pycore_gc.h" #include "pycore_import.h" #include "pycore_interpframe.h" #include "pycore_lazyimportobject.h" -#include "pycore_modsupport.h" +#include "pycore_long.h" +#include "pycore_moduleobject.h" +#include "pycore_pyerrors.h" +#include "pycore_traceback.h" +#include "pycore_tstate.h" + +typedef struct { + PyObject_HEAD + PyObject *lz_builtins; // Roots own the mapping; projections retain the root. + // A root stores its absolute name (PyUnicode) in lz_from, and original + // fromlist in lz_attr. + // A projection stores its source placeholder (a PyLazyImportObject) + // in lz_from, and the attribute to import from (PyUnicode) it in lz_attr. + PyObject *lz_from; + PyObject *lz_attr; + // Declaration location. + PyCodeObject *lz_code; + int lz_instr_offset; +} PyLazyImportObject; #define PyLazyImportObject_CAST(op) ((PyLazyImportObject *)(op)) +static PyObject *lazy_import_name(PyLazyImportObject *m); + PyObject * -_PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins, PyObject *name, PyObject *fromlist) +_PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins, + PyObject *name, PyObject *fromlist) { - PyLazyImportObject *m; if (!name || !(PyUnicode_Check(name) || PyLazyImport_CheckExact(name))) { PyErr_SetString(PyExc_TypeError, "expected str or lazy_import for name"); return NULL; @@ -26,7 +47,20 @@ _PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins, PyObject *name "lazy_import: fromlist must be None, a string, or a tuple"); return NULL; } - m = PyObject_GC_New(PyLazyImportObject, &PyLazyImport_Type); +#ifndef NDEBUG + if (PyLazyImport_CheckExact(name)) { + // projection + assert(builtins == NULL); + assert(fromlist != NULL); + assert(PyUnicode_Check(fromlist)); + } + else { + // root + assert(builtins != NULL); + } +#endif + PyLazyImportObject *m = PyObject_GC_New( + PyLazyImportObject, &PyLazyImport_Type); if (m == NULL) { return NULL; } @@ -34,23 +68,83 @@ _PyLazyImport_New(_PyInterpreterFrame *frame, PyObject *builtins, PyObject *name m->lz_from = Py_NewRef(name); m->lz_attr = Py_XNewRef(fromlist); - // Capture frame information for the original import location. m->lz_code = NULL; m->lz_instr_offset = -1; if (frame != NULL) { - PyCodeObject *code = _PyFrame_GetCode(frame); - if (code != NULL) { - m->lz_code = (PyCodeObject *)Py_NewRef(code); - // Calculate the instruction offset from the current frame. - m->lz_instr_offset = _PyInterpreterFrame_LASTI(frame); - } + m->lz_code = (PyCodeObject *)Py_NewRef(_PyFrame_GetCode(frame)); + m->lz_instr_offset = _PyInterpreterFrame_LASTI(frame); } _PyObject_GC_TRACK(m); return (PyObject *)m; } +// Reuse concrete attributes of initialized modules without waiting for imports +// or resolving lazy attributes. Failed cache lookups are retried at resolution. +// May return NULL with or without an exception set. +static PyObject * +lazy_import_get_loaded_attr(PyThreadState *tstate, PyObject *name, + PyObject *attr_name) +{ + PyObject *mod = NULL, *spec = NULL, *current = NULL, *attr = NULL; + PyObject *modules = Py_XNewRef(_PyImport_GetModules(tstate->interp)); + if (modules == NULL) { + return NULL; + } + int rc = PyMapping_GetOptionalItem(modules, name, &mod); + if (rc <= 0 || !PyModule_Check(mod)) { + goto done; + } + PyObject *dict = _PyModule_GetDict(mod); + if (PyObject_GetOptionalAttr(mod, &_Py_ID(__spec__), &spec) < 0 || + _PyModuleSpec_IsInitializing(spec) != 0) { + goto done; + } + // An initialization check can replace the module in sys.modules. + if (modules != _PyImport_GetModules(tstate->interp) || + PyMapping_GetOptionalItem(modules, name, ¤t) <= 0 || + current != mod) { + goto done; + } + if (PyDict_GetItemRef(dict, attr_name, &attr) < 0) { + goto done; + } + if (attr != NULL && PyLazyImport_CheckExact(attr)) { + Py_CLEAR(attr); + } + +done: + Py_XDECREF(current); + Py_XDECREF(spec); + Py_XDECREF(mod); + Py_DECREF(modules); + if (PyErr_ExceptionMatches(PyExc_Exception)) { + PyErr_Clear(); + } + return attr; +} + +PyObject * +_PyEval_LazyImportFrom(PyThreadState *tstate, _PyInterpreterFrame *frame, + PyObject *v, PyObject *name) +{ + assert(PyLazyImport_CheckExact(v)); + assert(name); + assert(PyUnicode_Check(name)); + PyLazyImportObject *lz = PyLazyImportObject_CAST(v); + // Only `from a import b` can take b off an already imported a; + // `import a.b as c` has to import a.b first. + if (lz->lz_attr != NULL && PyTuple_Check(lz->lz_attr) && + PyTuple_GET_SIZE(lz->lz_attr) > 0) { + PyObject *attr = lazy_import_get_loaded_attr(tstate, lz->lz_from, name); + if (attr != NULL || PyErr_Occurred()) { + return attr; + } + } + return _PyLazyImport_New(frame, NULL, v, name); +} + static int lazy_import_traverse(PyObject *op, visitproc visit, void *arg) { @@ -85,23 +179,20 @@ lazy_import_dealloc(PyObject *op) static PyObject * lazy_import_getattro(PyObject *op, PyObject *name) { - PyObject *value = _PyObject_GenericGetAttrWithDict(op, name, NULL, /* suppress */1); - if (value == NULL) { - if (PyErr_Occurred()) { - // pass up non-AttributeError exception - return NULL; - } - PyObject *lz_name = _PyLazyImport_GetName(op); - if (lz_name == NULL) { - return NULL; - } - PyErr_Format(PyExc_AttributeError, - "cannot access attribute %R on unresolved lazy import %R", - name, lz_name); - Py_DECREF(lz_name); + PyObject *value = _PyObject_GenericGetAttrWithDict( + op, name, NULL, /* suppress */ 1); + if (value != NULL || PyErr_Occurred()) { + return value; + } + PyObject *lz_name = lazy_import_name(PyLazyImportObject_CAST(op)); + if (lz_name == NULL) { return NULL; } - return value; + PyErr_Format(PyExc_AttributeError, + "cannot access attribute %R on unresolved lazy import %R", + name, lz_name); + Py_DECREF(lz_name); + return NULL; } // The dotted name of the object that resolving the placeholder returns. @@ -160,12 +251,320 @@ lazy_import_repr(PyObject *op) return res; } -PyObject * -_PyLazyImport_GetName(PyObject *op) +// Consume a result, resolving a placeholder returned by an import hook or +// an attribute lookup under the same cycle and recursion checks. +static PyObject * +lazy_import_resolve_result(PyThreadState *tstate, PyObject *obj) +{ + if (obj == NULL || !PyLazyImport_CheckExact(obj)) { + return obj; + } + PyObject *result = _PyImport_LoadLazyImportTstate(tstate, obj); + Py_DECREF(obj); + return result; +} + +// Look up, in order, the attributes recorded from the root placeholder to lz +// on the module the root's import returned. +static PyObject * +lazy_import_replay_from(PyThreadState *tstate, PyObject *mod, + PyLazyImportObject *lz) +{ + if (!PyLazyImport_CheckExact(lz->lz_from)) { + return Py_NewRef(mod); + } + PyObject *from = lazy_import_replay_from( + tstate, mod, (PyLazyImportObject *)lz->lz_from); + if (from == NULL) { + return NULL; + } + PyObject *obj = _PyEval_ImportFrom(tstate, from, lz->lz_attr); + Py_DECREF(from); + return lazy_import_resolve_result(tstate, obj); +} + +// Preserve the resolution error and attach the import's declaration location. +static void +lazy_import_add_exception_cause(PyThreadState *tstate, PyLazyImportObject *lz) { - PyLazyImportObject *lazy_import = PyLazyImportObject_CAST(op); + if (!PyErr_Occurred() || lz->lz_code == NULL || lz->lz_instr_offset < 0) { + return; + } + PyObject *exc = _PyErr_GetRaisedException(tstate); + PyObject *name = lazy_import_name(lz); + if (name == NULL) { + goto done; + } + int lineno = PyCode_Addr2Line(lz->lz_code, lz->lz_instr_offset * 2); + const char *filename = PyUnicode_AsUTF8(lz->lz_code->co_filename); + if (filename == NULL) { + goto done; + } + const char *funcname = PyUnicode_AsUTF8(lz->lz_code->co_name); + if (funcname == NULL) { + goto done; + } + PyBaseExceptionObject *base_exc = (PyBaseExceptionObject *)exc; + if (base_exc->cause != NULL || base_exc->context != NULL || + base_exc->suppress_context) { + // Preserve the original chain, including `raise ... from None`. + PyObject *note = PyUnicode_FromFormat( + "lazy import of '%U' declared in %s at %s:%d", + name, funcname, filename, lineno); + if (note != NULL) { + PyObject *notes; + if (PyObject_GetOptionalAttr(exc, &_Py_ID(__notes__), ¬es) >= 0) { + if (notes == NULL || PySequence_Contains(notes, note) == 0) { + (void)_PyException_AddNote(exc, note); + } + Py_XDECREF(notes); + } + Py_DECREF(note); + } + goto done; + } + PyObject *msg = PyUnicode_FromFormat( + "lazy import of '%U' raised an exception during resolution", name); + if (msg == NULL) { + goto done; + } + PyObject *cause = PyObject_CallOneArg(PyExc_ImportError, msg); + Py_DECREF(msg); + if (cause == NULL) { + goto done; + } + _PyErr_SetRaisedException(tstate, cause); + _PyTraceback_Add(funcname, filename, lineno); + PyException_SetCause(exc, _PyErr_GetRaisedException(tstate)); + +done: + Py_XDECREF(name); + _PyErr_SetRaisedException(tstate, exc); +} + +int +_PyLazyImport_IsResolving(PyThreadState *tstate, PyObject *op) +{ + _PyThreadStateImpl *ts = (_PyThreadStateImpl *)tstate; + assert(PyLazyImport_CheckExact(op)); + int active = ts->lazy_imports == NULL ? 0 : PySet_Contains(ts->lazy_imports, op); + assert(active >= 0); // Exact placeholders use identity hashing and equality. + return active; +} + +static PyObject * +lazy_import_resolve_impl(PyThreadState *tstate, PyObject *lazy_import, + PyObject **imported_module) +{ + PyObject *obj = NULL; + PyObject *fromlist = NULL; + PyObject *import_func = NULL; + PyObject *resolving = NULL; + assert(lazy_import != NULL); assert(PyLazyImport_CheckExact(lazy_import)); - return lazy_import_name(lazy_import); + + PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import; + + // Walk back to the placeholder IMPORT_NAME left, and the first lookup on it. + PyLazyImportObject *root = lz, *first = NULL; + while (PyLazyImport_CheckExact(root->lz_from)) { + first = root; + root = (PyLazyImportObject *)root->lz_from; + } + + if (_PyLazyImport_IsResolving(tstate, lazy_import)) { + PyObject *name = lazy_import_name(lz); + if (name == NULL) { + return NULL; + } + PyObject *errmsg = PyUnicode_FromFormat( + "cannot import name %R (most likely due to a circular import)", + name); + Py_DECREF(name); + if (errmsg != NULL) { + PyErr_SetImportErrorSubclass(PyExc_ImportCycleError, errmsg, + root->lz_from, NULL); + Py_DECREF(errmsg); + } + return NULL; + } + if (_Py_EnterRecursiveCallTstate(tstate, " while resolving a lazy import")) { + return NULL; + } + _PyThreadStateImpl *ts = (_PyThreadStateImpl *)tstate; + if (ts->lazy_imports == NULL) { + ts->lazy_imports = PySet_New(NULL); + if (ts->lazy_imports == NULL) { + goto done; + } + } + resolving = ts->lazy_imports; + if (PySet_Add(resolving, lazy_import) < 0) { + goto done; + } + + // `from a import b, c`: import only the name being resolved. + // Keep an empty tuple intact for custom __import__ hooks. + if (first != NULL && root->lz_attr != NULL && + PyTuple_Check(root->lz_attr) && PyTuple_GET_SIZE(root->lz_attr) > 0) { + fromlist = PyTuple_Pack(1, first->lz_attr); + } + else { + fromlist = Py_NewRef(root->lz_attr != NULL ? root->lz_attr : Py_None); + } + if (fromlist == NULL) { + goto done; + } + + PyObject *globals = PyEval_GetGlobals(); + if (globals == NULL) { + globals = Py_None; + } + + if (PyMapping_GetOptionalItem(root->lz_builtins, &_Py_ID(__import__), + &import_func) < 0) { + goto done; + } + if (import_func == NULL) { + PyErr_SetString(PyExc_ImportError, "__import__ not found"); + goto done; + } + obj = _PyEval_ImportNameWithImport( + tstate, import_func, globals, globals, + root->lz_from, fromlist, _PyLong_GetZero() + ); + obj = lazy_import_resolve_result(tstate, obj); + // The normal importer may publish this module on its parent. Custom + // hooks retain control of their own assignments to the parent. + if (imported_module != NULL && obj != NULL && PyModule_Check(obj) && + _PyImport_IsDefaultImportFunc(tstate->interp, import_func)) { + *imported_module = Py_NewRef(obj); + } + if (obj != NULL && first != NULL) { + // Keep the hook and root result alive until all attribute lookups finish. + PyObject *from = obj; + obj = lazy_import_replay_from(tstate, from, lz); + Py_DECREF(from); + } + +done: + if (obj == NULL) { + lazy_import_add_exception_cause(tstate, lz); + } + assert(obj == NULL || !PyLazyImport_CheckExact(obj)); + if (resolving != NULL) { + // A failed set resize can leave the placeholder inserted. Removing by + // identity also permits greenlets to finish in a different order. + if (PySet_Discard(resolving, lazy_import) < 0) { + Py_CLEAR(obj); + } + if (PySet_GET_SIZE(resolving) == 0) { + // Keep the set, but release the capacity used by deep resolutions. + (void)PySet_Clear(resolving); + } + } + + Py_XDECREF(fromlist); + Py_XDECREF(import_func); + _Py_LeaveRecursiveCallTstate(tstate); + return obj; +} + +PyObject * +_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import) +{ + return lazy_import_resolve_impl(tstate, lazy_import, NULL); +} + +// Loading pkg.child can replace a placeholder in pkg.child with the module +// before a from-import retrieves the value that belongs in that binding. +// This is an optimization that can be safely skipped. +static int +lazy_import_replace_child(PyThreadState *tstate, PyObject *placeholder, + PyObject *name, PyObject *namespace, + PyObject *child, PyObject *value) +{ + PyLazyImportObject *root = (PyLazyImportObject *)placeholder; + if (!PyLazyImport_CheckExact(root->lz_from)) { + return 0; + } + while (PyLazyImport_CheckExact(root->lz_from)) { + root = (PyLazyImportObject *)root->lz_from; + } + Py_ssize_t end = PyUnicode_GET_LENGTH(root->lz_from); + Py_ssize_t dot = PyUnicode_FindChar(root->lz_from, '.', 0, end, -1); + if (dot < 0) { + return dot == -1 ? 0 : -1; + } + if (end - dot - 1 != PyUnicode_GET_LENGTH(name)) { + return 0; + } + Py_ssize_t matches = PyUnicode_Tailmatch(root->lz_from, name, dot + 1, end, 1); + if (matches <= 0) { + return matches ? -1 : 0; + } + PyObject *parent_name = PyUnicode_Substring(root->lz_from, 0, dot); + if (parent_name == NULL) { + return -1; + } + PyObject *modules = Py_XNewRef(_PyImport_GetModules(tstate->interp)); + PyObject *parent = NULL; + int rc = 0; + if (modules != NULL) { + rc = PyMapping_GetOptionalItem(modules, parent_name, &parent); + if (rc > 0 && PyModule_Check(parent) && + _PyModule_GetDict(parent) == namespace) { + rc = _PyDict_ReplaceItemIf(namespace, name, child, value); + } + } + Py_XDECREF(parent); + Py_XDECREF(modules); + Py_DECREF(parent_name); + return rc; +} + +PyObject * +_PyLazyImport_Reify(PyThreadState *tstate, PyObject *placeholder, + PyObject *name, PyObject *namespace) +{ + PyObject *imported_module = NULL; + PyObject *value = lazy_import_resolve_impl( + tstate, placeholder, &imported_module); + if (value == NULL) { + Py_XDECREF(imported_module); + return NULL; + } + int rc; + if (PyDict_CheckExact(namespace)) { + rc = _PyDict_ReplaceItemIf(namespace, name, placeholder, value); + if (rc == 0 && imported_module != NULL) { + rc = lazy_import_replace_child( + tstate, placeholder, name, namespace, imported_module, value); + } + } + else if (Py_TYPE(namespace)->tp_as_mapping == NULL || + Py_TYPE(namespace)->tp_as_mapping->mp_ass_subscript == NULL) { + // Read-only namespaces can resolve a value without caching it. + Py_XDECREF(imported_module); + return value; + } + else { + // Custom namespaces retain their mapping protocol. Atomic replacement + // is only available for exact dictionaries. + PyObject *current; + rc = PyMapping_GetOptionalItem(namespace, name, ¤t); + if (rc > 0) { + if (current == placeholder) { + rc = PyObject_SetItem(namespace, name, value); + } + Py_DECREF(current); + } + } + if (rc < 0) { + Py_CLEAR(value); + } + Py_XDECREF(imported_module); + return value; } static PyObject * @@ -177,7 +576,7 @@ lazy_import_resolve(PyObject *self, PyObject *args) static PyMethodDef lazy_import_methods[] = { { "resolve", lazy_import_resolve, METH_NOARGS, - PyDoc_STR("resolves the lazy import and returns the actual object") + PyDoc_STR("Resolve the lazy import and return the imported object.") }, {NULL, NULL} }; diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index b8cd6025c20ba5..57df195b7f3201 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -7,7 +7,7 @@ #include "pycore_fileutils.h" // _Py_wgetcwd #include "pycore_import.h" // _PyImport_GetNextModuleIndex() #include "pycore_interp.h" // PyInterpreterState.importlib -#include "pycore_lazyimportobject.h" // _PyLazyImportObject_Check() +#include "pycore_lazyimportobject.h" // PyLazyImport_CheckExact() #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_modsupport.h" // _PyModule_CreateInitialized() #include "pycore_moduleobject.h" // _PyModule_GetDefOrNull() @@ -1299,32 +1299,21 @@ _PyModule_IsPossiblyShadowing(PyObject *origin) return result; } -static PyObject * -try_load_lazy_submodule(PyModuleObject *m, PyObject *name) +static int +module_get_resolved_dict_item(PyObject *dict, PyObject *name, PyObject **result) { - PyObject *mod_name; - int rc = PyDict_GetItemRef(m->md_dict, &_Py_ID(__name__), &mod_name); - if (rc <= 0) { - return NULL; - } - if (!PyUnicode_Check(mod_name)) { - Py_DECREF(mod_name); - return NULL; - } - PyObject *result = NULL; - _PyLazySubmoduleImportResult status = - _PyImport_TryLoadLazySubmodule(mod_name, name, &result); - Py_DECREF(mod_name); - if (status != _Py_LAZY_SUBMODULE_LOADED) { - assert(status == _Py_LAZY_SUBMODULE_ERROR || - status == _Py_LAZY_SUBMODULE_NOT_FOUND); - return NULL; + int rc = PyDict_GetItemRef(dict, name, result); + if (rc <= 0 || !PyLazyImport_CheckExact(*result)) { + return rc; } - if (PyDict_SetItem(m->md_dict, name, result) < 0) { - Py_DECREF(result); - return NULL; + PyThreadState *tstate = PyThreadState_GET(); + if (_PyLazyImport_IsResolving(tstate, *result)) { + Py_CLEAR(*result); + return 0; } - return result; + PyObject *value = _PyLazyImport_Reify(tstate, *result, name, dict); + Py_SETREF(*result, value); + return value == NULL ? -1 : 1; } PyObject* @@ -1333,11 +1322,52 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) // When suppress=1, this function suppresses AttributeError. PyObject *attr, *mod_name, *getattr; attr = _PyObject_GenericGetAttrWithDict((PyObject *)m, name, NULL, suppress); + if (attr == NULL) { + if (suppress == 1) { + if (PyErr_Occurred()) { + // pass up non-AttributeError exception + return NULL; + } + } + else { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + // pass up non-AttributeError exception + return NULL; + } + PyErr_Clear(); + } + assert(m->md_dict != NULL); + int recheck_dict; + attr = _PyImport_TryLoadLazySubmodule((PyObject *)m, name, &recheck_dict); + if (attr != NULL || PyErr_Occurred()) { + return attr; + } + // A concurrent load may have bound the child and removed its pending + // registration after our initial dictionary lookup. + if (recheck_dict) { + if (Py_TYPE(m) != &PyModule_Type) { + PyObject *descr = _PyType_LookupRef(Py_TYPE(m), name); + if (descr != NULL) { + // Preserve the fallback after a descriptor raised. + recheck_dict = Py_TYPE(descr)->tp_descr_get == NULL; + Py_DECREF(descr); + } + } + if (recheck_dict && + PyDict_GetItemRef(m->md_dict, name, &attr) < 0) { + return NULL; + } + } + } if (attr) { if (PyLazyImport_CheckExact(attr)) { // gh-144957: Module __getattr__ should get a chance to provide // the attribute before resolving a lazy import placeholder. - if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__getattr__), &getattr) < 0) { + // Resolving __getattr__ itself must not invoke the hook. + getattr = NULL; + if (!_PyUnicode_EqualToASCIIString(name, "__getattr__") && + module_get_resolved_dict_item( + m->md_dict, &_Py_ID(__getattr__), &getattr) < 0) { Py_DECREF(attr); return NULL; } @@ -1354,51 +1384,21 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) } PyErr_Clear(); } - PyObject *new_value = _PyImport_LoadLazyImportTstate( - PyThreadState_GET(), attr); - if (new_value == NULL) { - if (suppress && - PyErr_ExceptionMatches(PyExc_ImportCycleError)) { - // ImportCycleError is raised when a lazy object tries - // to import itself. In this case, the error should not - // propagate to the caller and instead treated as if the - // attribute doesn't exist. - PyErr_Clear(); - } + PyThreadState *tstate = PyThreadState_GET(); + if (suppress && _PyLazyImport_IsResolving(tstate, attr)) { + // Only direct reentry means this attribute is unavailable. Py_DECREF(attr); return NULL; } - - if (PyDict_SetItem(m->md_dict, name, new_value) < 0) { - Py_CLEAR(new_value); - } + PyObject *new_value = _PyLazyImport_Reify( + tstate, attr, name, m->md_dict); Py_DECREF(attr); return new_value; } return attr; } - if (suppress == 1) { - if (PyErr_Occurred()) { - // pass up non-AttributeError exception - return NULL; - } - } - else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - // pass up non-AttributeError exception - return NULL; - } - PyErr_Clear(); - } - assert(m->md_dict != NULL); - attr = try_load_lazy_submodule(m, name); - if (attr != NULL) { - return attr; - } - if (PyErr_Occurred()) { - return NULL; - } - if (PyDict_GetItemRef(m->md_dict, &_Py_ID(__getattr__), &getattr) < 0) { + if (module_get_resolved_dict_item( + m->md_dict, &_Py_ID(__getattr__), &getattr) < 0) { return NULL; } if (getattr) { @@ -1589,11 +1589,14 @@ module_dir(PyObject *self, PyObject *args) if (dict != NULL) { if (PyDict_Check(dict)) { - PyObject *dirfunc = PyDict_GetItemWithError(dict, &_Py_ID(__dir__)); - if (dirfunc) { + PyObject *dirfunc; + int rc = module_get_resolved_dict_item( + dict, &_Py_ID(__dir__), &dirfunc); + if (rc > 0) { result = _PyObject_CallNoArgs(dirfunc); + Py_DECREF(dirfunc); } - else if (!PyErr_Occurred()) { + else if (rc == 0) { result = PyDict_Keys(dict); } } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index f841e12793a800..8e487d0b88ff59 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2223,80 +2223,30 @@ dummy_func( inst(LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *namespace = PyStackRef_AsPyObjectBorrow(mod_or_class_dict); int err; - PyObject *v_o = _PyMapping_GetOptionalItem2(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &err); - + PyObject *v_o = _PyMapping_GetOptionalItem2(namespace, name, &err); + if (v_o != NULL && PyLazyImport_CheckExact(v_o)) { + Py_SETREF(v_o, _PyLazyImport_Reify(tstate, v_o, name, namespace)); + if (v_o == NULL) { + err = -1; + } + } PyStackRef_CLOSE(mod_or_class_dict); ERROR_IF(err < 0); if (v_o == NULL) { - if (PyDict_CheckExact(GLOBALS()) - && PyDict_CheckExact(BUILTINS())) - { - v_o = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), - (PyDictObject *)BUILTINS(), - name); - if (v_o == NULL) { - if (!_PyErr_Occurred(tstate)) { - /* _PyDict_LoadGlobal() returns NULL without raising - * an exception if the key doesn't exist */ - _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - } - ERROR_NO_POP(); - } - - if (PyLazyImport_CheckExact(v_o)) { - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - Py_SETREF(v_o, l_v); - ERROR_IF(v_o == NULL); - } - } - else { - /* Slow-path if globals or builtins is not a dict */ - /* namespace 1: globals */ - v_o = _PyMapping_GetOptionalItem2(GLOBALS(), name, &err); - ERROR_IF(err < 0); - if (v_o == NULL) { - /* namespace 2: builtins */ - v_o = _PyMapping_GetOptionalItem2(BUILTINS(), name, &err); - ERROR_IF(err < 0); - if (v_o == NULL) { - _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - ERROR_IF(true); - } - } - if (PyLazyImport_CheckExact(v_o)) { - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - Py_SETREF(v_o, l_v); - ERROR_IF(v_o == NULL); - } - } + _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, &v); + ERROR_IF(PyStackRef_IsNull(v)); + } + else { + v = PyStackRef_FromPyObjectSteal(v_o); } - v = PyStackRef_FromPyObjectSteal(v_o); } inst(LOAD_NAME, (-- v)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *v_o = _PyEval_LoadName(tstate, frame, name); ERROR_IF(v_o == NULL); - if (PyLazyImport_CheckExact(v_o)) { - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - // cannot early-decref v_o as it may cause a side-effect on l_v - if (l_v == NULL) { - Py_DECREF(v_o); - ERROR_IF(true); - } - int err = PyDict_SetItem(GLOBALS(), name, l_v); - if (err < 0) { - Py_DECREF(v_o); - Py_DECREF(l_v); - ERROR_IF(true); - } - Py_SETREF(v_o, l_v); - } - v = PyStackRef_FromPyObjectSteal(v_o); } @@ -2458,6 +2408,13 @@ dummy_func( ERROR_NO_POP(); } } + else if (PyLazyImport_CheckExact(value_o)) { + Py_SETREF(value_o, _PyLazyImport_Reify( + tstate, value_o, name, class_dict)); + if (value_o == NULL) { + ERROR_NO_POP(); + } + } PyStackRef_CLOSE(class_dict_st); value = PyStackRef_FromPyObjectSteal(value_o); } diff --git a/Python/ceval.c b/Python/ceval.c index 780fdbbc886be2..bf2d0a87909cc9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3127,8 +3127,8 @@ _PyEval_LazyImportName(PyThreadState *tstate, PyObject *builtins, goto error; } - PyObject *args[6] = {name, globals, locals, fromlist, level, builtins}; - res = PyObject_Vectorcall(lazy_import_func, args, 6, NULL); + PyObject *args[5] = {name, globals, locals, fromlist, level}; + res = PyObject_Vectorcall(lazy_import_func, args, 5, NULL); error: Py_XDECREF(lazy_import_func); return res; @@ -3302,43 +3302,6 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name) return NULL; } -PyObject * -_PyEval_LazyImportFrom(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *v, PyObject *name) -{ - assert(PyLazyImport_CheckExact(v)); - assert(name); - assert(PyUnicode_Check(name)); - PyObject *ret; - PyLazyImportObject *d = (PyLazyImportObject *)v; - PyObject *mod = NULL; - // Only `from a import b` can take b off an already imported a; - // `import a.b as c` has to import a.b first. - if (d->lz_attr != NULL && PyTuple_Check(d->lz_attr) && - PyTuple_GET_SIZE(d->lz_attr) > 0) { - mod = PyImport_GetModule(d->lz_from); - } - if (mod != NULL) { - // Check if the module already has the attribute, if so, resolve it - // eagerly. - if (PyModule_Check(mod)) { - PyObject *mod_dict = PyModule_GetDict(mod); - if (mod_dict != NULL) { - if (PyDict_GetItemRef(mod_dict, name, &ret) < 0) { - Py_DECREF(mod); - return NULL; - } - if (ret != NULL) { - Py_DECREF(mod); - return ret; - } - } - } - Py_DECREF(mod); - } - - return _PyLazyImport_New(frame, d->lz_builtins, v, name); -} - #define CANNOT_CATCH_MSG "catching classes that do not inherit from "\ "BaseException is not allowed" @@ -3604,13 +3567,13 @@ _PyEval_GetANext(PyObject *aiter) void _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name, _PyStackRef *writeto) { + PyObject *namespace = globals; if (PyAnyDict_CheckExact(globals) && PyAnyDict_CheckExact(builtins)) { - _PyDict_LoadGlobalStackRef((PyDictObject *)globals, - (PyDictObject *)builtins, - name, writeto); + namespace = _PyDict_LoadGlobalStackRef((PyDictObject *)globals, + (PyDictObject *)builtins, + name, writeto); if (PyStackRef_IsNull(*writeto) && !PyErr_Occurred()) { - /* _PyDict_LoadGlobal() returns NULL without raising - * an exception if the key doesn't exist */ + // A missing key does not set an exception in the dictionary helper. _PyEval_FormatExcCheckArg(PyThreadState_GET(), PyExc_NameError, NAME_ERROR_MSG, name); } @@ -3625,6 +3588,7 @@ _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name } if (res == NULL) { /* namespace 2: builtins */ + namespace = builtins; if (PyMapping_GetOptionalItem(builtins, name, &res) < 0) { *writeto = PyStackRef_NULL; return; @@ -3642,20 +3606,10 @@ _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name PyObject *res_o = PyStackRef_AsPyObjectBorrow(*writeto); if (res_o != NULL && PyLazyImport_CheckExact(res_o)) { - PyObject *l_v = _PyImport_LoadLazyImportTstate(PyThreadState_GET(), res_o); + PyObject *l_v = _PyLazyImport_Reify( + PyThreadState_GET(), res_o, name, namespace); PyStackRef_CLOSE(writeto[0]); - if (l_v == NULL) { - assert(PyErr_Occurred()); - *writeto = PyStackRef_NULL; - return; - } - int err = PyDict_SetItem(globals, name, l_v); - if (err < 0) { - Py_DECREF(l_v); - *writeto = PyStackRef_NULL; - return; - } - *writeto = PyStackRef_FromPyObjectSteal(l_v); + *writeto = l_v == NULL ? PyStackRef_NULL : PyStackRef_FromPyObjectSteal(l_v); } } @@ -3686,32 +3640,39 @@ _PyEval_GetAwaitable(PyObject *iterable, int oparg) PyObject * _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name) { - PyObject *value; - if (frame->f_locals == NULL) { + PyObject *namespace = frame->f_locals; + if (namespace == NULL) { _PyErr_SetString(tstate, PyExc_SystemError, "no locals found"); return NULL; } - if (PyMapping_GetOptionalItem(frame->f_locals, name, &value) < 0) { + if (PyMapping_GetOptionalItem(namespace, name, &value) < 0) { return NULL; } if (value != NULL) { - return value; + goto found; } - if (PyDict_GetItemRef(frame->f_globals, name, &value) < 0) { + namespace = frame->f_globals; + if (PyDict_GetItemRef(namespace, name, &value) < 0) { return NULL; } if (value != NULL) { - return value; + goto found; } - if (PyMapping_GetOptionalItem(frame->f_builtins, name, &value) < 0) { + namespace = frame->f_builtins; + if (PyMapping_GetOptionalItem(namespace, name, &value) < 0) { return NULL; } if (value == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, - NAME_ERROR_MSG, name); + NAME_ERROR_MSG, name); + return NULL; + } +found: + if (PyLazyImport_CheckExact(value)) { + Py_SETREF(value, _PyLazyImport_Reify(tstate, value, name, namespace)); } return value; } diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h index 2e4e178b308406..749eaebca19dc5 100644 --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -627,7 +627,7 @@ PyDoc_STRVAR(_imp__set_lazy_attributes__doc__, "_set_lazy_attributes($module, modobj, name, /)\n" "--\n" "\n" -"Sets attributes to lazy submodules on the module, as side effects."); +"Remove the resolved module name from sys.lazy_modules."); #define _IMP__SET_LAZY_ATTRIBUTES_METHODDEF \ {"_set_lazy_attributes", _PyCFunction_CAST(_imp__set_lazy_attributes), METH_FASTCALL, _imp__set_lazy_attributes__doc__}, @@ -665,4 +665,4 @@ _imp__set_lazy_attributes(PyObject *module, PyObject *const *args, Py_ssize_t na #ifndef _IMP_EXEC_DYNAMIC_METHODDEF #define _IMP_EXEC_DYNAMIC_METHODDEF #endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=0974db098d601372 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ae9cf67e39955555 input=a9049054013a1b77]*/ diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index dc5c68794e8a5f..8c02c0c89e862f 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -10095,46 +10095,72 @@ break; } - /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 because it has both popping and not-popping errors */ - - case _LOAD_NAME_r01: { - CHECK_CURRENT_CACHED_VALUES(0); + case _LOAD_FROM_DICT_OR_GLOBALS_r11: { + CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef mod_or_class_dict; _PyStackRef v; + _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); + mod_or_class_dict = _stack_item_0; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *namespace = PyStackRef_AsPyObjectBorrow(mod_or_class_dict); + int err; + stack_pointer[0] = mod_or_class_dict; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *v_o = _PyEval_LoadName(tstate, frame, name); + PyObject *v_o = _PyMapping_GetOptionalItem2(namespace, name, &err); stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - if (PyLazyImport_CheckExact(v_o)) { + if (v_o != NULL && PyLazyImport_CheckExact(v_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); + Py_SETREF(v_o, _PyLazyImport_Reify(tstate, v_o, name, namespace)); stack_pointer = _PyFrame_GetStackPointer(frame); - if (l_v == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(v_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); + if (v_o == NULL) { + err = -1; } + } + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(mod_or_class_dict); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + if (v_o == NULL) { _PyFrame_SetStackPointer(frame, stack_pointer); - int err = PyDict_SetItem(GLOBALS(), name, l_v); + _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, &v); stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(v_o); - Py_DECREF(l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsNull(v)) { SET_CURRENT_CACHED_VALUES(0); JUMP_TO_ERROR(); } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + v = PyStackRef_FromPyObjectSteal(v_o); + } + _tos_cache0 = v; + _tos_cache1 = PyStackRef_ZERO_BITS; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_NAME_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef v; + oparg = CURRENT_OPARG(); + PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *v_o = _PyEval_LoadName(tstate, frame, name); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); } v = PyStackRef_FromPyObjectSteal(v_o); _tos_cache0 = v; @@ -10498,6 +10524,16 @@ JUMP_TO_ERROR(); } } + else if (PyLazyImport_CheckExact(value_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(value_o, _PyLazyImport_Reify( + tstate, value_o, name, class_dict)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (value_o == NULL) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 741306f7cf27f7..d312fef398794f 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -9518,6 +9518,15 @@ JUMP_TO_LABEL(error); } } + else if (PyLazyImport_CheckExact(value_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(value_o, _PyLazyImport_Reify( + tstate, value_o, name, class_dict)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (value_o == NULL) { + JUMP_TO_LABEL(error); + } + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -9542,10 +9551,19 @@ _PyStackRef v; mod_or_class_dict = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + PyObject *namespace = PyStackRef_AsPyObjectBorrow(mod_or_class_dict); int err; _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *v_o = _PyMapping_GetOptionalItem2(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &err); + PyObject *v_o = _PyMapping_GetOptionalItem2(namespace, name, &err); stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o != NULL && PyLazyImport_CheckExact(v_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_SETREF(v_o, _PyLazyImport_Reify(tstate, v_o, name, namespace)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (v_o == NULL) { + err = -1; + } + } stack_pointer += -1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -9555,68 +9573,16 @@ JUMP_TO_LABEL(error); } if (v_o == NULL) { - if (PyDict_CheckExact(GLOBALS()) - && PyDict_CheckExact(BUILTINS())) - { - _PyFrame_SetStackPointer(frame, stack_pointer); - v_o = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), - (PyDictObject *)BUILTINS(), - name); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - if (!_PyErr_Occurred(tstate)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - stack_pointer = _PyFrame_GetStackPointer(frame); - } - JUMP_TO_LABEL(error); - } - if (PyLazyImport_CheckExact(v_o)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - JUMP_TO_LABEL(error); - } - } - } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - v_o = _PyMapping_GetOptionalItem2(GLOBALS(), name, &err); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - JUMP_TO_LABEL(error); - } - if (v_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - v_o = _PyMapping_GetOptionalItem2(BUILTINS(), name, &err); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - JUMP_TO_LABEL(error); - } - if (v_o == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyEval_FormatExcCheckArg( - tstate, PyExc_NameError, - NAME_ERROR_MSG, name); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - } - if (PyLazyImport_CheckExact(v_o)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (v_o == NULL) { - JUMP_TO_LABEL(error); - } - } + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, &v); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsNull(v)) { + JUMP_TO_LABEL(error); } } - v = PyStackRef_FromPyObjectSteal(v_o); + else { + v = PyStackRef_FromPyObjectSteal(v_o); + } stack_pointer[0] = v; stack_pointer += 1; ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); @@ -9866,30 +9832,6 @@ if (v_o == NULL) { JUMP_TO_LABEL(error); } - if (PyLazyImport_CheckExact(v_o)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *l_v = _PyImport_LoadLazyImportTstate(tstate, v_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (l_v == NULL) { - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(v_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - int err = PyDict_SetItem(GLOBALS(), name, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (err < 0) { - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(v_o); - Py_DECREF(l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - JUMP_TO_LABEL(error); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_SETREF(v_o, l_v); - stack_pointer = _PyFrame_GetStackPointer(frame); - } v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[0] = v; stack_pointer += 1; diff --git a/Python/import.c b/Python/import.c index e528b458f0dc37..a3b07facc1afa7 100644 --- a/Python/import.c +++ b/Python/import.c @@ -11,7 +11,6 @@ #include "pycore_interp.h" // struct _import_runtime_state #include "pycore_interpframe.h" #include "pycore_lazyimportobject.h" -#include "pycore_long.h" // _PyLong_GetZero #include "pycore_magic_number.h" // PYC_MAGIC_NUMBER_TOKEN #include "pycore_moduleobject.h" // _PyModule_GetDef() #include "pycore_namespace.h" // _PyNamespace_Type @@ -25,7 +24,6 @@ #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_sysmodule.h" // _PySys_ClearAttrString() #include "pycore_time.h" // _PyTime_AsMicroseconds() -#include "pycore_traceback.h" #include "pycore_unicodeobject.h" // _PyUnicode_AsUTF8NoNUL() #include "pycore_weakref.h" // _PyWeakref_GET_REF() @@ -3888,227 +3886,6 @@ resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level return NULL; } -PyObject * -_PyImport_ResolveName(PyThreadState *tstate, PyObject *name, - PyObject *globals, int level) -{ - return resolve_name(tstate, name, globals, level); -} - -// Look up, in order, the attributes recorded from the root placeholder to lz -// on the module the root's import returned. -static PyObject * -lazy_import_replay_from(PyThreadState *tstate, PyObject *mod, - PyLazyImportObject *lz) -{ - if (!PyLazyImport_CheckExact(lz->lz_from)) { - return Py_NewRef(mod); - } - PyObject *from = lazy_import_replay_from( - tstate, mod, (PyLazyImportObject *)lz->lz_from); - if (from == NULL) { - return NULL; - } - PyObject *obj = _PyEval_ImportFrom(tstate, from, lz->lz_attr); - Py_DECREF(from); - return obj; -} - -PyObject * -_PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import) -{ - PyObject *obj = NULL; - PyObject *fromlist = Py_None; - PyObject *import_func = NULL; - assert(lazy_import != NULL); - assert(PyLazyImport_CheckExact(lazy_import)); - - PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import; - PyInterpreterState *interp = tstate->interp; - - // Walk back to the placeholder IMPORT_NAME left, and the first lookup on it. - PyLazyImportObject *root = lz, *first = NULL; - while (PyLazyImport_CheckExact(root->lz_from)) { - first = root; - root = (PyLazyImportObject *)root->lz_from; - } - - // Acquire the global import lock to serialize reification - _PyImport_AcquireLock(interp); - - // Check if we are already importing this module, if so, then we want to - // return an error that indicates we've hit a cycle which will indicate - // the value isn't yet available. - PyObject *importing = interp->imports.lazy_importing_modules; - if (importing == NULL) { - importing = interp->imports.lazy_importing_modules = PySet_New(NULL); - if (importing == NULL) { - _PyImport_ReleaseLock(interp); - return NULL; - } - } - - assert(PyAnySet_CheckExact(importing)); - int is_loading = _PySet_Contains((PySetObject *)importing, lazy_import); - if (is_loading < 0) { - _PyImport_ReleaseLock(interp); - return NULL; - } - else if (is_loading == 1) { - PyObject *name = _PyLazyImport_GetName(lazy_import); - if (name == NULL) { - _PyImport_ReleaseLock(interp); - return NULL; - } - PyObject *errmsg = PyUnicode_FromFormat( - "cannot import name %R (most likely due to a circular import)", - name); - if (errmsg == NULL) { - Py_DECREF(name); - _PyImport_ReleaseLock(interp); - return NULL; - } - PyErr_SetImportErrorSubclass(PyExc_ImportCycleError, errmsg, - root->lz_from, NULL); - Py_DECREF(errmsg); - Py_DECREF(name); - _PyImport_ReleaseLock(interp); - return NULL; - } - else if (PySet_Add(importing, lazy_import) < 0) { - goto error; - } - - if (root->lz_attr != NULL) { - // `from a import b, c`: import only the name being resolved. - // Keep an empty tuple intact for custom __import__ hooks. - fromlist = first && PyTuple_GET_SIZE(root->lz_attr) > 0 - ? PyTuple_Pack(1, first->lz_attr) - : Py_NewRef(root->lz_attr); - if (fromlist == NULL) { - goto error; - } - } - - PyObject *globals = PyEval_GetGlobals(); - - if (PyMapping_GetOptionalItem(root->lz_builtins, &_Py_ID(__import__), - &import_func) < 0) { - goto error; - } - if (import_func == NULL) { - PyErr_SetString(PyExc_ImportError, "__import__ not found"); - goto error; - } - obj = _PyEval_ImportNameWithImport( - tstate, import_func, globals, globals, - root->lz_from, fromlist, _PyLong_GetZero() - ); - if (obj == NULL) { - goto error; - } - - PyObject *from = obj; - obj = lazy_import_replay_from(tstate, from, lz); - Py_DECREF(from); - if (obj == NULL) { - goto error; - } - - assert(!PyLazyImport_CheckExact(obj)); - - goto ok; - -error: - Py_CLEAR(obj); - - // If an error occurred and we have frame information, add it to the - // exception. - if (PyErr_Occurred() && lz->lz_code != NULL && lz->lz_instr_offset >= 0) { - // Get the current exception - this already has the full traceback - // from the access point. - PyObject *exc = _PyErr_GetRaisedException(tstate); - - // Get import name - this can fail and set an exception. - PyObject *import_name = _PyLazyImport_GetName(lazy_import); - if (!import_name) { - // Failed to get import name, just restore original exception. - _PyErr_SetRaisedException(tstate, exc); - goto ok; - } - - // Resolve line number from instruction offset on demand. - int lineno = PyCode_Addr2Line((PyCodeObject *)lz->lz_code, - lz->lz_instr_offset*2); - - // Get strings - these can return NULL on encoding errors. - const char *filename_str = PyUnicode_AsUTF8(lz->lz_code->co_filename); - if (!filename_str) { - // Unicode conversion failed - clear error and restore original - // exception. - PyErr_Clear(); - Py_DECREF(import_name); - _PyErr_SetRaisedException(tstate, exc); - goto ok; - } - - const char *funcname_str = PyUnicode_AsUTF8(lz->lz_code->co_name); - if (!funcname_str) { - // Unicode conversion failed - clear error and restore original - // exception. - PyErr_Clear(); - Py_DECREF(import_name); - _PyErr_SetRaisedException(tstate, exc); - goto ok; - } - - // Create a cause exception showing where the lazy import was declared. - PyObject *msg = PyUnicode_FromFormat( - "lazy import of '%U' raised an exception during resolution", - import_name - ); - Py_DECREF(import_name); // Done with import_name. - - if (!msg) { - // Failed to create message - restore original exception. - _PyErr_SetRaisedException(tstate, exc); - goto ok; - } - - PyObject *cause_exc = PyObject_CallOneArg(PyExc_ImportError, msg); - Py_DECREF(msg); // Done with msg. - - if (!cause_exc) { - // Failed to create exception - restore original. - _PyErr_SetRaisedException(tstate, exc); - goto ok; - } - - // Add traceback entry for the lazy import declaration. - _PyErr_SetRaisedException(tstate, cause_exc); - _PyTraceback_Add(funcname_str, filename_str, lineno); - PyObject *cause_with_tb = _PyErr_GetRaisedException(tstate); - - // Set the cause on the original exception. - PyException_SetCause(exc, cause_with_tb); // Steals ref to cause_with_tb. - - // Restore the original exception with its full traceback. - _PyErr_SetRaisedException(tstate, exc); - } - -ok: - if (PySet_Discard(importing, lazy_import) < 0) { - Py_CLEAR(obj); - } - - // Release the global import lock. - _PyImport_ReleaseLock(interp); - - Py_XDECREF(fromlist); - Py_XDECREF(import_func); - return obj; -} - static PyObject * import_find_and_load_with_name(PyThreadState *tstate, PyObject *abs_name, PyObject *find_and_load, @@ -4177,9 +3954,9 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name) tstate, abs_name, &_Py_ID(_find_and_load), NULL); } -static PyObject * -get_abs_name(PyThreadState *tstate, PyObject *name, PyObject *globals, - int level) +PyObject * +_PyImport_GetAbsName(PyThreadState *tstate, PyObject *name, PyObject *globals, + int level) { if (level > 0) { return resolve_name(tstate, name, globals, level); @@ -4191,13 +3968,6 @@ get_abs_name(PyThreadState *tstate, PyObject *name, PyObject *globals, return Py_NewRef(name); } -PyObject * -_PyImport_GetAbsName(PyThreadState *tstate, PyObject *name, - PyObject *globals, int level) -{ - return get_abs_name(tstate, name, globals, level); -} - PyObject * PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, @@ -4229,7 +3999,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, goto error; } - abs_name = get_abs_name(tstate, name, globals, level); + abs_name = _PyImport_GetAbsName(tstate, name, globals, level); if (abs_name == NULL) { goto error; } @@ -4355,7 +4125,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, return final_mod; } -// ensure we have the set for the parent module name in sys.lazy_modules. +// Ensure a set of pending submodule names exists for the parent. // Returns a new reference. static PyObject * ensure_lazy_pending_submodules(PyDictObject *lazy_modules, PyObject *parent) @@ -4384,59 +4154,35 @@ ensure_lazy_pending_submodules(PyDictObject *lazy_modules, PyObject *parent) static int register_lazy_on_parent(PyThreadState *tstate, PyObject *name) { - int ret = -1; - PyObject *parent = NULL; - PyObject *child = NULL; - - PyInterpreterState *interp = tstate->interp; - PyObject *lazy_pending_submodules = LAZY_PENDING_SUBMODULES(interp); - assert(lazy_pending_submodules != NULL); - - Py_INCREF(name); + PyDictObject *pending = + (PyDictObject *)LAZY_PENDING_SUBMODULES(tstate->interp); + assert(pending != NULL); + Py_ssize_t end = PyUnicode_GET_LENGTH(name); while (true) { - Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, - PyUnicode_GET_LENGTH(name), -1); + Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, end, -1); if (dot < 0) { - PyObject *lazy_submodules = ensure_lazy_pending_submodules( - (PyDictObject *)lazy_pending_submodules, name); - if (lazy_submodules == NULL) { - goto done; - } - Py_DECREF(lazy_submodules); - ret = 0; - goto done; + return dot == -1 ? 0 : -1; } - parent = PyUnicode_Substring(name, 0, dot); + PyObject *parent = PyUnicode_Substring(name, 0, dot); if (parent == NULL) { - goto done; + return -1; } - Py_XDECREF(child); - child = PyUnicode_Substring(name, dot + 1, PyUnicode_GET_LENGTH(name)); + PyObject *child = PyUnicode_Substring(name, dot + 1, end); if (child == NULL) { - goto done; - } - - PyObject *lazy_submodules = ensure_lazy_pending_submodules( - (PyDictObject *)lazy_pending_submodules, parent); - if (lazy_submodules == NULL) { - goto done; + Py_DECREF(parent); + return -1; } - if (PySet_Add(lazy_submodules, child) < 0) { - Py_DECREF(lazy_submodules); - goto done; + PyObject *submodules = ensure_lazy_pending_submodules(pending, parent); + Py_DECREF(parent); + int err = submodules == NULL ? -1 : PySet_Add(submodules, child); + Py_DECREF(child); + Py_XDECREF(submodules); + if (err < 0) { + return -1; } - Py_DECREF(lazy_submodules); - - Py_SETREF(name, parent); - parent = NULL; + end = dot; } - -done: - Py_XDECREF(child); - Py_XDECREF(parent); - Py_XDECREF(name); - return ret; } static int @@ -4450,80 +4196,65 @@ register_from_lazy_on_parent(PyThreadState *tstate, PyObject *abs_name, // Add the module name to sys.lazy_modules set (PEP 810). PyObject *lazy_modules = LAZY_MODULES(tstate->interp); - if (PySet_Add(lazy_modules, fromname) < 0) { - Py_DECREF(fromname); - return -1; + int res = PySet_Add(lazy_modules, fromname); + if (res == 0) { + res = register_lazy_on_parent(tstate, fromname); } - - int res = register_lazy_on_parent(tstate, fromname); Py_DECREF(fromname); return res; } -_PyLazySubmoduleImportResult -_PyImport_TryLoadLazySubmodule(PyObject *mod_name, PyObject *attr_name, - PyObject **result) +PyObject * +_PyImport_TryLoadLazySubmodule(PyObject *module, PyObject *attr_name, + int *recheck_dict) { - assert(result != NULL); - *result = NULL; - - PyThreadState *tstate = _PyThreadState_GET(); - PyInterpreterState *interp = tstate->interp; - PyObject *lazy_pending = LAZY_PENDING_SUBMODULES(interp); - if (lazy_pending == NULL) { - return _Py_LAZY_SUBMODULE_NOT_FOUND; + *recheck_dict = 0; + PyObject *mod_dict = _PyModule_GetDict(module); + PyObject *mod_name; + if (PyDict_GetItemRef(mod_dict, &_Py_ID(__name__), &mod_name) <= 0) { + return NULL; } - - PyObject *pending_set; - int rc = PyDict_GetItemRef(lazy_pending, mod_name, &pending_set); - if (rc < 0) { - return _Py_LAZY_SUBMODULE_ERROR; + PyObject *mod = NULL, *pending_set = NULL; + if (!PyUnicode_Check(mod_name)) { + goto done; } - if (rc == 0) { - return _Py_LAZY_SUBMODULE_NOT_FOUND; + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *lazy_pending = LAZY_PENDING_SUBMODULES(tstate->interp); + if (lazy_pending == NULL || + PyDict_GetItemRef(lazy_pending, mod_name, &pending_set) <= 0) { + goto done; } - int contains = PySet_Contains(pending_set, attr_name); - if (contains < 0) { - Py_DECREF(pending_set); - return _Py_LAZY_SUBMODULE_ERROR; - } - if (contains == 0) { - Py_DECREF(pending_set); - return _Py_LAZY_SUBMODULE_NOT_FOUND; + *recheck_dict = 1; + if (PySet_Contains(pending_set, attr_name) <= 0) { + goto done; } - PyObject *full_name = PyUnicode_FromFormat("%U.%U", mod_name, attr_name); if (full_name == NULL) { - Py_DECREF(pending_set); - return _Py_LAZY_SUBMODULE_ERROR; + goto done; } - - PyObject *mod = import_find_and_load_with_name( - tstate, full_name, &_Py_ID(_find_and_load_lazy_submodule), Py_None); + // Match eager from-imports: accept a partial module in an import cycle. + mod = PyImport_GetModule(full_name); + if ((mod == NULL && !PyErr_Occurred()) || mod == Py_None) { + Py_XDECREF(mod); + mod = import_find_and_load_with_name( + tstate, full_name, &_Py_ID(_find_and_load_lazy_submodule), Py_None); + } + Py_DECREF(full_name); if (mod == NULL) { - Py_DECREF(pending_set); - Py_DECREF(full_name); remove_importlib_frames(tstate); - return _Py_LAZY_SUBMODULE_ERROR; } - if (mod == Py_None) { - Py_DECREF(mod); - Py_DECREF(pending_set); - Py_DECREF(full_name); - return _Py_LAZY_SUBMODULE_NOT_FOUND; + /* Keep missing children pending: a finder may provide them later. */ + else if (mod == Py_None || + PyDict_SetItem(mod_dict, attr_name, mod) < 0 || + PySet_Discard(pending_set, attr_name) < 0) { + Py_CLEAR(mod); } - if (PySet_Discard(pending_set, attr_name) < 0) { - Py_DECREF(mod); - Py_DECREF(pending_set); - Py_DECREF(full_name); - return _Py_LAZY_SUBMODULE_ERROR; - } - Py_DECREF(pending_set); - Py_DECREF(full_name); - *result = mod; - return _Py_LAZY_SUBMODULE_LOADED; +done: + Py_XDECREF(pending_set); + Py_DECREF(mod_name); + return mod; } PyObject * @@ -4543,12 +4274,11 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, return NULL; } - PyObject *abs_name = get_abs_name(tstate, name, globals, level); + PyObject *abs_name = _PyImport_GetAbsName(tstate, name, globals, level); if (abs_name == NULL) { return NULL; } - PyInterpreterState *interp = tstate->interp; _PyInterpreterFrame *frame = _PyEval_GetFrame(); if (frame == NULL || frame->f_globals != frame->f_locals) { Py_DECREF(abs_name); @@ -4557,71 +4287,69 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, return NULL; } + PyObject *res = NULL; + if (fromlist != NULL && PyUnicode_Check(fromlist)) { + fromlist = PyTuple_Pack(1, fromlist); + if (fromlist == NULL) { + goto done; + } + } + else { + fromlist = Py_NewRef(fromlist != NULL ? fromlist : Py_None); + } + // Check if the filter disables the lazy import. - // We must hold a reference to the filter while calling it to prevent - // use-after-free if another thread replaces it via - // PyImport_SetLazyImportsFilter. - LAZY_IMPORTS_LOCK(interp); - PyObject *filter = Py_XNewRef(LAZY_IMPORTS_FILTER(interp)); - LAZY_IMPORTS_UNLOCK(interp); + PyObject *filter = PyImport_GetLazyImportsFilter(); if (filter != NULL) { PyObject *modname; if (PyDict_GetItemRef(globals, &_Py_ID(__name__), &modname) < 0) { Py_DECREF(filter); - Py_DECREF(abs_name); - return NULL; + goto done; } if (modname == NULL) { assert(!PyErr_Occurred()); modname = Py_NewRef(Py_None); } - if (fromlist == NULL) { - assert(!PyErr_Occurred()); - fromlist = Py_None; - } PyObject *args[] = {modname, abs_name, fromlist}; - PyObject *res = PyObject_Vectorcall(filter, args, 3, NULL); + PyObject *decision = PyObject_Vectorcall(filter, args, 3, NULL); Py_DECREF(modname); Py_DECREF(filter); - if (res == NULL) { - Py_DECREF(abs_name); - return NULL; + if (decision == NULL) { + goto done; } - int is_true = PyObject_IsTrue(res); - Py_DECREF(res); + int is_true = PyObject_IsTrue(decision); + Py_DECREF(decision); if (is_true < 0) { - Py_DECREF(abs_name); - return NULL; + goto done; } if (!is_true) { - Py_DECREF(abs_name); - return PyImport_ImportModuleLevelObject( + res = PyImport_ImportModuleLevelObject( name, globals, locals, fromlist, level ); + goto done; } } - // here, 'filter' is either NULL or is equivalent to a borrowed reference - if (fromlist && PyUnicode_Check(fromlist)) { - fromlist = PyTuple_Pack(1, fromlist); - if (fromlist == NULL) { - Py_DECREF(abs_name); - return NULL; + // Validate the entire fromlist before registering any pending imports. + if (PyTuple_Check(fromlist)) { + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(fromlist); i++) { + PyObject *item = PyTuple_GET_ITEM(fromlist, i); + if (!PyUnicode_Check(item)) { + _PyErr_Format(tstate, PyExc_TypeError, + "Item in ``from list'' must be str, not %.200s", + Py_TYPE(item)->tp_name); + goto done; + } } } - else { - Py_XINCREF(fromlist); - } - PyObject *res = _PyLazyImport_New(frame, builtins, abs_name, fromlist); + res = _PyLazyImport_New(frame, builtins, abs_name, fromlist); if (res == NULL) { - Py_XDECREF(fromlist); - Py_DECREF(abs_name); - return NULL; + goto done; } // Add the module name to sys.lazy_modules set (PEP 810). @@ -4630,7 +4358,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, goto error; } - if (fromlist && PyTuple_Check(fromlist) && PyTuple_GET_SIZE(fromlist)) { + if (PyTuple_Check(fromlist) && PyTuple_GET_SIZE(fromlist)) { for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(fromlist); i++) { if (register_from_lazy_on_parent(tstate, abs_name, PyTuple_GET_ITEM(fromlist, i)) < 0) @@ -4643,14 +4371,13 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate, goto error; } - Py_XDECREF(fromlist); - Py_DECREF(abs_name); - return res; + goto done; error: + Py_CLEAR(res); +done: Py_XDECREF(fromlist); Py_DECREF(abs_name); - Py_DECREF(res); - return NULL; + return res; } PyObject * @@ -4862,7 +4589,6 @@ _PyImport_ClearCore(PyInterpreterState *interp) Py_CLEAR(LAZY_IMPORT_FUNC(interp)); Py_CLEAR(interp->imports.lazy_pending_submodules); Py_CLEAR(interp->imports.lazy_modules); - Py_CLEAR(interp->imports.lazy_importing_modules); Py_CLEAR(interp->imports.lazy_imports_filter); } @@ -5657,13 +5383,13 @@ _imp._set_lazy_attributes modobj: object name: unicode / -Sets attributes to lazy submodules on the module, as side effects. +Remove the resolved module name from sys.lazy_modules. [clinic start generated code]*/ static PyObject * _imp__set_lazy_attributes_impl(PyObject *module, PyObject *modobj, PyObject *name) -/*[clinic end generated code: output=3369bb3242b1f043 input=38ea6f30956dd7d6]*/ +/*[clinic end generated code: output=3369bb3242b1f043 input=900339e013ab2b82]*/ { PyInterpreterState *interp = _PyInterpreterState_GET(); if (PySet_Discard(LAZY_MODULES(interp), name) < 0) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index f336549d2ed244..2e34f2e9f1df20 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2185,7 +2185,12 @@ break; } - /* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */ + case _LOAD_FROM_DICT_OR_GLOBALS: { + JitOptRef v; + v = sym_new_not_null(ctx); + stack_pointer[-1] = v; + break; + } case _LOAD_NAME: { JitOptRef v; diff --git a/Python/pystate.c b/Python/pystate.c index 786a3ca27f0c18..4cfb873c71c37e 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1599,6 +1599,7 @@ init_threadstate(_PyThreadStateImpl *_tstate, _tstate->asyncio_running_loop = NULL; _tstate->asyncio_running_task = NULL; + _tstate->lazy_imports = NULL; #ifdef _Py_TIER2 _tstate->jit_tracer_state = NULL; @@ -1842,6 +1843,9 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->context); + // Finalizers above may resolve imports and create this set. + Py_CLEAR(((_PyThreadStateImpl *)tstate)->lazy_imports); + #ifdef Py_GIL_DISABLED // Each thread should clear own freelists in free-threading builds. struct _Py_freelists *freelists = _Py_freelists_GET();