@@ -1242,20 +1242,35 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
1242
1242
}
1243
1243
1244
1244
#if MICROPY_PY_DESCRIPTORS
1245
- // call __set_name__ on all entries (especially descriptors)
1245
+ // make a list of all names of __set_name__-able attributes that won't be mutated by __set_name__ calls
1246
+ mp_obj_list_t * setname_list = MP_OBJ_TO_PTR (mp_obj_list_make_new (& mp_type_list , 0 , 0 , NULL ));
1246
1247
for (size_t i = 0 ; i < locals_map -> alloc ; i ++ ) {
1247
1248
if (mp_map_slot_is_filled (locals_map , i )) {
1248
1249
elem = & (locals_map -> table [i ]);
1249
1250
1250
- mp_obj_t set_name_method [4 ];
1251
- mp_load_method_maybe (elem -> value , MP_QSTR___set_name__ , set_name_method );
1251
+ mp_obj_t set_name_method [2 ];
1252
+ mp_load_method_protected (elem -> value , MP_QSTR___set_name__ , set_name_method , true );
1252
1253
if (set_name_method [1 ] != MP_OBJ_NULL ) {
1253
- set_name_method [2 ] = MP_OBJ_FROM_PTR (o );
1254
- set_name_method [3 ] = elem -> key ;
1255
- mp_call_method_n_kw (2 , 0 , set_name_method );
1254
+ mp_obj_list_append (MP_OBJ_FROM_PTR (setname_list ), elem -> key );
1256
1255
}
1257
1256
}
1258
1257
}
1258
+
1259
+ nlr_buf_t nlr ;
1260
+ if (nlr_push (& nlr ) == 0 ) {
1261
+ // then use that list to call __set_name__ on each
1262
+ for (size_t i = 0 ; i < setname_list -> len ; i ++ ) {
1263
+ elem = mp_map_lookup (locals_map , setname_list -> items [i ], MP_MAP_LOOKUP );
1264
+ mp_obj_t set_name_method [4 ] = { [2 ] = MP_OBJ_FROM_PTR (o ), [3 ] = elem -> key };
1265
+ mp_load_method (elem -> value , MP_QSTR___set_name__ , set_name_method );
1266
+ mp_call_method_n_kw (2 , 0 , set_name_method );
1267
+ }
1268
+ nlr_pop ();
1269
+ } else {
1270
+ m_del_obj (& mp_type_list , setname_list );
1271
+ nlr_raise (nlr .ret_val );
1272
+ }
1273
+ m_del_obj (& mp_type_list , setname_list );
1259
1274
#endif
1260
1275
1261
1276
return MP_OBJ_FROM_PTR (o );
0 commit comments