Skip to content

Django 5.2 compat - #2

Open
xkludge wants to merge 3 commits into
procurifydevelopment-02132023from
django-5.2-compat
Open

Django 5.2 compat#2
xkludge wants to merge 3 commits into
procurifydevelopment-02132023from
django-5.2-compat

Conversation

@xkludge

@xkludge xkludge commented Jul 29, 2026

Copy link
Copy Markdown

Django 5.2 compatibility: choices backport + CI modernization

Base: procurifydevelopment-02132023 · Head: django-5.2-compat (3 commits)

Why

procurify-monolith is upgrading from Django 4.2 (EOL April 2026) to 5.2 LTS.
Django 5.0 replaced forms.ChoiceField._get_choices/_set_choices with a
plain choices property, so this fork's ChoiceIteratorMixin override raises
on every filter that defines choices:

AttributeError: 'super' object has no attribute '_set_choices'

In the monolith this 500s real endpoints (e.g. /api/v3/locations/, any
ChoiceFilter/MultipleChoiceFilter-backed list view).

This fork exists to retain the pre-23.x range-field suffixes
(3610e9b Retain old suffixes for range field to be backwards compatible),
so we can't simply move to upstream — the fix is backported instead.

On top of that, this fork's CI had been broken/red since the suffix
customization landed: the workflow still targeted Python 3.7 and Django
3.2–4.2 with deprecated actions and a dead tox plugin, and the test suite
itself had never been updated for the suffix change or for Django 5.x test
API renames. The second commit fixes all of that so the fork has a green,
trustworthy matrix covering the Djangos we're migrating between.

Changes

1. Backport Django 5.0+ choices compatibility (5bb368d)

Straight port of upstream django-filter's fix (shipped in 23.5, verified
against the 24.3 tag), applied to django_filters/fields.py:

  • Feature-detect Django 5.0 via
    from django.utils.choices import BaseChoiceIterator, normalize_choices
    (DJANGO_50 flag, same pattern as upstream and as this fork's existing
    utils.py backport).
  • ChoiceIterator subclasses BaseChoiceIterator on 5.0+ and yields
    normalize_choices(...).
  • ChoiceIteratorMixin overrides the choices property (getter +
    setter via super(ChoiceIteratorMixin, self.__class__).choices.__set__,
    the documented workaround for cpython#59170) instead of the removed
    _get_choices/_set_choices pair. The pre-5.0 branch keeps the original
    code path, matching upstream.

2. Modernize CI matrix and fix the test suite (ea41acb)

Workflow (.github/workflows/tests.yml):

  • Matrix is now Python 3.8–3.13 (3.7 dropped — unavailable on current
    ubuntu-latest runners and EOL since June 2023).
  • actions/checkout@v2/setup-python@v2 (retired Node runtimes) bumped to
    @v4/@v5; the codecov-action@v1 publish step removed (dead action,
    and this private fork has no codecov token) — coverage report -m output
    stays in the job log.
  • The unmaintained tox-py plugin replaced with tox 4 native factor
    selection (tox run -f py311).
  • Push trigger fixed from main to master (this repo's default branch),
    so push builds actually run.

tox matrix (tox.ini):

  • Rebuilt around the LTS lines: Django 3.2 (py3.8–3.10), 4.2 (py3.8–3.12),
    and 5.2 (py3.10–3.13), each pinned with ~= for deterministic cells.
  • Dropped EOL non-LTS Django 4.0/4.1 and the latest env that installed
    Django main from GitHub (now 6.x dev, requires Python ≥ 3.12, failed at
    install). The -Werror warnings env now runs against 5.2.
  • Django 3.2 envs pin djangorestframework~=3.14.0 — DRF doesn't constrain
    Django in its package metadata, so pip would otherwise pair 3.2 with the
    latest DRF.

Packaging (setup.py): python_requires>=3.8; classifiers updated to
Python 3.8–3.13 and Django 3.2/4.2/5.2.

Test suite:

  • assertQuerysetEqualassertQuerySetEqual (117 call sites; the old
    spelling was removed in Django 5.1 and produced 84 errors on 5.2), with a
    guarded alias in tests/__init__.py so the new name also works on
    Django 3.2.
  • Range filter/widget tests updated to this fork's intentional _0/_1
    widget suffixes. The tests still assumed upstream's
    _min/_max/_after/_before params, so the filters silently received
    no input and returned unfiltered querysets — 12 tests had been failing on
    every Python/Django combination since 3610e9b.

3. Fix docs tox env: itercompat removal and rtd-theme deprecation (c642f6e)

  • django_filters/filters.py imported django.utils.itercompat.is_iterable,
    which is deprecated in Django 5.1 and removed in 6.0. The docs env installs
    the package with an unpinned Django, got 6.x, and crashed sphinx on import.
    is_iterable is now inlined in django_filters.utils (Django's own
    implementation) — this also silences the 5.1+ deprecation warning for the
    monolith. The docs env is additionally pinned to Django 5.2 so it can't
    drift to an unsupported major again.
  • docs/conf.py dropped the deprecated
    sphinx_rtd_theme.get_html_theme_path() call, which sphinx-build -W
    turns into a hard failure; the theme registers itself with Sphinx
    since 1.0.

Compatibility

  • Django < 5.0: identical code path to today (the old branch is preserved).
  • Django ≥ 5.0: upstream's exact behavior.
  • The procurify range-suffix customization is untouched — and now actually
    covered by the test suite.

Validation

  • Full suite (508 tests) green on py3.8/Django 3.2, py3.11/Django 4.2, and
    py3.13/Django 5.2; flake8 and isort clean.
  • tox envs verified locally end-to-end via the same factor selection CI
    uses (tox run -f py313, -f py310), including per-env pin resolution
    (Django 3.2.25 + DRF 3.14.0 / 4.2.30 / 5.2.16); tox run -e docs
    builds clean, and the package imports cleanly under Django 6.0.
  • Tested from the monolith's Django 5.2 upgrade branch with this rev
    installed: the previously-500ing choice-filter endpoints (locations
    v1/v2/v3, ap item filters) pass their API suites, and the full monolith
    module suite (12,741 tests) is green with this package installed.

🤖 Generated with Claude Code

Django 5.0 replaced ChoiceField._get_choices/_set_choices with a plain
property, so the ChoiceIteratorMixin override raised AttributeError on any
filter with choices. Port of upstream django-filter 23.5/24.3 fix:
ChoiceIterator subclasses BaseChoiceIterator and normalizes choices on 5.0+,
and the mixin overrides the choices property instead of the removed private
pair. Pre-5.0 branches are kept, matching upstream.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5bb368d. Configure here.

Comment thread django_filters/widgets.py
xkludge and others added 2 commits July 30, 2026 16:35
Drop Python 3.7 and EOL Django 4.0/4.1 from the matrix; test Python
3.8-3.13 against the LTS lines (3.2, 4.2, 5.2). Replace the dead tox-py
plugin with tox 4 factor selection, upgrade deprecated GitHub actions,
remove the codecov v1 publish step, and fix the push trigger to match
this repo's master branch. Pin DRF 3.14 for Django 3.2 envs since DRF
does not constrain Django in its metadata.

Test fixes:
- Rename assertQuerysetEqual to assertQuerySetEqual (removed in Django
  5.1), with an alias in tests/__init__.py for Django < 4.2.
- Update range filter/widget tests to the _0/_1 suffixes this fork
  intentionally restored in 3610e9b; the tests still assumed upstream's
  _min/_max/_after/_before and had been failing on every version.

508 tests pass on py3.8/dj3.2, py3.11/dj4.2, and py3.13/dj5.2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The docs env installs the package with an unpinned Django and now gets
6.x, where django.utils.itercompat was removed (deprecated in 5.1), so
importing django_filters from docs/conf.py crashed sphinx. Inline
is_iterable in django_filters.utils (Django's implementation) and stop
importing itercompat — this also silences the 5.1+ deprecation warning
for the monolith. Pin the docs env to Django 5.2 so it can't drift to
an unsupported major again.

Also drop the deprecated sphinx_rtd_theme.get_html_theme_path() call in
docs/conf.py, which sphinx-build -W turns into a hard failure; the
theme registers itself with Sphinx since 1.0.

508 tests still green on Django 3.2 and 5.2; flake8/isort clean; docs
env builds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@xkludge
xkludge changed the base branch from master to procurifydevelopment-02132023 July 31, 2026 13:40
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.

1 participant