Challenge 2: A Class-Based Logging Context Manager — Possible Solution ==================================================================== class LogSection: def __init__(self, name): self.name = name def __enter__(self): print(f"Entering {self.name}") return self def __exit__(self, exc_type, exc_value, traceback): print(f"Exiting {self.name}") return False with LogSection("data processing"): print("doing work...") print("still working...") Output: Entering data processing doing work... still working... Exiting data processing WHY THIS WORKS AS AN ANSWER ------------------------------ __init__(self, name) stores name as an ordinary instance attribute, reusing Course 2 Chapter 1's constructor pattern — nothing about context managers changes how a normal __init__ works. __enter__(self) reuses this chapter's own Timer.__enter__ structure: it runs the moment the with block starts, prints the "Entering ..." message using an f-string (Course 1, Chapter 5), and returns self — though this challenge doesn't use the with ... as x: form, so the returned value is simply discarded, which is perfectly valid. __exit__(self, exc_type, exc_value, traceback) reuses this chapter's own Timer.__exit__ signature exactly, including the required three parameters that carry exception details. It prints the "Exiting ..." message and returns False, following this chapter's warn-box guidance to never suppress an exception unintentionally — since this challenge doesn't need to swallow any error, False (or no return at all, which defaults to None, also falsy) is the correct choice. The two print("...") lines inside the with block run between __enter__ and __exit__ automatically, and — per the chapter's own guarantee — __exit__ would still run and print "Exiting data processing" even if one of those lines raised an exception instead of completing normally.