Skip to content

support for Django 5.0+ choice override types (dictionaries and calla…#178

Open
JohananOppongAmoateng wants to merge 7 commits intodjango-commons:mainfrom
JohananOppongAmoateng:django-choices-overrides
Open

support for Django 5.0+ choice override types (dictionaries and calla…#178
JohananOppongAmoateng wants to merge 7 commits intodjango-commons:mainfrom
JohananOppongAmoateng:django-choices-overrides

Conversation

@JohananOppongAmoateng
Copy link

@JohananOppongAmoateng JohananOppongAmoateng commented Mar 15, 2026

This PR adds support for Django 5.0+ choice override types (dictionaries and callables) in EnumField

@JohananOppongAmoateng JohananOppongAmoateng marked this pull request as ready for review March 21, 2026 14:58
Copilot AI review requested due to automatic review settings March 21, 2026 14:58
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds compatibility in EnumField (and related form widgets/fields) for Django 5.0+ “choices overrides” that can be provided as dictionaries or callables, while preserving the original override format through deconstruct().

Changes:

  • Add normalize_choices() utility and expose django_version from django_enum.utils.
  • Update EnumField to preserve original choices overrides in deconstruct() and recursively coerce nested/grouped choices in get_choices().
  • Update form widgets/fields to better handle nested/grouped choices and normalize dict/callable choices on Django < 5.0; add a dedicated test module.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
tests/test_django5_overrides.py Adds regression tests for dict/callable/nested/grouped choices overrides and deconstruction behavior.
src/django_enum/utils.py Introduces normalize_choices() and exports django_version for cross-version choices handling.
src/django_enum/forms.py Updates non-strict widget rendering logic and normalizes pre-Django-5 choices inputs.
src/django_enum/fields.py Preserves original override formats in deconstruct() and improves recursive coercion of complex choices.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +139 to +141
raw_choices = zip(get_set_values(value), get_set_bits(value))
self.choices = list(self.choices)
choice_values = set(choice[0] for choice in self.choices)
for value, label in raw_choices:
if value not in choice_values:
self.choices.append((value, label))
return super().render(*args, **kwargs) # type: ignore[misc]

Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NonStrictFlagMixin.render() converts self.choices with list(self.choices). If self.choices is a dict (allowed on Django 5+), this becomes a list of keys, which will break the subsequent (choice, label) unpacking in _get_values() and also makes the later isinstance(self.choices, dict) branch unreachable. Consider preserving the original dict (or converting dicts via .items()) before iterating/unpacking so dict-based choices work correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +113
with pytest.raises(Exception): # Django raises ValidationError
field.validate(3, None)
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test expects a ValidationError, but it currently uses pytest.raises(Exception), which can mask unrelated errors and make failures harder to diagnose. Prefer asserting the specific django.core.exceptions.ValidationError (as other tests in this suite do).

Copilot uses AI. Check for mistakes.
from django.db import models
from django_enum import EnumField
from django.db.models import IntegerChoices
from django import VERSION as django_version
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

django_version is imported but never used in this test module. Either remove the import, or use it (e.g., for a module-level skip/conditional assertions) to avoid dead code.

Suggested change
from django import VERSION as django_version

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Mar 21, 2026

Codecov Report

❌ Patch coverage is 62.82051% with 29 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/django_enum/forms.py 50.00% 18 Missing and 7 partials ⚠️
src/django_enum/fields.py 80.95% 2 Missing and 2 partials ⚠️
Files with missing lines Coverage Δ
src/django_enum/utils.py 100.00% <100.00%> (ø)
src/django_enum/fields.py 99.22% <80.95%> (-0.78%) ⬇️
src/django_enum/forms.py 88.09% <50.00%> (-11.91%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants