ruff/crates/ty_python_semantic/resources/mdtest
Andrii Turov 957320c0f1
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
[ty] Add diagnostics for invalid await expressions (#19711)
## 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>
2025-08-14 14:38:33 -07:00
..
annotations [ty] simplify return type of place_from_declarations (#19884) 2025-08-13 14:17:08 +00:00
assignment [ty] Return Option<TupleType> from infer_tuple_type_expression (#19735) 2025-08-04 13:48:19 +01:00
binary [ty] Remove special casing for string-literal-in-tuple __contains__ (#19642) 2025-07-31 11:28:03 +01:00
boolean Revert "[ty] Better control flow for boolean expressions that are inside if (#18010)" (#18150) 2025-05-17 08:27:32 -04:00
boundness_declaredness Update class literal display to use <class 'Foo'> style (#17889) 2025-05-06 20:11:25 -04:00
call [ty] Remove Type::Tuple (#19669) 2025-08-11 22:03:32 +01:00
class [ty] Remove use of ClassBase::try_from_type from super() machinery (#19902) 2025-08-14 22:14:31 +01:00
comparison [ty] Enum literal types (#19328) 2025-07-15 21:31:53 +02:00
comprehensions [ty] Async for loops and async iterables (#19634) 2025-07-30 17:40:24 +02:00
conditional [ty] Support as-patterns in reachability analysis (#19728) 2025-08-04 20:13:50 +02:00
dataclasses [ty] support kw_only=True for dataclass() and field() (#19677) 2025-08-14 08:02:55 -07:00
declaration [ty] Format conflicting types as an enumeration (#18956) 2025-06-26 14:29:33 +02:00
diagnostics [ty] Add diagnostics for invalid await expressions (#19711) 2025-08-14 14:38:33 -07:00
directives [ty] Exhaustiveness checking & reachability for match statements (#19508) 2025-07-23 22:45:45 +02:00
doc ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
exception [ty] Use separate Rust types for bound and unbound type variables (#19796) 2025-08-11 15:29:58 -04:00
expression [ty] Support async/await, async with and yield from (#19595) 2025-07-30 11:51:21 +02:00
function [ty] Short circuit ReachabilityConstraints::analyze_single for dynamic types (#19867) 2025-08-11 21:58:34 +02:00
generics [ty] fix deferred name loading in PEP695 generic classes/functions (#19888) 2025-08-13 15:51:59 -07:00
ide_support [ty] Fix attribute access on TypedDicts (#19758) 2025-08-05 13:59:10 +02:00
import [ty] Implement module-level __getattr__ support (#19791) 2025-08-08 10:39:37 -07:00
literal [ty] Understand classes that inherit from subscripted Protocol[] as generic (#17832) 2025-05-09 17:39:15 +01:00
loops [ty] Async for loops and async iterables (#19634) 2025-07-30 17:40:24 +02:00
narrow [ty] more cases for the class body global fallback 2025-08-07 17:30:27 -07:00
regression
scopes [ty] fix deferred name loading in PEP695 generic classes/functions (#19888) 2025-08-13 15:51:59 -07:00
shadowing
snapshots [ty] Add diagnostics for invalid await expressions (#19711) 2025-08-14 14:38:33 -07:00
stubs [ty] Do not carry the generic context of Protocol or Generic in the ClassBase enum (#17989) 2025-05-22 21:37:03 -04:00
subscript [ty] Improve sys.version_info special casing (#19894) 2025-08-13 14:39:13 +01:00
suppressions [ty] Consistent use of American english (in rules) (#19488) 2025-07-22 16:10:38 +02:00
type_compendium [ty] Remove Type::Tuple (#19669) 2025-08-11 22:03:32 +01:00
type_of [ty] Improve the Display for generic type[] types (#19667) 2025-07-31 19:45:01 +01:00
type_properties [ty] Remove Type::Tuple (#19669) 2025-08-11 22:03:32 +01:00
type_qualifiers [ty] Keep track of type qualifiers in stub declarations without right-hand side (#19756) 2025-08-05 12:07:05 +02:00
unary Update class literal display to use <class 'Foo'> style (#17889) 2025-05-06 20:11:25 -04:00
with [ty] Diagnostics for async context managers (#19704) 2025-08-05 07:41:37 -07:00
.mdformat.toml
async.md [ty] Support async/await, async with and yield from (#19595) 2025-07-30 11:51:21 +02:00
attributes.md [ty] Infer type[tuple[int, str]] as the meta-type of tuple[int, str] (#19741) 2025-08-04 13:10:47 +00:00
cycle.md [ty] Add cycle handling for unpacking targets (#18078) 2025-05-13 21:27:48 +00:00
decorators.md ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
del.md [ty] Support __setitem__ and improve __getitem__ related diagnostics (#19578) 2025-08-01 09:23:27 +02:00
deprecated.md [ty] Consistent use of American english (in rules) (#19488) 2025-07-22 16:10:38 +02:00
descriptor_protocol.md [ty] Fix descriptor lookups for most types that overlap with None (#19120) 2025-07-05 19:34:23 +01:00
enums.md [ty] Exhaustiveness checking & reachability for match statements (#19508) 2025-07-23 22:45:45 +02:00
exhaustiveness_checking.md [ty] Support as-patterns in reachability analysis (#19728) 2025-08-04 20:13:50 +02:00
final.md
instance_layout_conflict.md [ty] Remove special casing for tuple addition (#19636) 2025-07-30 16:25:42 +00:00
intersection_types.md [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
invalid_syntax.md
known_constants.md
mdtest_config.md
mdtest_custom_typeshed.md [ty] Remove Type::Tuple (#19669) 2025-08-11 22:03:32 +01:00
metaclass.md Update class literal display to use <class 'Foo'> style (#17889) 2025-05-06 20:11:25 -04:00
mro.md [ty] Track different uses of legacy typevars, including context when rendering typevars (#19604) 2025-08-01 12:20:32 -04:00
named_tuple.md [ty] Synthesize read-only properties for all declared members on NamedTuple classes (#19899) 2025-08-14 21:25:45 +00:00
overloads.md [ty] Track different uses of legacy typevars, including context when rendering typevars (#19604) 2025-08-01 12:20:32 -04:00
pep695_type_aliases.md [ty] support recursive type aliases (#19805) 2025-08-12 09:03:10 -07:00
properties.md ty_python_semantic: add union type context to function call type errors 2025-05-09 13:40:51 -04:00
protocols.md [ty] fix deferred name loading in PEP695 generic classes/functions (#19888) 2025-08-13 15:51:59 -07:00
public_types.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
statically_known_branches.md [ty] Infer nonlocal types as unions of all reachable bindings (#18750) 2025-06-26 12:24:40 +02:00
sys_platform.md
sys_version_info.md
terminal_statements.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00
ty_extensions.md [ty] Rename type_api => ty_extensions (#19523) 2025-07-24 08:24:26 +00:00
typed_dict.md [ty] Validate writes to TypedDict keys (#19782) 2025-08-06 15:19:13 -07:00
union_types.md [ty] Expansion of enums into unions of literals (#19382) 2025-07-21 19:37:55 +02:00
unpacking.md [ty] Remove Type::Tuple (#19669) 2025-08-11 22:03:32 +01:00
unreachable.md [ty] improve lazy scope place lookup (#19321) 2025-07-25 07:11:11 +00:00