Is it possible to implement a python property in a c implemented module?
I have an instance method, class method and class constant but can't find an example of a property.
//instance method
{ MP_OBJ_NEW_QSTR(MP_QSTR_circle), (mp_obj_t)&pyb_tft_circle_obj },
//class method
{ MP_OBJ_NEW_QSTR(MP_QSTR_color), (mp_obj_t)&tft_color_obj },
//class constant
{ MP_OBJ_NEW_QSTR(MP_QSTR_BLACK), MP_OBJ_NEW_SMALL_INT(TFT_COLOR_BLACK) },
Implement a property in a builtin module
Implement a property in a builtin module
End of line...
Re: Implement a property in a builtin module
I think you have to implement it as load_attr/store_attr (at least that is what I'm using and it works ok), but maybe I'm overlooking something and there's another way.
Anyway see objmodule.c for a possible implementation which just loads/stores to the module's dict
Anyway see objmodule.c for a possible implementation which just loads/stores to the module's dict
Code: Select all
STATIC void module_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_module_t *self = self_in;
mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) {
dest[0] = elem->value;
}
}
STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
mp_obj_module_t *self = self_in;
if (value == MP_OBJ_NULL) {
// delete attribute
mp_obj_dict_delete(self->globals, MP_OBJ_NEW_QSTR(attr));
} else {
// store attribute
// TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
mp_obj_dict_store(self->globals, MP_OBJ_NEW_QSTR(attr), value);
}
return true;
}
const mp_obj_type_t mp_type_module = {
{ &mp_type_type },
.name = MP_QSTR_module,
.print = module_print,
.load_attr = module_load_attr,
.store_attr = module_store_attr,
};
Re: Implement a property in a builtin module
Thanks for the help. I got my "size" property working but all methods and variables broke.
It seems that if I set .load_attr then my .locals_dict is not accessible. help() shows all of my methods but attempting to call them returns an error TFT object has not attribute ???.
It seems that if I set .load_attr then my .locals_dict is not accessible. help() shows all of my methods but attempting to call them returns an error TFT object has not attribute ???.
End of line...
Re: Implement a property in a builtin module
Currently the code assumes that if load_attr exists. then it does the right thing.
I think that mp_load_method_maybe (from py/runtime.c) is the function that makes this decision.
It might be interesting to split out this portion: https://github.com/micropython/micropyt ... #L900-L928 into a separate function so that you could override load_attr and have it call the new method if load_attr didn't find what it was looking for.
You should probably bring this up as an issue on github in case there is a better way to implement what you want.
I think that mp_load_method_maybe (from py/runtime.c) is the function that makes this decision.
It might be interesting to split out this portion: https://github.com/micropython/micropyt ... #L900-L928 into a separate function so that you could override load_attr and have it call the new method if load_attr didn't find what it was looking for.
You should probably bring this up as an issue on github in case there is a better way to implement what you want.
Re: Implement a property in a builtin module
I might do that but right now I'm trying a different approach. I am attempting to create an actual property using mp_obj_property_t. I have created the property and help() shows the property on my TFT class. But the property doesn't work. It simply returns a property object rather than calling the getter/setter. So I'm still doing something wrong but I think it's the better approach. I'll take a couple more stabs at it. Maybe create a test that builds in windows so I can debug it.
End of line...
Re: Implement a property in a builtin module
Or maybe just switch the two cases so if first checks locals_dict and then load_attr. Though likely there's a good reason it is the way it is now. Yet, it doesn't make much sense (to me) that when there is a load_attr the type has to do al the work itself?dhylands wrote:It might be interesting to split out this portion: https://github.com/micropython/micropyt ... #L900-L928 into a separate function so that you could override load_attr and have it call the new method if load_attr didn't find what it was looking for.