mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-05 16:10:36 +00:00
![]()
Some checks are pending
CI / mkdocs (push) Waiting to run
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
## Summary This PR adds a new lint, `invalid-await`, for all sorts of reasons why an object may not be `await`able, as discussed in astral-sh/ty#919. Precisely, `__await__` is guarded against being missing, possibly unbound, or improperly defined (expects additional arguments or doesn't return an iterator). Of course, diagnostics need to be fine-tuned. If `__await__` cannot be called with no extra arguments, it indicates an error (or a quirk?) in the method signature, not at the call site. Without any doubt, such an object is not `Awaitable`, but I feel like talking about arguments for an *implicit* call is a bit leaky. I didn't reference any actual diagnostic messages in the lint definition, because I want to hear feedback first. Also, there's no mention of the actual required method signature for `__await__` anywhere in the docs. The only reference I had is the `typing` stub. I basically ended up linking `[Awaitable]` to ["must implement `__await__`"](https://docs.python.org/3/library/collections.abc.html#collections.abc.Awaitable), which is insufficient on its own. ## Test Plan The following code was tested: ```python import asyncio import typing class Awaitable: def __await__(self) -> typing.Generator[typing.Any, None, int]: yield None return 5 class NoDunderMethod: pass class InvalidAwaitArgs: def __await__(self, value: int) -> int: return value class InvalidAwaitReturn: def __await__(self) -> int: return 5 class InvalidAwaitReturnImplicit: def __await__(self): pass async def main() -> None: result = await Awaitable() # valid result = await NoDunderMethod() # `__await__` is missing result = await InvalidAwaitReturn() # `__await__` returns `int`, which is not a valid iterator result = await InvalidAwaitArgs() # `__await__` expects additional arguments and cannot be called implicitly result = await InvalidAwaitReturnImplicit() # `__await__` returns `Unknown`, which is not a valid iterator asyncio.run(main()) ``` --------- Co-authored-by: Carl Meyer <carl@astral.sh> |
||
---|---|---|
.. | ||
attribute_assignment.md | ||
invalid_argument_type.md | ||
invalid_await.md | ||
no_matching_overload.md | ||
semantic_syntax_errors.md | ||
shadowing.md | ||
single_matching_overload.md | ||
union_call.md | ||
unpacking.md | ||
unresolved_import.md | ||
unresolved_reference.md | ||
unsupported_bool_conversion.md | ||
version_related_syntax_errors.md |