Avatar for the astral-sh user
astral-sh
ruff
BlogDocsChangelog

Performance History

Latest Results

GitHub Actions run
1 second ago
[ty] Preserve declaration order when synthesizing class fields
charlie/declaration-order
5 seconds ago
nonlocal3 WIP
jack/nonlocal3
40 minutes ago
Fix performance
samuelcolvin:parse-recursion-limit
2 hours ago
[ty] Support class decorators (#25091) ## Summary This PR adds support for class decorator return types, following Carl's comment in https://github.com/astral-sh/ty/issues/2604#issuecomment-3793310652: assume unannotated decorators preserve the class binding when their result is otherwise `Unknown`, but support explicit spelling of an annotated decorator return type. In more detail, the rule is roughly: - If applying the decorator gives a non-`Unknown` result... - And that result still retains the original class object, we preserve the class. - Otherwise, we replace the public binding with that result. - If applying the decorator gives an `Unknown` result: - We fall back to the decorator’s own shape. - Unannotated function/method decorators are treated as "identity-preserving", so we keep the current class binding. - Decorators with an explicit return annotation are not, so we do _not_ preserve the binding. As a concrete example, an unannotated decorator like the personify example from #2604 is still treated as preserving the original class (since we don't have a static replacement type): ```python def personify(cls): class Wrapped(cls): full_name: str def set_full_name(self, full_name: str) -> None: self.full_name = full_name return Wrapped @personify class Animal: ... reveal_type(Animal) # <class 'Animal'> Animal().set_full_name("John") # error: unresolved attribute ``` But if the decorator has an explicit return type, we use it for the public class binding: ```python class WrapBackend: def __init__(self, cls: type[object]) -> None: ... def get(self, key: str) -> bytes | None: ... @WrapBackend class CacheClient: ... reveal_type(CacheClient) # WrapBackend reveal_type(CacheClient.get("x")) # bytes | None ``` This gives us stable behavior for common untyped identity decorators while leaving the advanced and unsound returned-class inference path out of scope... Closes https://github.com/astral-sh/ty/issues/143.
main
2 hours ago

Latest Branches

CodSpeed Performance Gauge
0%
[ty] Preserve declaration order when synthesizing class fields#25249
27 minutes ago
bba1d8c
charlie/declaration-order
CodSpeed Performance Gauge
-4%
13 days ago
bd87a25
jack/nonlocal3
CodSpeed Performance Gauge
0%
1 day ago
b02bcaa
samuelcolvin:parse-recursion-limit
© 2026 CodSpeed Technology
Home Terms Privacy Docs