What is printed, given the context manager and how exceptions interact with yield?
from contextlib import contextmanager
@contextmanager
def cm():
print('enter')
try:
yield
finally:
print('cleanup')
try:
with cm():
raise ValueError('boom')
except ValueError:
print('caught')