Skip to content

Calling "django.setup()" before the test collection #135

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

Closed
magopian opened this issue Jul 25, 2014 · 4 comments
Closed

Calling "django.setup()" before the test collection #135

magopian opened this issue Jul 25, 2014 · 4 comments

Comments

@magopian
Copy link
Contributor

I don't know the rationale for now calling django.setup() before the test collection (cf #119 (comment)), but what I know is that it's causing an issue in a corner case implying lazy translations in a modelForm field choice list, because of the new feature allowing one to customiz the empty choice.

Here's how to reproduce:
1/ Create an app with the following models.py:

from django import forms
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Foo(models.Model):
    choice = models.CharField(max_length=200, choices=(
        (_('Audio'), (('vinyl', 'Vinyl'), ('cd', 'CD'))),
        (_('Video'), (('vhs', 'VHS Tape'), ('dvd', 'DVD'))),
    ))


class MyForm(forms.ModelForm):

    class Meta:
        fields = ['choice']
        model = Foo

2/ Now create a simple test file that imports this, eg from foo.models import MyForm
3/ Here's the result:

tests/test_models.py:1: in <module>
    from foo.models import MyForm
foo/models.py:14: in <module>
    class MyForm(forms.ModelForm):
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/forms/models.py:283: in __new__
    opts.help_texts, opts.error_messages)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/forms/models.py:210: in fields_for_model
    formfield = f.formfield(**kwargs)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py:1059: in formfield
    return super(CharField, self).formfield(**defaults)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py:818: in formfield
    defaults['choices'] = self.get_choices(include_blank=include_blank)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py:732: in get_choices
    if choice in ('', None):
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/functional.py:169: in __eq__
    return self.__cast() == other
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/functional.py:157: in __cast
    return self.__text_cast()
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/functional.py:148: in __text_cast
    return func(*self.__args, **self.__kw)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/translation/__init__.py:83: in ugettext
    return _trans.ugettext(message)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py:319: in ugettext
    return do_translate(message, 'ugettext')
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py:300: in do_translate
    _default = translation(settings.LANGUAGE_CODE)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py:210: in translation
    _translations[language] = DjangoTranslation(language)
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py:120: in __init__
    self._add_installed_apps_translations()
../../.virtualenvs/bugmig/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py:166: in _add_installed_apps_translations
    "The translation infrastructure cannot be initialized before the "
E   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.

This is a special case that only happens because we have translated named groups.

From my investigations, here's what happening:
When building the model form, it goes through the choice list to see if we've customized the empty choice: https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L732

To compare the choice with '' or None, we must first translate it for real (and thus "unlazy" the translation). Then, at the end, we try to merge all the translations together, and thus need to access the app configs (https://github.com/django/django/blob/master/django/utils/translation/trans_real.py#L163).

As we haven't run Django's setup yet (we're still in the test collection phase), the app-loading hasn't even started, and thus the failure.

I can obviously fix this issue by doing the setup myself in my conftest file, but I'm wondering if this should (could?) be fixed at pytest_django's level?

@pelme
Copy link
Member

pelme commented Jul 25, 2014

Hmm, the point of lazy translations is to defer the actual translation to a later point (typically when a view runs, when the language has been determined).

Apart from peeking into app registry, the traceback shows accessing settings.LANGUAGE_CODE, which does not look quite right.

Therefore I think that this looks like a bug in Django form initialization. The translation (and therefore the app registry) should be delayed to form construction/rendering time.

@magopian
Copy link
Contributor Author

I understand (and kind of agree) to what you're saying, however... we're only trying to check if the translation is '' or None.

Actually, thinking of it, I can see two issues here:
1/ why would we translate the empty string?
2/ if it's contributing those "too early" translations to the apps translations... that's a real bug.

I'm going to close this one, and open a ticket on Django. Thanks for your analysis ;)

@blueyed
Copy link
Contributor

blueyed commented Jul 25, 2014

For reference, the issue in Django's tracker is: https://code.djangoproject.com/ticket/23098

@sreedharbukya
Copy link

I am also getting same as fallows .. after upgrading django 1.7 -- How to resolve the issue.

I already did changed wsgi file

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.common")

This application object is used by any WSGI server configured to use this

file. This includes Django's development server, if the WSGI_APPLICATION

setting points here.

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

#===========================================================================

error on termial

#============================================================================
Traceback (most recent call last):
File "manage.py", line 27, in
execute_from_command_line(sys.argv)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/core/management/init.py", line 385, in execute_from_command_line
utility.execute()
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/core/management/init.py", line 354, in execute
django.setup()
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/init.py", line 21, in setup
apps.populate(settings.INSTALLED_APPS)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate
app_config = AppConfig.create(entry)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/apps/config.py", line 87, in create
module = import_module(entry)
File "/usr/lib64/python2.7/importlib/init.py", line 37, in import_module
import(name)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/mezzanine/conf/init.py", line 197, in
import_module("%s.defaults" % app)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/importlib.py", line 46, in import_module
import(name)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/mezzanine/accounts/defaults.py", line 83, in
default="",
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/mezzanine/conf/init.py", line 47, in register_setting
if not label:
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/functional.py", line 132, in wrapper
res = func(_self.__args, *_self.kw)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/translation/__init
.py", line 83, in ugettext
return _trans.ugettext(message)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 325, in ugettext
return do_translate(message, 'ugettext')
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 306, in do_translate
_default = translation(settings.LANGUAGE_CODE)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 209, in translation
default_translation = _fetch(settings.LANGUAGE_CODE)
File "/home/sbukya/projects/virtu/local/lib/python2.7/site-packages/django/utils/translation/trans_real.py", line 189, in _fetch
"The translation infrastructure cannot be initialized before the "
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.

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

No branches or pull requests

4 participants