# Asyncio Desk > Audit the asyncio in Python code before it ships - does it freeze the event loop, silently skip work, lose tasks and errors, or swallow cancellation - then fix it. The free check runs in the browser and uploads nothing: it lexes pasted Python (one or more files, plus pyproject.toml for the Python version), rebuilds its blocks from indentation, inventories every coroutine, awaited call, task, gather, wait, blocking call, lock, queue, session and except that can catch CancelledError, and runs 18 deterministic checks drawn from asyncio practice. The paid audit rates the event loop, tasks, cancellation and resources, confirms or dismisses every flag and gives exact before/after edits per finding; the paid fix lane writes the whole fixed file(s) and a changes list tied to the flags. The page checks every quote and line against the paste, applies every edit and file back into the paste and re-runs its checks, and calls out a reply that repeats a credential from the paste. App: https://asyncio-desk.skillsafe.ai/ API tutorial: https://asyncio-desk.skillsafe.ai/api.html ## Input - The code pasted into one box, each file introduced by a `# file: ` line; dropped files or a dropped package folder are joined that way automatically. A paste with no `# file:` line is read as one file (app.py). pyproject.toml, when pasted, gives the Python version (`asyncio.TaskGroup` and `asyncio.timeout` need 3.11). - Nothing is imported or run: every flag is a reading of the text, with the file and line it points at. Strings and comments are lexed out first, so a string that mentions time.sleep( is never a finding. - Whether an imported function is a coroutine, or blocks, is outside the check (AP-19 says so); asyncio debug mode (`PYTHONASYNCIODEBUG=1`) stays the ground truth for slow callbacks and never-awaited coroutines. ## Flags the free check raises - AP-01 (high): time.sleep inside a coroutine - the whole loop stops. - AP-02 (high): a blocking network call inside a coroutine - requests, urllib, sync httpx, socket, smtplib, or a method of a requests.Session / httpx.Client variable. - AP-03 (medium): a blocking subprocess, database (sqlite3, psycopg2, pymysql, sync redis, pymongo) or thread-queue call inside a coroutine; one flag per coroutine with every line. - AP-04 (low): blocking file I/O inside a coroutine - open(), Path.read_text/write_text, shutil. - AP-05 (high): a coroutine called without await - a bare call of an async def in the paste, asyncio.sleep, an asyncio.Queue put/get or Lock acquire, or a result assigned and then indexed as if it were the value. - AP-06 (medium): asyncio.create_task / ensure_future whose task is neither kept nor awaited. - AP-07 (high): a bare except, except BaseException or except CancelledError in a coroutine that does not re-raise (awaiting a task it cancelled itself is exempt). - AP-08 (medium): asyncio.gather(..., return_exceptions=True) whose results are never checked with isinstance. - AP-09 (high): asyncio.run, run_until_complete or run_forever inside a coroutine. - AP-10 (high): a while True / while flag loop in a coroutine that never awaits. - AP-11 (medium): a threading.Lock (with lock: or acquire) or threading.Event.wait inside a coroutine. - AP-12 (medium): await lock.acquire() on an asyncio Lock/Semaphore with no release in a finally. - AP-13 (medium): an aiohttp.ClientSession, httpx.AsyncClient or asyncpg connection created in a function, not in async with and never closed. - AP-14 (medium): asyncio.wait with FIRST_COMPLETED, FIRST_EXCEPTION or a timeout whose pending tasks are never cancelled. - AP-15 (low): gather over a comprehension, or create_task in a loop over input, with no Semaphore anywhere (a fixed pool over range(n) is exempt). - AP-16 (low): asyncio.get_event_loop() inside a coroutine, or get_event_loop + run_until_complete to start the program. - AP-17 (low): an async def that never awaits (stubs, dunders, async generators and route handlers are exempt). - AP-18 (low): an asyncio.Queue() without maxsize that is filled in a loop. - AP-19 (info): context - counts, the Python version, what is outside the check. ## Free extras - Every blocking call with the coroutine it is in; every task with its kind, target and whether its reference is kept; every lock, queue, event, session and connection with its kind; every except that can catch CancelledError and whether it re-raises. - Put any audit finding (or all of them, or the fixed files) back into the paste and re-run the check; undo puts the original back. - Exports: the check as Markdown, the flags as CSV, the edited or fixed code, the findings or changes as CSV, the whole result as JSON. ## Paid lanes (the `task` field) - `audit`: `{task, verdict: blocked|needs_work|ready, headline, service, areas: [{area: event_loop|tasks|cancellation|resources, status: sound|fragile|broken, note}], findings: [{id, flags, file, line, severity, area, title, evidence, why, edits: [{before, after}]}], flag_answers: [{flag, status: confirmed|dismissed, reason}], plan, questions, summary}`. `before` is an exact slice of the file, applied in order. - `fix`: `{task, verdict: fixed|partial, headline, files: [{path, content}], changes: [{file, function, flags, change, why}], verify, open: [{item, flags, reason}], questions, summary}`. `content` is the whole file; every function keeps its name, parameters and def or async def. - Run input: `{task, code, facts, note?, audit_handoff?, retry_note?}` - all strings; `facts` is the page's analysis as a JSON string. The audit hands its findings to the fix lane with every edit applied to `code`. - Model: gpt-terra, 10% publisher markup. A run needs a signed-in account; the reservation shown before a run is a hold, and only what the run uses is charged. ## Sources - async-python-patterns by Seth Hobson, wshobson/agents (github.com/wshobson/agents, plugins/python-development/skills/async-python-patterns), MIT - https://skillsafe.ai/skill/@wshobson/async-python-patterns - The checks and the reconciliation are original to this app. Python is a trademark of the Python Software Foundation; this app is not affiliated with the PSF.