Skip to content
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

Fixes for Django 5.0. #1606

Closed
wants to merge 3 commits into from
Closed

Fixes for Django 5.0. #1606

wants to merge 3 commits into from

Conversation

carltongibson
Copy link
Owner

@carltongibson carltongibson commented Aug 31, 2023

Refs #1605.

b035bf2 is needed to surface the ChoiceIterator issue, otherwise we hit apps not loaded setting up the test run.

Found 77 test(s).
Creating test database for alias 'default'...
Traceback (most recent call last):
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/base.py", line 106, in wrapper
    res = handle_func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/commands/migrate.py", line 107, in handle
    for app_config in apps.get_app_configs():
                      ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/apps/registry.py", line 147, in get_app_configs
    self.check_apps_ready()
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/apps/registry.py", line 138, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/utils/translation/trans_real.py", line 215, in _add_installed_apps_translations
    app_configs = reversed(apps.get_app_configs())
                           ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/apps/registry.py", line 147, in get_app_configs
    self.check_apps_ready()
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/apps/registry.py", line 138, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/carlton/Projects/Django/django-filter/runtests.py", line 15, in <module>
    runtests()
  File "/Users/carlton/Projects/Django/django-filter/runtests.py", line 11, in runtests
    execute_from_command_line(argv)
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/commands/test.py", line 24, in run_from_argv
    super().run_from_argv(argv)
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/commands/test.py", line 68, in handle
    failures = test_runner.run_tests(test_labels)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/test/runner.py", line 1056, in run_tests
    old_config = self.setup_databases(
                 ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/test/runner.py", line 955, in setup_databases
    return _setup_databases(
           ^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/test/utils.py", line 203, in setup_databases
    connection.creation.create_test_db(
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/db/backends/base/creation.py", line 78, in create_test_db
    call_command(
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/__init__.py", line 194, in call_command
    return command.execute(*args, **defaults)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/core/management/base.py", line 109, in wrapper
    translation.activate(saved_locale)
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/utils/translation/__init__.py", line 181, in activate
    return _trans.activate(language)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/utils/translation/trans_real.py", line 303, in activate
    _active.value = translation(language)
                    ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/utils/translation/trans_real.py", line 292, in translation
    _translations[language] = DjangoTranslation(language)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/utils/translation/trans_real.py", line 169, in __init__
    self._add_installed_apps_translations()
  File "/Users/carlton/Projects/Django/django-filter/.tox/py311-latest/lib/python3.11/site-packages/django/utils/translation/trans_real.py", line 217, in _add_installed_apps_translations
    raise AppRegistryNotReady(
django.core.exceptions.AppRegistryNotReady: The translation infrastructure cannot be initialized before the apps registry is ready. Check that you don't make non-lazy gettext calls at import time.
py311-latest: exit 1 (0.35 seconds) /Users/carlton/Projects/Django/django-filter> coverage run --parallel-mode --source django_filters ./runtests.py --testrunner xmlrunner.extra.djangotestrunner.XMLTestRunner pid=84393

(@felixxm don't suppose you know when this snuck in do you? Ta! 😊)

@codecov-commenter
Copy link

codecov-commenter commented Aug 31, 2023

Codecov Report

Merging #1606 (f279fb7) into main (e5fc05d) will increase coverage by 0.01%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #1606      +/-   ##
==========================================
+ Coverage   98.58%   98.59%   +0.01%     
==========================================
  Files          15       15              
  Lines        1271     1285      +14     
==========================================
+ Hits         1253     1267      +14     
  Misses         18       18              
Files Changed Coverage Δ
django_filters/fields.py 100.00% <100.00%> (ø)

@carltongibson
Copy link
Owner Author

Hey @ngnpope 👋 Don't suppose I could ask for your opinion here could I please? 🎁

@carltongibson
Copy link
Owner Author

carltongibson commented Sep 1, 2023

b035bf2 is needed to surface the ChoiceIterator issue, otherwise we hit apps not loaded setting up the test run.

This only comes up in tox. (Grrr.) Calling django.setup() is unobjectionable, and probably should have always been there… 🤔, so unless someone wants to input I'm just going to leave it.

@ngnpope
Copy link
Contributor

ngnpope commented Sep 1, 2023

Hey @ngnpope 👋 Don't suppose I could ask for your opinion here could I please? 🎁

Will take a look... 👀

from django.core.management import execute_from_command_line


def runtests():
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.settings")
django.setup()
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this was due to a deep circular import issue that didn't flag up when running Django's test suite.

See django/django#17215 for where this was fixed.

Comment on lines +20 to +27
# Compat for Django >= 5.0
try:
from django.utils.choices import normalize_choices
except ImportError:
normalize_choices = None

DJANGO_50 = normalize_choices is not None

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this could be simplified:

Suggested change
# Compat for Django >= 5.0
try:
from django.utils.choices import normalize_choices
except ImportError:
normalize_choices = None
DJANGO_50 = normalize_choices is not None
try:
from django.utils.choices import normalize_choices
except ImportError:
DJANGO_50 = False
else:
DJANGO_50 = True

@forms.ChoiceField.choices.setter
def choices(self, value):
self._choices = self.widget.choices = self.iterator(
self, normalize_choices(value)
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a few interesting things here:

  1. Ideally we'd not rehash the Django internals here, i.e. self._choices = self.widget.choices = ...
  2. For equivalent behaviour as in Django 5.0 it ought to be ... = normalize_choices(self.iterator(...))
  3. To make the normalization lazy, ChoiceIterator should extend django.utils.choices.ChoiceIterator
    • Maybe I should have called that django.utils.choices.BaseChoiceIterator? 🤔
  4. We should push the normalize_choices() call into ChoiceIterator.__iter__()
  5. It's a shame that we have to implement this twice rather than once in the mixin

I think all of this can be solved. Will open an alternate PR soon...

@ngnpope
Copy link
Contributor

ngnpope commented Sep 1, 2023

See #1607 for an alternative 🙂

@carltongibson
Copy link
Owner Author

Thanks @ngnpope 🦸‍♀️ Looks good. I'll give it a proper read over the weekend. 🎁

@carltongibson
Copy link
Owner Author

Closing in favour of #1607

@carltongibson carltongibson deleted the fixes-for-django-5.0 branch September 4, 2023 09:03
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.

Choice iterator breakage against Django pre-5.0
3 participants