"""
Exercise 3: tasks and cancellation (hardest)

STEP 1: Implement `worker(log)` — an async function that:
          - appends "started" to the list `log`
          - tries to `await asyncio.sleep(10)`
          - if an `asyncio.CancelledError` is raised during that sleep,
            append "cancelled" to `log` and RE-RAISE the CancelledError
            (do not swallow it)
          - if it were somehow never cancelled, it would append "finished"
            to `log` and return "finished" (this path is not exercised by
            the self-check, but write it anyway for completeness)

STEP 2: Implement `run_and_cancel()` — no arguments. It should:
          - create a fresh list `log = []`
          - create a task from `worker(log)` with `asyncio.create_task`
          - await `asyncio.sleep(0.05)` (give the task a moment to start
            and reach its own internal `await asyncio.sleep(10)`)
          - call `.cancel()` on the task
          - await the task inside a try/except that catches
            `asyncio.CancelledError` and does nothing (this is the ONLY
            place in this exercise allowed to swallow it, since it's the
            top-level awaiter observing an expected cancellation)
          - return `log`
"""

import asyncio


async def worker(log):
    log.append("started")
    try:
        await asyncio.sleep(10)
        log.append("finished")
        return "finished"
    except asyncio.CancelledError:
        # TODO: append "cancelled" to log, then re-raise (bare `raise`)
        pass


async def run_and_cancel():
    log = []
    # TODO:
    #   task = asyncio.create_task(worker(log))
    #   await asyncio.sleep(0.05)
    #   task.cancel()
    #   try:
    #       await task
    #   except asyncio.CancelledError:
    #       pass
    #   return log
    pass


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

result_log = asyncio.run(run_and_cancel())
checks.append(("worker logs 'started' before being cancelled",
                result_log[:1] if result_log else None, ["started"]))
checks.append(("worker logs 'cancelled' after catching CancelledError",
                result_log[-1] if result_log else None, "cancelled"))
checks.append(("worker never reaches 'finished' — it was cancelled first",
                "finished" in result_log, False))
checks.append(("log has exactly 2 entries: started, cancelled",
                len(result_log), 2))

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")
