I personally consider code generation an anti-pattern in Python. With its dynamic nature and the two-step execution model, Python is essentially its own macro language, and any generation can be done at runtime.
unfortunately pep-484 changed all that. now you have to use static generation for basically anything that used to be at runtime previously, if you want it to have any kind of compatibility with mypy, pylance, etc.
when people using your library need pylance type hinting to show up for all your public methods, and those public methods are in fact generated as proxies for some other object. This was trivial as a dynamic runtime thing before, now must be statically generated. I can share examples if you'd like.