-
-
Notifications
You must be signed in to change notification settings - Fork 67
Fix alru_cache crash with deferred annotations on Python 3.14 #781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rodrigobnogueira
wants to merge
6
commits into
master
Choose a base branch
from
fix/deferred-annotations-py314
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+132
−8
Open
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
d098e0f
Fix alru_cache crash with deferred annotations on Python 3.14
rodrigobnogueira 60fa4fe
Execute the wrapped functions in the annotation parity test
rodrigobnogueira 235da6c
Rename the py314 marker to requires_py314
rodrigobnogueira 140a4b8
Merge branch 'master' into fix/deferred-annotations-py314
rodrigobnogueira 73906f3
Gate the __annotate__ copy on sys.version_info >= (3, 14)
rodrigobnogueira 26f7eda
Make the annotation-copy comments concise
rodrigobnogueira File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| """Tests for PEP 649 deferred annotations (Python 3.14+). | ||
|
|
||
| On Python 3.14 annotations are evaluated lazily via ``__annotate__``. | ||
| Copying ``fn.__annotations__`` eagerly at decoration time forces that | ||
| evaluation and crashes with ``NameError`` when the annotation refers to | ||
| a name defined after the decorated function, a pattern that works with | ||
| ``functools.lru_cache``. | ||
| """ | ||
|
|
||
| import inspect | ||
| import sys | ||
| from functools import lru_cache, partial | ||
|
|
||
| import pytest | ||
|
|
||
| from async_lru import alru_cache | ||
|
|
||
|
|
||
| requires_py314 = pytest.mark.skipif( | ||
| sys.version_info < (3, 14), | ||
| reason="deferred annotation evaluation requires Python 3.14", | ||
| ) | ||
|
|
||
|
|
||
| @requires_py314 | ||
| async def test_deco_with_annotation_defined_after() -> None: | ||
| @alru_cache(maxsize=1) | ||
| async def get_foo() -> Foo: | ||
| return Foo() | ||
|
|
||
| class Foo: | ||
| pass | ||
|
|
||
| first = await get_foo() | ||
| assert isinstance(first, Foo) | ||
| assert await get_foo() is first | ||
|
|
||
|
|
||
| @requires_py314 | ||
| async def test_annotations_stay_lazy_like_lru_cache() -> None: | ||
| @alru_cache(maxsize=1) | ||
| async def get_foo_async() -> Foo: | ||
| return Foo() | ||
|
|
||
| @lru_cache(maxsize=1) | ||
| def get_foo_sync() -> Foo: | ||
| return Foo() | ||
|
|
||
| class Foo: | ||
| pass | ||
|
|
||
| assert isinstance(await get_foo_async(), Foo) | ||
| assert isinstance(get_foo_sync(), Foo) | ||
| assert ( | ||
| inspect.get_annotations(get_foo_async) | ||
| == inspect.get_annotations(get_foo_sync) | ||
| == {"return": Foo} | ||
| ) | ||
|
|
||
|
|
||
| @requires_py314 | ||
| async def test_unresolvable_annotation_raises_only_on_access() -> None: | ||
| @alru_cache(maxsize=1) | ||
| async def broken() -> Missing: # type: ignore[name-defined] # noqa: F821 | ||
| pass # pragma: no cover | ||
|
|
||
| with pytest.raises(NameError): | ||
| inspect.get_annotations(broken) | ||
|
|
||
|
|
||
| async def test_method_wrapping_partial_without_annotation_attributes() -> None: | ||
| """A wrapped ``partial`` carries neither ``__annotate__`` nor | ||
| ``__annotations__``; binding it as a method copies neither.""" | ||
|
|
||
| async def impl(self: object) -> int: | ||
| return 42 | ||
|
|
||
| class Api: | ||
| meth = alru_cache(partial(impl)) | ||
|
|
||
| api = Api() | ||
| assert await api.meth() == 42 | ||
| assert not hasattr(api.meth, "__annotations__") | ||
|
|
||
|
|
||
| @requires_py314 | ||
| async def test_method_annotations_stay_lazy() -> None: | ||
| class Api: | ||
| @alru_cache(maxsize=1) | ||
| async def get_foo(self) -> Foo: | ||
| return Foo() | ||
|
|
||
| class Foo: | ||
| pass | ||
|
|
||
| api = Api() | ||
| assert isinstance(await api.get_foo(), Foo) | ||
| assert inspect.get_annotations(api.get_foo) == {"return": Foo} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should really make both comments concise like this. I'd also drop the prefix so there's less maintenance. We can see the version check below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 26f7eda — both comments trimmed, prefix dropped.