Psycopg 3 supports both sync and async code. Starting from release 3.2, the sync side is automatically generated from the async counterpart. This article explains how it's done, and the workflow used for the initial conversion to autogenerated code and for the regular maintenance.
and then generate a bunch of sync and async closures that capture that_call and then call the right things. In the typical API that you might want to compose sync/async I find at least 90% can be generated that way but working at the AST level you can get the last bit.