module.__getattr__ works pretty well for normal access, after being imported by another module, but it doesn't properly trigger loading by functions defined in the module's own namespace.
The idea of my PEP is to be very simple (both semantically and in terms of implementation). This is why I don't want to add any complex logic. People who will want to use __getattr__ for lazy loading still can do this by importing submodules.
The main two use cases I know of for this and PEP 549 are lazy imports of submodules, and deprecating attributes.
Yes, lazy loading seems to be a popular idea :-) I will add the simple recipe by Inada to the PEP since it will already work.
I still think the better way to solve the custom dir() would be to change the module __dir__ method to check if __all__ is defined and use it to generate the result if it exists. This seems like a logical enhancement to me, and I'm planning on writing a patch to implement this. Whether it would be accepted is still an open issue though.
This seems a reasonable rule to me, I can also make this patch if you will not have time.
@Guido What do you think about the above idea?