In order to lose the parenthesis, lookup needs to resolve to a dictionary rather than a function.
As well as defining attributes statically (with the QSTR/obj pointer) you can implement a .attr function which will do the lookup at runtime.
IIRC the struct/uctypes classes do a dynamic lookup via the .attr function.
For an example of how this is done statically, take a look at the pins. Something like machine.Pin.cpu.A3
pin.c has the Pin module. The board and cpu attributes are pointers to dictionaries:
https://github.com/micropython/micropyt ... #L548-L549
which you can see defined here:
https://github.com/micropython/micropyt ... .c#L34-L44
The actual contents of those dictionaries are generated, so you need to look in the build directory. For the PYBV11 board, you'd look at
ports/stm32/build-PYBV11/pins_PYBV11.c file and you'll see that pin_cpu_pins_locals_dict_table looks like:
Code: Select all
STATIC const mp_rom_map_elem_t pin_cpu_pins_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_A0_obj) },
{ MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_A1_obj) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_A2_obj) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_A3_obj) },
{ MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_A4_obj) },
...
{ MP_ROM_QSTR(MP_QSTR_C13), MP_ROM_PTR(&pin_C13_obj) },
{ MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_D2_obj) },
};
MP_DEFINE_CONST_DICT(pin_cpu_pins_locals_dict, pin_cpu_pins_locals_dict_table);