-
Notifications
You must be signed in to change notification settings - Fork 184
Fix pickling ABC classes with type annotations (Python 3.13+) #577
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
In Python 3.13+ (PEP 649), classes with annotations have an __annotate__ function that may have closures referencing unpicklable objects in the class namespace (like _abc._abc_data in _abc_impl). This fix removes __annotate__ from the pickled class state, allowing Python to regenerate it from __annotations__ when the class is reconstructed. Co-authored-by: ogrisel <89061+ogrisel@users.noreply.github.com>
Co-authored-by: ogrisel <89061+ogrisel@users.noreply.github.com>
Co-authored-by: ogrisel <89061+ogrisel@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #577 +/- ##
==========================================
+ Coverage 96.33% 96.34% +0.01%
==========================================
Files 3 3
Lines 573 575 +2
Branches 120 120
==========================================
+ Hits 552 554 +2
Misses 11 11
Partials 10 10 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@copilot Since this bug impacts CPython 3.14 only, please make sure that the tests pass with the version. |
Add removal of __annotate_func__ in addition to __annotate__ to ensure compatibility with Python 3.14 where both attribute names may be present. Co-authored-by: ogrisel <89061+ogrisel@users.noreply.github.com>
I've updated the fix to also handle |
|
@copilot please also make sure to remove any unrelated formatting changes to this PR. The linters were fine with the previous version of the code so those formatting changes are probably not needed. |
Reverted all unrelated formatting changes and kept only the substantive fix for ABC classes with annotations. The changes now only include: - Addition of __annotate__ and __annotate_func__ removal in _class_getstate() - Addition of test_abc_with_annotations() test Co-authored-by: ogrisel <89061+ogrisel@users.noreply.github.com>
I've removed all unrelated formatting changes (commit 361947a). The PR now only contains the substantive bug fix and test, with no formatting changes. Ruff linting passes. |
ogrisel
left a comment
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.
Thanks the PR, the final state is clean. However, this bug was fixed in #578 first so I will merge it instead.
| # that may have closures referencing unpicklable objects in the class | ||
| # namespace. We don't need to pickle it as Python will regenerate it from | ||
| # __annotations__ when the class is reconstructed. | ||
| clsdict.pop("__annotate__", None) |
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.
This is probably useless.
Summary
Successfully fixed the issue where abstract classes (using
abc.ABC) with type annotations could not be pickled in Python 3.13+.Changes Made
1. Core Fix (
cloudpickle/cloudpickle.py)clsdict.pop("__annotate__", None)in the_class_getstate()functionclsdict.pop("__annotate_func__", None)for Python 3.14 compatibility__annotate__function (introduced in Python 3.13 by PEP 649) before pickling__annotate__from__annotations__when the class is reconstructed_abc._abc_dataobjects2. Test Coverage (
tests/cloudpickle_test.py)test_abc_with_annotations()test methodValidation
Technical Details
Problem: In Python 3.13+, PEP 649 introduced deferred annotation evaluation using
__annotate__functions. When a class inherits fromabc.ABCand has type annotations, the__annotate__function may have closures referencing the class namespace, which includes the unpicklable_abc._abc_dataobject in_abc_impl.Solution: Remove both
__annotate__and__annotate_func__from the pickled state. Python regenerates them from__annotations__during class reconstruction, so no functionality is lost.Original prompt
abc.ABC) with type annotations #572✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.