@@ -229,15 +229,35 @@ STATIC mp_obj_t class_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
229229STATIC void class_load_attr (mp_obj_t self_in , qstr attr , mp_obj_t * dest ) {
230230 // logic: look in obj members then class locals (TODO check this against CPython)
231231 mp_obj_class_t * self = self_in ;
232+
232233 mp_map_elem_t * elem = mp_map_lookup (& self -> members , MP_OBJ_NEW_QSTR (attr ), MP_MAP_LOOKUP );
233234 if (elem != NULL ) {
234235 // object member, always treated as a value
236+ // TODO should we check for properties?
235237 dest [0 ] = elem -> value ;
236238 return ;
237239 }
240+
238241 mp_obj_t member = mp_obj_class_lookup (self -> base .type , attr );
239242 if (member != MP_OBJ_NULL ) {
240- class_convert_return_attr (self_in , member , dest );
243+ if (0 ) {
244+ #if MICROPY_ENABLE_PROPERTY
245+ } else if (MP_OBJ_IS_TYPE (member , & mp_type_property )) {
246+ // object member is a property
247+ // delegate the store to the property
248+ // TODO should this be part of class_convert_return_attr?
249+ const mp_obj_t * proxy = mp_obj_property_get (member );
250+ if (proxy [0 ] == mp_const_none ) {
251+ // TODO
252+ } else {
253+ dest [0 ] = mp_call_function_n_kw (proxy [0 ], 1 , 0 , & self_in );
254+ // TODO should we convert the returned value using class_convert_return_attr?
255+ }
256+ #endif
257+ } else {
258+ // not a property
259+ class_convert_return_attr (self_in , member , dest );
260+ }
241261 return ;
242262 }
243263
@@ -257,10 +277,30 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
257277
258278STATIC bool class_store_attr (mp_obj_t self_in , qstr attr , mp_obj_t value ) {
259279 mp_obj_class_t * self = self_in ;
280+
281+ #if MICROPY_ENABLE_PROPERTY
282+ // for property, we need to do a lookup first in the class dict
283+ // this makes all stores slow... how to fix?
284+ mp_obj_t member = mp_obj_class_lookup (self -> base .type , attr );
285+ if (member != MP_OBJ_NULL && MP_OBJ_IS_TYPE (member , & mp_type_property )) {
286+ // attribute already exists and is a property
287+ // delegate the store to the property
288+ const mp_obj_t * proxy = mp_obj_property_get (member );
289+ if (proxy [1 ] == mp_const_none ) {
290+ // TODO better error message
291+ return false;
292+ } else {
293+ mp_obj_t dest [2 ] = {self_in , value };
294+ mp_call_function_n_kw (proxy [1 ], 2 , 0 , dest );
295+ return true;
296+ }
297+ }
298+ #endif
299+
260300 if (value == MP_OBJ_NULL ) {
261301 // delete attribute
262- mp_map_elem_t * el = mp_map_lookup (& self -> members , MP_OBJ_NEW_QSTR (attr ), MP_MAP_LOOKUP_REMOVE_IF_FOUND );
263- return el != NULL ;
302+ mp_map_elem_t * elem = mp_map_lookup (& self -> members , MP_OBJ_NEW_QSTR (attr ), MP_MAP_LOOKUP_REMOVE_IF_FOUND );
303+ return elem != NULL ;
264304 } else {
265305 // store attribute
266306 mp_map_lookup (& self -> members , MP_OBJ_NEW_QSTR (attr ), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )-> value = value ;
0 commit comments