Several hot paths use assert ... is not None to narrow client._transport, client.auto_ack, runtime.credential_provisioner, and runtime.revocation_log before dereferencing them. The pattern appears at src/arcp/_client/client.py:151, src/arcp/_client/client.py:188, src/arcp/_client/ops.py:55, src/arcp/_client/ops.py:87, src/arcp/_client/ops.py:108, src/arcp/_client/ops.py:134, src/arcp/_client/ops.py:171, src/arcp/_client/ops.py:186, src/arcp/_client/dispatch.py:69, src/arcp/_runtime/_handlers.py:193, and src/arcp/_runtime/_job_runner.py:157. The runtime is shipped as a library, so an embedder running python -O or PYTHONOPTIMIZE=1 strips every one of those checks: the code then attempts to call .send, .bind, or .issue on None and raises AttributeError: 'NoneType' object has no attribute ... in the middle of a session instead of the intended InternalError or early-fail behavior. Pyright also reads these asserts as type narrowing, so removing them would surface real None-handling holes that are presently invisible. This is a Python-specific footgun called out in PEP 8 and the assert documentation explicitly: assert is for invariants the program may not need at runtime, not for control flow.
Fix prompt: Replace every assert ... is not None that narrows a load-bearing attribute in src/arcp/_client/ and src/arcp/_runtime/ with an explicit if x is None: raise InternalError("transport not connected") (or the appropriate ARCPError subclass). Keep assert only for genuine developer-time invariants that are safe to strip. Add a regression test that imports the package under python -O and exercises ARCPClient.submit against a disconnected client to confirm the explicit error path fires instead of an AttributeError. After the change, run uv run pyright and resolve any newly surfaced None-related diagnostics rather than re-adding the asserts.
Several hot paths use
assert ... is not Noneto narrowclient._transport,client.auto_ack,runtime.credential_provisioner, andruntime.revocation_logbefore dereferencing them. The pattern appears atsrc/arcp/_client/client.py:151,src/arcp/_client/client.py:188,src/arcp/_client/ops.py:55,src/arcp/_client/ops.py:87,src/arcp/_client/ops.py:108,src/arcp/_client/ops.py:134,src/arcp/_client/ops.py:171,src/arcp/_client/ops.py:186,src/arcp/_client/dispatch.py:69,src/arcp/_runtime/_handlers.py:193, andsrc/arcp/_runtime/_job_runner.py:157. The runtime is shipped as a library, so an embedder runningpython -OorPYTHONOPTIMIZE=1strips every one of those checks: the code then attempts to call.send,.bind, or.issueonNoneand raisesAttributeError: 'NoneType' object has no attribute ...in the middle of a session instead of the intendedInternalErroror early-fail behavior. Pyright also reads these asserts as type narrowing, so removing them would surface realNone-handling holes that are presently invisible. This is a Python-specific footgun called out in PEP 8 and the assert documentation explicitly:assertis for invariants the program may not need at runtime, not for control flow.Fix prompt: Replace every
assert ... is not Nonethat narrows a load-bearing attribute insrc/arcp/_client/andsrc/arcp/_runtime/with an explicitif x is None: raise InternalError("transport not connected")(or the appropriate ARCPError subclass). Keepassertonly for genuine developer-time invariants that are safe to strip. Add a regression test that imports the package underpython -Oand exercisesARCPClient.submitagainst a disconnected client to confirm the explicit error path fires instead of anAttributeError. After the change, runuv run pyrightand resolve any newly surfacedNone-related diagnostics rather than re-adding the asserts.