Fix compatibility issues with django-modeltranslation#649
Fix compatibility issues with django-modeltranslation#649Hopiu wants to merge 2 commits intojazzband:masterfrom
Conversation
…nager mixins - Added a new class `_GenericMixin` to serve as a runtime placeholder for `Generic[ModelT]`. This change prevents `TypeError` during `__class__` assignments, which was an issue when mixins inherited from `Generic[T]` at runtime. - All manager mixins have been updated to inherit from `_GenericMixin` instead of `Generic[ModelT]`. This ensures compatibility with `django-modeltranslation`. - Introduced regressions tests to confirm that the manager instances support `__class__` reassignment without issues. Tests were added for `SoftDeletableManager`, `InheritanceManager`, `QueryManager`, and `JoinManager`. Closes GH-jazzband#636.
There was a problem hiding this comment.
Pull request overview
This PR fixes compatibility issues between django-model-utils and django-modeltranslation by addressing a Python runtime limitation with __class__ assignment when Generic[T] is in the class hierarchy. The fix moves Generic[ModelT] inheritance behind TYPE_CHECKING so it's only present during static type analysis, while using a runtime placeholder class _GenericMixin that supports subscripting but avoids layout incompatibility issues.
- Introduces a
_GenericMixinclass that replacesGeneric[ModelT]at runtime while maintaining type-checking support - Updates all manager mixin classes to inherit from
_GenericMixininstead ofGeneric[ModelT] - Adds comprehensive tests to verify
__class__reassignment works correctly for all affected managers
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| model_utils/managers.py | Implements the _GenericMixin pattern and updates all mixin classes (InheritanceQuerySetMixin, InheritanceManagerMixin, QueryManagerMixin, SoftDeletableQuerySetMixin, SoftDeletableManagerMixin) to use it |
| tests/test_managers/test_manager_class_assignment.py | Adds regression tests that verify __class__ assignment works for SoftDeletableManager, InheritanceManager, QueryManager, and JoinManager |
| CHANGES.rst | Documents the fix with reference to issue #636 |
| AUTHORS.rst | Adds contributor credit for Benedikt Willi |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - Fix compatibility with django-modeltranslation: manager mixins no longer | ||
| inherit from `Generic[T]` at runtime, preventing `TypeError` on `__class__` | ||
| assignment (GH-#636) |
There was a problem hiding this comment.
The formatting of the issue reference is inconsistent with other entries in this file. Other entries use the format (GH-#636) at the end of the line, but this entry spans multiple lines with the reference at the end. Consider reformatting to match the style of other entries, such as placing it all on one line or breaking it differently to maintain consistency.
| - Fix compatibility with django-modeltranslation: manager mixins no longer | |
| inherit from `Generic[T]` at runtime, preventing `TypeError` on `__class__` | |
| assignment (GH-#636) | |
| - Fix compatibility with django-modeltranslation: manager mixins no longer inherit from `Generic[T]` at runtime, preventing `TypeError` on `__class__` assignment (GH-#636) |
Problem
When using
django-model-utilstogether withdjango-modeltranslation, registering a model that usesSoftDeletableModel(or other models using manager mixins) causes a TypeError during app initialization:This occurs because
django-modeltranslationpatches manager classes by reassigningmanager.__class__to a dynamically created subclass. Python's__class__assignment has strict layout compatibility requirements, and theGeneric[ModelT]base class in our manager mixins causes a layout mismatch.Fixes #636
Solution
Move the
Generic[ModelT]inheritance behindTYPE_CHECKINGso it's only present during static type analysis, not at runtime. At runtime, a simple placeholder class_GenericMixinis used instead.Commandments
CHANGES.rstfile to describe the changes, and quote according issue withGH-<issue_number>.