"""
Exercise 2: contextlib.contextmanager (generator-based context managers)

STEP 1: Implement `timer_block(label, log)` as a generator-based context
        manager using @contextmanager:
          - before yielding: append f"{label}: start" to `log`
          - yield nothing meaningful (yield None is fine) — this context
            manager's `as` target isn't used by callers
          - in a finally block: append f"{label}: end" to `log`, whether
            or not an exception occurred

STEP 2: Implement `suppress_and_log(exc_type, log)` as a second
        @contextmanager-based context manager:
          - wrap the yield in a try/except that catches exactly
            `exc_type`
          - on catching it: append f"suppressed {exc_type.__name__}" to
            `log`, and DO NOT re-raise (this is how a generator-based
            context manager suppresses an exception: catch it inside the
            generator and simply don't re-raise)
          - any exception that is NOT an instance of exc_type must
            propagate normally (don't catch it, or re-raise it if you do)
"""

from contextlib import contextmanager


@contextmanager
def timer_block(label, log):
    # TODO: append f"{label}: start" to log, then `yield`, then in a
    # finally block append f"{label}: end" to log
    yield


@contextmanager
def suppress_and_log(exc_type, log):
    # TODO: try: yield  except exc_type: log.append(f"suppressed {exc_type.__name__}")
    yield


# --- self-check: do not modify below this line ---
checks = []

log1 = []
with timer_block("task", log1):
    pass
checks.append(("timer_block logs start then end on normal exit",
                log1, ["task: start", "task: end"]))

log2 = []
raised = None
try:
    with timer_block("task2", log2):
        raise RuntimeError("boom")
except RuntimeError:
    raised = True
checks.append(("timer_block still logs end even when the block raises",
                log2, ["task2: start", "task2: end"]))
checks.append(("timer_block does NOT suppress the exception", raised, True))

log3 = []
with suppress_and_log(ValueError, log3):
    raise ValueError("nope")
checks.append(("suppress_and_log suppresses the matching exception type",
                log3, ["suppressed ValueError"]))

log4 = []
propagated = None
try:
    with suppress_and_log(ValueError, log4):
        raise TypeError("different type")
except TypeError:
    propagated = True
checks.append(("suppress_and_log lets a non-matching exception type propagate",
                propagated, True))

passed = 0
for label, actual, expected in checks:
    ok = actual == expected
    passed += ok
    print(f"{'PASS' if ok else 'FAIL'}: {label} (got {actual!r}, expected {expected!r})")

print("PASS" if passed == len(checks) else "FAIL")
