MediumPro challengePython

Avoid Nested Callbacks

PythonClean CodeAsyncRefactoring

Callback-passing style makes async code impossible to follow — a pyramid of doom.

# dirty — pyramid of doom
def build_pipeline(user_data, orders_data, products_data, on_done):
    def with_user(user):
        def with_orders(orders):
            def with_products(products):
                on_done({'user': user, 'orders': orders, 'products': products})
            fake_products(products_data, with_products)
        fake_orders(orders_data, with_orders)
    fake_user(user_data, with_user)

Refactor `solve(user_data, orders_data, products_data)` using async/await so the function is flat and readable.
Keep solve itself a regular (non-async) function — drive the coroutine internally with asyncio.run(...).

solve({'id': 'u1', 'name': 'Alice'}, [{'id': 'o1'}], [{'id': 'p1'}]){'user': ..., 'orders': ..., 'products': ...}

Sample tests

Test #1Multiple products
Input: [{"id":"u3","name":"Carol"},[{"id":"o4"}],[{"id":"p2"},{"id":"p3"}]]
Output: {"user":{"id":"u3","name":"Carol"},"orders":[{"id":"o4"}],"products":[{"id":"p2"},{"id":"p3"}]}
Test #2Resolves all three levels and returns combined result
Input: [{"id":"u1","name":"Alice"},[{"id":"o1"}],[{"id":"p1","title":"Book"}]]
Output: {"user":{"id":"u1","name":"Alice"},"orders":[{"id":"o1"}],"products":[{"id":"p1","title":"Book"}]}
Test #3Multiple orders, empty products
Input: [{"id":"u2","name":"Bob"},[{"id":"o2"},{"id":"o3"}],[]]
Output: {"user":{"id":"u2","name":"Bob"},"orders":[{"id":"o2"},{"id":"o3"}],"products":[]}