Header image for TestProva

TestProva

Prompt

Implementa in Python 3.12 la funzione: async def retry_async( fn, *, attempts: int = 3, base_delay: float = 0.1, retry_on: tuple[type[Exception], ...] = (Exception,), sleep=asyncio.sleep, ): ... Requisiti: - `fn` è una callable asincrona senza argomenti. - `attempts` indica il numero TOTALE massimo di esecuzioni, non il numero di retry. - Se `attempts < 1`, solleva ValueError senza eseguire `fn`. - Se `fn` termina correttamente, restituisci immediatamente il suo risultato. - Ritenta solo se l'eccezione appartiene a `retry_on`. - Le altre eccezioni devono essere rilanciate immediatamente. - Dopo l'ultimo tentativo fallito, rilancia la stessa eccezione senza fare sleep. - Usa exponential backoff: base_delay base_delay * 2 base_delay * 4 ... - `sleep` è iniettato per rendere la funzione facilmente testabile. - Non catturare BaseException. - Aggiungi type hints ragionevoli. - Non usare librerie esterne. Fornisci: 1. l'implementazione; 2. una piccola suite di test con pytest che verifichi almeno: - successo al primo tentativo; - successo dopo due errori; - esaurimento dei tentativi; - eccezione non retryable; - attempts=0; - corretta sequenza dei delay. Mantieni la soluzione semplice e idiomatica: niente classi o astrazioni non necessarie.