Python cocktail: mix a context manager and an iterator in equal parts
bitecode.dev
bitecode.dev
The tenacity library comes with an intriguing mix of iterators and context managers to allow the users to retry blocks with this syntax:
from tenacity import Retrying, stop_after_attempt
for attempt in Retrying(stop=stop_after_attempt(3)):
with attempt:
1 / 0
You can use the same mechanism yourself, by creating and linking a custom context manager and iterator: class YouAndIhaveUnfinishedBusiness:
def __init__(self, notify_success, attempt_number):
self.notify_success = notify_success
self.attempt = attempt_number
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
if exc_value:
print(f"You have disappointed me {self.attempt} time(s).")
else:
self.notify_success()
return True
class DoOrDoNotThereIsNoTry:
def __init__(self, max_attempts):
self.max_attempts = max_attempts
self.success = False
def __iter__(self):
for i in range(self.max_attempts):
yield YouAndIhaveUnfinishedBusiness(self.succeed, i+1)
if self.success:
print("You are ready for the Kumite.")
break
else:
print("We trained him wrong on purpose, as a joke.")
def succeed(self):
self.success = True