-
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Fix #9794: Pydantic integration fails with __future__.annotations. #9795
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
Conversation
When a project uses `from __future__ import annotations`, all annotations will be stored as strings. This is fairly common, and many projects dictate that any use of type annotations must be accompanied by this import. The Pydantic integration in Celery introspects the annotations to check if any parameters and/or the return type are subclasses of `pydantic.BaseModel`. This fails when the annotations are `str` instead of the actual class. This change fixes the issue by optimistically using `typing.get_type_hints()` instead of relying on the annotations included in the result of `inspect.signature()`. This works in most cases, although there can be cases where `get_type_hints()` fails due to circular import chains. In this case, we fall back to the old implementation. A new test has been added to t/integration/test_tasks.py to validate the issue.
for more information, see https://pre-commit.ci
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #9795 +/- ##
==========================================
- Coverage 78.62% 78.60% -0.02%
==========================================
Files 153 153
Lines 19178 19186 +8
Branches 2540 2542 +2
==========================================
+ Hits 15079 15082 +3
- Misses 3809 3812 +3
- Partials 290 292 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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.
Pull Request Overview
This PR addresses a bug where Pydantic‐typed task annotations stored as strings (due to from __future__ import annotations) aren’t correctly recognized. It switches to using typing.get_type_hints() with a fallback and adds a new integration test to cover this case.
- Use
typing.get_type_hints()first, falling back to raw signature annotations on failure. - Add a new task
add_pydantic_string_annotationswith string annotations. - Add an integration test
test_pydantic_string_annotationsto validate the fix.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| celery/app/base.py | Resolve string annotations via get_type_hints() with fallback. |
| t/integration/tasks.py | Define new test task add_pydantic_string_annotations. |
| t/integration/test_tasks.py | Add test_pydantic_string_annotations to cover string annotations. |
Comments suppressed due to low confidence (2)
celery/app/base.py:135
- Consider also catching
RecursionErrorfromget_type_hints(), as circular import chains can raise it. This ensures the fallback path handles all common failures.
except (NameError, AttributeError, TypeError):
t/integration/tasks.py:497
- [nitpick] Per PEP8, add two blank lines before top-level function definitions for better readability.
@shared_task(pydantic=True)
Description
When a project uses
from __future__ import annotations, all annotations will be stored as strings. This is fairly common, and many projects dictate that any use of type annotations must be accompanied by this import.The Pydantic integration in Celery introspects the annotations to check if any parameters and/or the return type are subclasses of
pydantic.BaseModel. This fails when the annotations arestrinstead of the actual class.This change fixes the issue by optimistically using
typing.get_type_hints()instead of relying on the annotations included in the result ofinspect.signature(). This works in most cases, although there can be cases whereget_type_hints()fails due to circular import chains. In this case, we fall back to the old implementation. A new test has been added to t/integration/test_tasks.py to validate the issue.