Fixed #25746 -- Isolated inlined test models registration.

Thanks to Tim for the review.
This commit is contained in:
Simon Charette 2015-11-17 00:39:28 -05:00
parent 3096f4b082
commit a08fda2111
29 changed files with 285 additions and 371 deletions

View File

@ -6,10 +6,22 @@ from django.conf import settings
from django.core import checks
def check_user_model(**kwargs):
errors = []
def check_user_model(app_configs=None, **kwargs):
if app_configs is None:
cls = apps.get_model(settings.AUTH_USER_MODEL)
else:
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
for app_config in app_configs:
if app_config.label == app_label:
cls = app_config.get_model(model_name)
break
else:
# Checks might be run against a set of app configs that don't
# include the specified user model. In this case we simply don't
# perform the checks defined below.
return []
cls = apps.get_model(settings.AUTH_USER_MODEL)
errors = []
# Check that REQUIRED_FIELDS is a list
if not isinstance(cls.REQUIRED_FIELDS, (list, tuple)):

View File

@ -1,17 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from itertools import chain
from django.apps import apps
from django.utils import six
def check_generic_foreign_keys(**kwargs):
def check_generic_foreign_keys(app_configs=None, **kwargs):
from .fields import GenericForeignKey
if app_configs is None:
models = apps.get_models()
else:
models = chain.from_iterable(app_config.get_models() for app_config in app_configs)
errors = []
fields = (obj
for cls in apps.get_models()
for obj in six.itervalues(vars(cls))
for model in models
for obj in six.itervalues(vars(model))
if isinstance(obj, GenericForeignKey))
for field in fields:
errors.extend(field.check())

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
import inspect
import types
from itertools import chain
from django.apps import apps
from django.core.checks import Error, Tags, register
@ -11,21 +12,24 @@ from django.core.checks import Error, Tags, register
@register(Tags.models)
def check_all_models(app_configs=None, **kwargs):
errors = []
for model in apps.get_models():
if app_configs is None or model._meta.app_config in app_configs:
if not inspect.ismethod(model.check):
errors.append(
Error(
"The '%s.check()' class method is "
"currently overridden by %r." % (
model.__name__, model.check),
hint=None,
obj=model,
id='models.E020'
)
if app_configs is None:
models = apps.get_models()
else:
models = chain.from_iterable(app_config.get_models() for app_config in app_configs)
for model in models:
if not inspect.ismethod(model.check):
errors.append(
Error(
"The '%s.check()' class method is "
"currently overridden by %r." % (
model.__name__, model.check),
hint=None,
obj=model,
id='models.E020'
)
else:
errors.extend(model.check(**kwargs))
)
else:
errors.extend(model.check(**kwargs))
return errors

View File

@ -1,7 +1,9 @@
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
@isolate_apps('absolute_url_overrides')
class AbsoluteUrlOverrideTests(SimpleTestCase):
def test_get_absolute_url(self):

View File

@ -9,7 +9,7 @@ from django.contrib.admin.models import LogEntry
from django.core.exceptions import AppRegistryNotReady, ImproperlyConfigured
from django.db import models
from django.test import SimpleTestCase, override_settings
from django.test.utils import extend_sys_path
from django.test.utils import extend_sys_path, isolate_apps
from django.utils import six
from django.utils._os import upath
@ -260,7 +260,8 @@ class AppsTests(SimpleTestCase):
finally:
apps.apps_ready = True
def test_lazy_model_operation(self):
@isolate_apps('apps', kwarg_name='apps')
def test_lazy_model_operation(self, apps):
"""
Tests apps.lazy_model_operation().
"""

View File

@ -1,14 +1,10 @@
from .custom_permissions import CustomPermissionsUser
from .invalid_models import (
CustomUserBadRequiredFields, CustomUserNonListRequiredFields,
CustomUserNonUniqueUsername,
)
from .invalid_models import CustomUserNonUniqueUsername
from .is_active import IsActiveTestUser1
from .uuid_pk import UUIDUser
from .with_foreign_key import CustomUserWithFK, Email
__all__ = (
'CustomPermissionsUser', 'CustomUserNonUniqueUsername',
'CustomUserNonListRequiredFields', 'CustomUserBadRequiredFields',
'CustomUserWithFK', 'Email', 'IsActiveTestUser1', 'UUIDUser',
'CustomPermissionsUser', 'CustomUserWithFK', 'Email',
'IsActiveTestUser1', 'UUIDUser', 'CustomUserNonUniqueUsername',
)

View File

@ -18,21 +18,3 @@ class CustomUserNonUniqueUsername(AbstractBaseUser):
REQUIRED_FIELDS = ['email']
objects = UserManager()
class CustomUserNonListRequiredFields(AbstractBaseUser):
"A user with a non-list REQUIRED_FIELDS"
username = models.CharField(max_length=30, unique=True)
date_of_birth = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = 'date_of_birth'
class CustomUserBadRequiredFields(AbstractBaseUser):
"A user with a USERNAME_FIELD that appears in REQUIRED_FIELDS (invalid)"
username = models.CharField(max_length=30, unique=True)
date_of_birth = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['username', 'date_of_birth']

View File

@ -11,23 +11,24 @@ from django.contrib.auth.management import create_permissions
from django.contrib.auth.management.commands import (
changepassword, createsuperuser,
)
from django.contrib.auth.models import Group, Permission, User
from django.contrib.auth.models import (
AbstractBaseUser, Group, Permission, User,
)
from django.contrib.auth.tests.custom_user import CustomUser
from django.contrib.contenttypes.models import ContentType
from django.core import checks, exceptions
from django.core.management import call_command
from django.core.management.base import CommandError
from django.db import models
from django.test import (
SimpleTestCase, TestCase, override_settings, override_system_checks,
)
from django.test.utils import isolate_apps
from django.utils import six
from django.utils.encoding import force_str
from django.utils.translation import ugettext_lazy as _
from .models import (
CustomUserBadRequiredFields, CustomUserNonListRequiredFields,
CustomUserNonUniqueUsername, CustomUserWithFK, Email,
)
from .models import CustomUserNonUniqueUsername, CustomUserWithFK, Email
def mock_inputs(inputs):
@ -568,9 +569,17 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
class CustomUserModelValidationTestCase(SimpleTestCase):
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserNonListRequiredFields')
@override_system_checks([check_user_model])
def test_required_fields_is_list(self):
"REQUIRED_FIELDS should be a list."
errors = checks.run_checks()
@isolate_apps('auth_tests', kwarg_name='apps')
def test_required_fields_is_list(self, apps):
"""REQUIRED_FIELDS should be a list."""
class CustomUserNonListRequiredFields(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
date_of_birth = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = 'date_of_birth'
errors = checks.run_checks(app_configs=apps.get_app_configs())
expected = [
checks.Error(
"'REQUIRED_FIELDS' must be a list or tuple.",
@ -583,9 +592,17 @@ class CustomUserModelValidationTestCase(SimpleTestCase):
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserBadRequiredFields')
@override_system_checks([check_user_model])
def test_username_not_in_required_fields(self):
"USERNAME_FIELD should not appear in REQUIRED_FIELDS."
errors = checks.run_checks()
@isolate_apps('auth_tests', kwarg_name='apps')
def test_username_not_in_required_fields(self, apps):
"""USERNAME_FIELD should not appear in REQUIRED_FIELDS."""
class CustomUserBadRequiredFields(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
date_of_birth = models.DateField()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['username', 'date_of_birth']
errors = checks.run_checks(apps.get_app_configs())
expected = [
checks.Error(
("The field named as the 'USERNAME_FIELD' for a custom user model "
@ -600,7 +617,10 @@ class CustomUserModelValidationTestCase(SimpleTestCase):
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserNonUniqueUsername')
@override_system_checks([check_user_model])
def test_username_non_unique(self):
"A non-unique USERNAME_FIELD should raise a model validation error."
"""
A non-unique USERNAME_FIELD should raise an error only if we use the
default authentication backend. Otherwise, an warning should be raised.
"""
errors = checks.run_checks()
expected = [
checks.Error(
@ -612,28 +632,19 @@ class CustomUserModelValidationTestCase(SimpleTestCase):
),
]
self.assertEqual(errors, expected)
@override_settings(AUTH_USER_MODEL='auth_tests.CustomUserNonUniqueUsername',
AUTHENTICATION_BACKENDS=[
'my.custom.backend',
])
@override_system_checks([check_user_model])
def test_username_non_unique_with_custom_backend(self):
""" A non-unique USERNAME_FIELD should raise an error only if we use the
default authentication backend. Otherwise, an warning should be raised.
"""
errors = checks.run_checks()
expected = [
checks.Warning(
("'CustomUserNonUniqueUsername.username' is named as "
"the 'USERNAME_FIELD', but it is not unique."),
hint=('Ensure that your authentication backend(s) can handle '
'non-unique usernames.'),
obj=CustomUserNonUniqueUsername,
id='auth.W004',
)
]
self.assertEqual(errors, expected)
with self.settings(AUTHENTICATION_BACKENDS=['my.custom.backend']):
errors = checks.run_checks()
expected = [
checks.Warning(
("'CustomUserNonUniqueUsername.username' is named as "
"the 'USERNAME_FIELD', but it is not unique."),
hint=('Ensure that your authentication backend(s) can handle '
'non-unique usernames.'),
obj=CustomUserNonUniqueUsername,
id='auth.W004',
)
]
self.assertEqual(errors, expected)
class PermissionTestCase(TestCase):

View File

@ -1,11 +1,11 @@
from django.core import checks
from django.db import models
from django.test import SimpleTestCase
from .tests import IsolateModelsMixin
from django.test.utils import isolate_apps
class TestDeprecatedField(IsolateModelsMixin, SimpleTestCase):
@isolate_apps('check_framework')
class TestDeprecatedField(SimpleTestCase):
def test_default_details(self):
class MyField(models.Field):
system_check_deprecated_details = {}
@ -45,7 +45,8 @@ class TestDeprecatedField(IsolateModelsMixin, SimpleTestCase):
])
class TestRemovedField(IsolateModelsMixin, SimpleTestCase):
@isolate_apps('check_framework')
class TestRemovedField(SimpleTestCase):
def test_default_details(self):
class MyField(models.Field):
system_check_removed_details = {}

View File

@ -1,8 +1,6 @@
from django.db import connections, models
from django.test import TestCase, mock
from django.test.utils import override_settings
from .tests import IsolateModelsMixin
from django.test.utils import isolate_apps, override_settings
class TestRouter(object):
@ -14,7 +12,8 @@ class TestRouter(object):
@override_settings(DATABASE_ROUTERS=[TestRouter()])
class TestMultiDBChecks(IsolateModelsMixin, TestCase):
@isolate_apps('check_framework')
class TestMultiDBChecks(TestCase):
multi_db = True
def _patch_check_field_on(self, db):

View File

@ -11,7 +11,9 @@ from django.core.management import call_command
from django.core.management.base import CommandError
from django.db import models
from django.test import SimpleTestCase
from django.test.utils import override_settings, override_system_checks
from django.test.utils import (
isolate_apps, override_settings, override_system_checks,
)
from django.utils.encoding import force_text
from django.utils.six import StringIO
@ -254,23 +256,10 @@ class SilencingCheckTests(SimpleTestCase):
self.assertEqual(err.getvalue(), '')
class IsolateModelsMixin(object):
def setUp(self):
self.current_models = apps.all_models[__package__]
self.saved_models = set(self.current_models)
def tearDown(self):
for model in (set(self.current_models) - self.saved_models):
del self.current_models[model]
apps.clear_cache()
class CheckFrameworkReservedNamesTests(IsolateModelsMixin, SimpleTestCase):
@override_settings(
SILENCED_SYSTEM_CHECKS=['models.E20', 'fields.W342'], # ForeignKey(unique=True)
INSTALLED_APPS=['django.contrib.auth', 'django.contrib.contenttypes', 'check_framework']
)
def test_model_check_method_not_shadowed(self):
class CheckFrameworkReservedNamesTests(SimpleTestCase):
@isolate_apps('check_framework', kwarg_name='apps')
@override_system_checks([checks.model_checks.check_all_models])
def test_model_check_method_not_shadowed(self, apps):
class ModelWithAttributeCalledCheck(models.Model):
check = 42
@ -288,7 +277,7 @@ class CheckFrameworkReservedNamesTests(IsolateModelsMixin, SimpleTestCase):
related_name='check',
)
errors = checks.run_checks()
errors = checks.run_checks(app_configs=apps.get_app_configs())
expected = [
Error(
"The 'ModelWithAttributeCalledCheck.check()' class method is "

View File

@ -12,8 +12,8 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.core import checks
from django.db import connections, models
from django.test import TestCase, override_settings
from django.test.utils import captured_stdout
from django.test import SimpleTestCase, TestCase, override_settings
from django.test.utils import captured_stdout, isolate_apps
from django.utils.encoding import force_str, force_text
from .models import Article, Author, SchemeIncludedURL
@ -114,20 +114,9 @@ class ContentTypesViewsTests(TestCase):
self.assertEqual(force_text(ct), 'modelcreatedonthefly')
class IsolatedModelsTestCase(TestCase):
def setUp(self):
# The unmanaged models need to be removed after the test in order to
# prevent bad interactions with the flush operation in other tests.
self._old_models = apps.app_configs['contenttypes_tests'].models.copy()
def tearDown(self):
apps.app_configs['contenttypes_tests'].models = self._old_models
apps.all_models['contenttypes_tests'] = self._old_models
apps.clear_cache()
@override_settings(SILENCED_SYSTEM_CHECKS=['fields.W342']) # ForeignKey(unique=True)
class GenericForeignKeyTests(IsolatedModelsTestCase):
@isolate_apps('contenttypes_tests', attr_name='apps')
class GenericForeignKeyTests(SimpleTestCase):
def test_str(self):
class Model(models.Model):
@ -239,11 +228,12 @@ class GenericForeignKeyTests(IsolatedModelsTestCase):
class Model(models.Model):
content_object = MyGenericForeignKey()
errors = checks.run_checks()
errors = checks.run_checks(app_configs=self.apps.get_app_configs())
self.assertEqual(errors, ['performed!'])
class GenericRelationshipTests(IsolatedModelsTestCase):
@isolate_apps('contenttypes_tests')
class GenericRelationshipTests(SimpleTestCase):
def test_valid_generic_relationship(self):
class TaggedItem(models.Model):

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
from operator import attrgetter
from django.apps import apps
from django.apps.registry import Apps
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.backends.db import SessionStore
from django.db import models
@ -12,6 +11,7 @@ from django.db.models.query_utils import (
DeferredAttribute, deferred_class_factory,
)
from django.test import TestCase, override_settings
from django.test.utils import isolate_apps
from .models import (
Base, Child, Derived, Feature, Item, ItemAndSimpleItem, Leaf, Location,
@ -265,22 +265,20 @@ class DeferRegressionTest(TestCase):
deferred_cls = deferred_class_factory(Item, ())
self.assertFalse(deferred_cls._deferred)
def test_deferred_class_factory_apps_reuse(self):
@isolate_apps('defer_regress', kwarg_name='apps')
def test_deferred_class_factory_apps_reuse(self, apps):
"""
#25563 - model._meta.apps should be used for caching and
retrieval of the created proxy class.
"""
isolated_apps = Apps(['defer_regress'])
class BaseModel(models.Model):
field = models.BooleanField()
class Meta:
apps = isolated_apps
app_label = 'defer_regress'
deferred_model = deferred_class_factory(BaseModel, ['field'])
self.assertIs(deferred_model._meta.apps, isolated_apps)
self.assertIs(deferred_model._meta.apps, apps)
self.assertIs(deferred_class_factory(BaseModel, ['field']), deferred_model)

View File

@ -1,11 +1,11 @@
import datetime
from operator import attrgetter
from django.apps.registry import Apps
from django.core.exceptions import FieldError
from django.db import models
from django.db.models.fields.related import ForeignObject
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
from django.test.utils import isolate_apps
from django.utils import translation
from .models import (
@ -410,15 +410,13 @@ class MultiColumnFKTests(TestCase):
class TestModelCheckTests(SimpleTestCase):
@isolate_apps('foreign_object')
def test_check_composite_foreign_object(self):
test_apps = Apps(['foreign_object'])
class Parent(models.Model):
a = models.PositiveIntegerField()
b = models.PositiveIntegerField()
class Meta:
apps = test_apps
unique_together = (('a', 'b'),)
class Child(models.Model):
@ -433,21 +431,16 @@ class TestModelCheckTests(SimpleTestCase):
related_name='children',
)
class Meta:
apps = test_apps
self.assertEqual(Child._meta.get_field('parent').check(from_model=Child), [])
@isolate_apps('foreign_object')
def test_check_subset_composite_foreign_object(self):
test_apps = Apps(['foreign_object'])
class Parent(models.Model):
a = models.PositiveIntegerField()
b = models.PositiveIntegerField()
c = models.PositiveIntegerField()
class Meta:
apps = test_apps
unique_together = (('a', 'b'),)
class Child(models.Model):
@ -463,7 +456,4 @@ class TestModelCheckTests(SimpleTestCase):
related_name='children',
)
class Meta:
apps = test_apps
self.assertEqual(Child._meta.get_field('parent').check(from_model=Child), [])

View File

@ -1,18 +0,0 @@
# -*- encoding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import apps
from django.test import SimpleTestCase
class IsolatedModelsTestCase(SimpleTestCase):
def setUp(self):
# The unmanaged models need to be removed after the test in order to
# prevent bad interactions with the flush operation in other tests.
self._old_models = apps.app_configs['invalid_models_tests'].models.copy()
def tearDown(self):
apps.app_configs['invalid_models_tests'].models = self._old_models
apps.all_models['invalid_models_tests'] = self._old_models
apps.clear_cache()

View File

@ -3,9 +3,8 @@ from __future__ import unicode_literals
from django.core.checks import Error
from django.db import connections, models
from django.test import mock
from .base import IsolatedModelsTestCase
from django.test import SimpleTestCase, mock
from django.test.utils import isolate_apps
def dummy_allow_migrate(db, app_label, **hints):
@ -14,7 +13,8 @@ def dummy_allow_migrate(db, app_label, **hints):
return db == 'default'
class BackendSpecificChecksTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class BackendSpecificChecksTests(SimpleTestCase):
@mock.patch('django.db.models.fields.router.allow_migrate', new=dummy_allow_migrate)
def test_check_field(self):

View File

@ -1,9 +1,10 @@
from django.db import models
from .base import IsolatedModelsTestCase
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class CustomFieldTest(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class CustomFieldTest(SimpleTestCase):
def test_none_column(self):
class NoColumnField(models.AutoField):

View File

@ -1,10 +1,11 @@
from django.core import checks
from django.db import models
from .base import IsolatedModelsTestCase
from django.test import SimpleTestCase
from django.test.utils import isolate_apps
class DeprecatedFieldsTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class DeprecatedFieldsTests(SimpleTestCase):
def test_IPAddressField_deprecated(self):
class IPAddressModel(models.Model):
ip = models.IPAddressField()

View File

@ -6,9 +6,8 @@ import unittest
from django.conf import settings
from django.core.checks import Error
from django.db import connections, models
from django.test.utils import override_settings
from .base import IsolatedModelsTestCase
from django.test import SimpleTestCase
from django.test.utils import isolate_apps, override_settings
def get_max_column_name_length():
@ -31,7 +30,8 @@ def get_max_column_name_length():
return (allowed_len, db_alias)
class IndexTogetherTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class IndexTogetherTests(SimpleTestCase):
def test_non_iterable(self):
class Model(models.Model):
@ -146,7 +146,8 @@ class IndexTogetherTests(IsolatedModelsTestCase):
# unique_together tests are very similar to index_together tests.
class UniqueTogetherTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class UniqueTogetherTests(SimpleTestCase):
def test_non_iterable(self):
class Model(models.Model):
@ -251,7 +252,8 @@ class UniqueTogetherTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class FieldNamesTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class FieldNamesTests(SimpleTestCase):
def test_ending_with_underscore(self):
class Model(models.Model):
@ -434,7 +436,8 @@ class FieldNamesTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class ShadowingFieldsTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class ShadowingFieldsTests(SimpleTestCase):
def test_field_name_clash_with_child_accessor(self):
class Parent(models.Model):
@ -558,7 +561,8 @@ class ShadowingFieldsTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class OtherModelTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class OtherModelTests(SimpleTestCase):
def test_unique_primary_key(self):
invalid_id = models.IntegerField(primary_key=False)

View File

@ -5,14 +5,13 @@ import unittest
from django.core.checks import Error, Warning as DjangoWarning
from django.db import connection, models
from django.test import TestCase
from django.test.utils import override_settings
from django.test import SimpleTestCase, TestCase
from django.test.utils import isolate_apps, override_settings
from django.utils.timezone import now
from .base import IsolatedModelsTestCase
class AutoFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class AutoFieldTests(SimpleTestCase):
def test_valid_case(self):
class Model(models.Model):
@ -46,7 +45,8 @@ class AutoFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class BooleanFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class BooleanFieldTests(SimpleTestCase):
def test_nullable_boolean_field(self):
class Model(models.Model):
@ -65,7 +65,8 @@ class BooleanFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class CharFieldTests(IsolatedModelsTestCase, TestCase):
@isolate_apps('invalid_models_tests')
class CharFieldTests(TestCase):
def test_valid_field(self):
class Model(models.Model):
@ -216,7 +217,8 @@ class CharFieldTests(IsolatedModelsTestCase, TestCase):
self.assertEqual(errors, expected)
class DateFieldTests(IsolatedModelsTestCase, TestCase):
@isolate_apps('invalid_models_tests')
class DateFieldTests(TestCase):
def test_auto_now_and_auto_now_add_raise_error(self):
class Model(models.Model):
@ -282,7 +284,8 @@ class DateFieldTests(IsolatedModelsTestCase, TestCase):
self.test_fix_default_value()
class DateTimeFieldTests(IsolatedModelsTestCase, TestCase):
@isolate_apps('invalid_models_tests')
class DateTimeFieldTests(TestCase):
def test_fix_default_value(self):
class Model(models.Model):
@ -326,7 +329,8 @@ class DateTimeFieldTests(IsolatedModelsTestCase, TestCase):
self.test_fix_default_value()
class DecimalFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class DecimalFieldTests(SimpleTestCase):
def test_required_attributes(self):
class Model(models.Model):
@ -420,7 +424,8 @@ class DecimalFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class FileFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class FileFieldTests(SimpleTestCase):
def test_valid_case(self):
class Model(models.Model):
@ -464,7 +469,8 @@ class FileFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class FilePathFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class FilePathFieldTests(SimpleTestCase):
def test_forbidden_files_and_folders(self):
class Model(models.Model):
@ -483,7 +489,8 @@ class FilePathFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class GenericIPAddressFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class GenericIPAddressFieldTests(SimpleTestCase):
def test_non_nullable_blank(self):
class Model(models.Model):
@ -503,7 +510,8 @@ class GenericIPAddressFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class ImageFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class ImageFieldTests(SimpleTestCase):
def test_pillow_installed(self):
try:
@ -530,7 +538,8 @@ class ImageFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class IntegerFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class IntegerFieldTests(SimpleTestCase):
def test_max_length_warning(self):
class Model(models.Model):
@ -549,7 +558,8 @@ class IntegerFieldTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class TimeFieldTests(IsolatedModelsTestCase, TestCase):
@isolate_apps('invalid_models_tests')
class TimeFieldTests(TestCase):
def test_fix_default_value(self):
class Model(models.Model):

View File

@ -3,21 +3,19 @@ from __future__ import unicode_literals
import warnings
from django.apps.registry import Apps
from django.core.checks import Error, Warning as DjangoWarning
from django.db import models
from django.db.models.fields.related import ForeignObject
from django.test import ignore_warnings
from django.test.testcases import skipIfDBFeature
from django.test.utils import override_settings
from django.test.testcases import SimpleTestCase, skipIfDBFeature
from django.test.utils import isolate_apps, override_settings
from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.version import get_docs_version
from .base import IsolatedModelsTestCase
class RelativeFieldTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class RelativeFieldTests(SimpleTestCase):
def test_valid_foreign_key_without_accessor(self):
class Target(models.Model):
@ -133,23 +131,18 @@ class RelativeFieldTests(IsolatedModelsTestCase):
]
self.assertEqual(errors, expected)
def test_foreign_key_to_isolated_apps_model(self):
@isolate_apps('invalid_models_tests')
def test_foreign_key_to_isolate_apps_model(self):
"""
#25723 - Referenced model registration lookup should be run against the
field's model registry.
"""
test_apps = Apps(['invalid_models_tests'])
class OtherModel(models.Model):
class Meta:
apps = test_apps
pass
class Model(models.Model):
foreign_key = models.ForeignKey('OtherModel', models.CASCADE)
class Meta:
apps = test_apps
field = Model._meta.get_field('foreign_key')
self.assertEqual(field.check(from_model=Model), [])
@ -170,23 +163,18 @@ class RelativeFieldTests(IsolatedModelsTestCase):
]
self.assertEqual(errors, expected)
def test_many_to_many_to_isolated_apps_model(self):
@isolate_apps('invalid_models_tests')
def test_many_to_many_to_isolate_apps_model(self):
"""
#25723 - Referenced model registration lookup should be run against the
field's model registry.
"""
test_apps = Apps(['invalid_models_tests'])
class OtherModel(models.Model):
class Meta:
apps = test_apps
pass
class Model(models.Model):
m2m = models.ManyToManyField('OtherModel')
class Meta:
apps = test_apps
field = Model._meta.get_field('m2m')
self.assertEqual(field.check(from_model=Model), [])
@ -329,30 +317,22 @@ class RelativeFieldTests(IsolatedModelsTestCase):
]
self.assertEqual(errors, expected)
def test_many_to_many_through_isolated_apps_model(self):
@isolate_apps('invalid_models_tests')
def test_many_to_many_through_isolate_apps_model(self):
"""
#25723 - Through model registration lookup should be run against the
field's model registry.
"""
test_apps = Apps(['invalid_models_tests'])
class GroupMember(models.Model):
person = models.ForeignKey('Person', models.CASCADE)
group = models.ForeignKey('Group', models.CASCADE)
class Meta:
apps = test_apps
class Person(models.Model):
class Meta:
apps = test_apps
pass
class Group(models.Model):
members = models.ManyToManyField('Person', through='GroupMember')
class Meta:
apps = test_apps
field = Group._meta.get_field('members')
self.assertEqual(field.check(from_model=Group), [])
@ -790,7 +770,8 @@ class RelativeFieldTests(IsolatedModelsTestCase):
self.assertFalse(errors)
class AccessorClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class AccessorClashTests(SimpleTestCase):
def test_fk_to_integer(self):
self._test_accessor_clash(
@ -902,7 +883,8 @@ class AccessorClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class ReverseQueryNameClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class ReverseQueryNameClashTests(SimpleTestCase):
def test_fk_to_integer(self):
self._test_reverse_query_name_clash(
@ -958,7 +940,8 @@ class ReverseQueryNameClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class ExplicitRelatedNameClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class ExplicitRelatedNameClashTests(SimpleTestCase):
def test_fk_to_integer(self):
self._test_explicit_related_name_clash(
@ -1022,7 +1005,8 @@ class ExplicitRelatedNameClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class ExplicitRelatedQueryNameClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class ExplicitRelatedQueryNameClashTests(SimpleTestCase):
def test_fk_to_integer(self):
self._test_explicit_related_query_name_clash(
@ -1086,7 +1070,8 @@ class ExplicitRelatedQueryNameClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class SelfReferentialM2MClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class SelfReferentialM2MClashTests(SimpleTestCase):
def test_clash_between_accessors(self):
class Model(models.Model):
@ -1181,7 +1166,8 @@ class SelfReferentialM2MClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, [])
class SelfReferentialFKClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class SelfReferentialFKClashTests(SimpleTestCase):
def test_accessor_clash(self):
class Model(models.Model):
@ -1244,7 +1230,8 @@ class SelfReferentialFKClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class ComplexClashTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class ComplexClashTests(SimpleTestCase):
# New tests should not be included here, because this is a single,
# self-contained sanity check, not a test of everything.
@ -1358,7 +1345,8 @@ class ComplexClashTests(IsolatedModelsTestCase):
self.assertEqual(errors, expected)
class M2mThroughFieldsTests(IsolatedModelsTestCase):
@isolate_apps('invalid_models_tests')
class M2mThroughFieldsTests(SimpleTestCase):
def test_m2m_field_argument_validation(self):
"""
Tests that ManyToManyField accepts the ``through_fields`` kwarg

View File

@ -1,9 +1,9 @@
from __future__ import unicode_literals
from django.apps import apps
from django.db import models
from django.template import Context, Template
from django.test import TestCase, override_settings
from django.test.utils import isolate_apps
from django.utils.encoding import force_text
from .models import (
@ -91,82 +91,58 @@ class ManagersRegressionTests(TestCase):
AbstractBase1.objects.all()
@override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
@isolate_apps('managers_regress')
def test_swappable_manager(self):
# The models need to be removed after the test in order to prevent bad
# interactions with the flush operation in other tests.
_old_models = apps.app_configs['managers_regress'].models.copy()
class SwappableModel(models.Model):
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
try:
class SwappableModel(models.Model):
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
# Accessing the manager on a swappable model should
# raise an attribute error with a helpful message
msg = (
"Manager isn't available; 'managers_regress.SwappableModel' "
"has been swapped for 'managers_regress.Parent'"
)
with self.assertRaisesMessage(AttributeError, msg):
SwappableModel.objects.all()
finally:
apps.app_configs['managers_regress'].models = _old_models
apps.all_models['managers_regress'] = _old_models
apps.clear_cache()
# Accessing the manager on a swappable model should
# raise an attribute error with a helpful message
msg = (
"Manager isn't available; 'managers_regress.SwappableModel' "
"has been swapped for 'managers_regress.Parent'"
)
with self.assertRaisesMessage(AttributeError, msg):
SwappableModel.objects.all()
@override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
@isolate_apps('managers_regress')
def test_custom_swappable_manager(self):
# The models need to be removed after the test in order to prevent bad
# interactions with the flush operation in other tests.
_old_models = apps.app_configs['managers_regress'].models.copy()
class SwappableModel(models.Model):
stuff = models.Manager()
try:
class SwappableModel(models.Model):
stuff = models.Manager()
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
msg = (
"Manager isn't available; 'managers_regress.SwappableModel' "
"has been swapped for 'managers_regress.Parent'"
)
with self.assertRaisesMessage(AttributeError, msg):
SwappableModel.stuff.all()
finally:
apps.app_configs['managers_regress'].models = _old_models
apps.all_models['managers_regress'] = _old_models
apps.clear_cache()
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
msg = (
"Manager isn't available; 'managers_regress.SwappableModel' "
"has been swapped for 'managers_regress.Parent'"
)
with self.assertRaisesMessage(AttributeError, msg):
SwappableModel.stuff.all()
@override_settings(TEST_SWAPPABLE_MODEL='managers_regress.Parent')
@isolate_apps('managers_regress')
def test_explicit_swappable_manager(self):
# The models need to be removed after the test in order to prevent bad
# interactions with the flush operation in other tests.
_old_models = apps.app_configs['managers_regress'].models.copy()
class SwappableModel(models.Model):
objects = models.Manager()
try:
class SwappableModel(models.Model):
objects = models.Manager()
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
msg = (
"Manager isn't available; 'managers_regress.SwappableModel' "
"has been swapped for 'managers_regress.Parent'"
)
with self.assertRaisesMessage(AttributeError, msg):
SwappableModel.objects.all()
finally:
apps.app_configs['managers_regress'].models = _old_models
apps.all_models['managers_regress'] = _old_models
apps.clear_cache()
# Accessing the manager on a swappable model with an
# explicit manager should raise an attribute error with a
# helpful message
msg = (
"Manager isn't available; 'managers_regress.SwappableModel' "
"has been swapped for 'managers_regress.Parent'"
)
with self.assertRaisesMessage(AttributeError, msg):
SwappableModel.objects.all()
def test_regress_3871(self):
related = RelatedModel.objects.create()

View File

@ -19,7 +19,7 @@ from django.db.models.fields import (
TimeField, URLField,
)
from django.db.models.fields.files import FileField, ImageField
from django.test.utils import requires_tz_support
from django.test.utils import isolate_apps, requires_tz_support
from django.utils import six, timezone
from django.utils.encoding import force_str
from django.utils.functional import lazy
@ -207,7 +207,11 @@ class ForeignKeyTests(test.TestCase):
fk_model_empty = FkToChar.objects.select_related('out').get(id=fk_model_empty.pk)
self.assertEqual(fk_model_empty.out, char_model_empty)
@isolate_apps('model_fields')
def test_warning_when_unique_true_on_fk(self):
class Foo(models.Model):
pass
class FKUniqueTrue(models.Model):
fk_field = models.ForeignKey(Foo, models.CASCADE, unique=True)

View File

@ -2,9 +2,9 @@ from __future__ import unicode_literals
from operator import attrgetter
from django.apps.registry import Apps
from django.db import models
from django.test import TestCase
from django.test.utils import isolate_apps
from .base_tests import BaseOrderWithRespectToTests
from .models import Answer, Dimension, Entity, Post, Question
@ -18,12 +18,10 @@ class OrderWithRespectToBaseTests(BaseOrderWithRespectToTests, TestCase):
class OrderWithRespectToTests(TestCase):
@isolate_apps('order_with_respect_to')
def test_duplicate_order_field(self):
test_apps = Apps(['order_with_respect_to'])
class Bar(models.Model):
class Meta:
apps = test_apps
app_label = 'order_with_respect_to'
class Foo(models.Model):
@ -32,7 +30,6 @@ class OrderWithRespectToTests(TestCase):
class Meta:
order_with_respect_to = 'bar'
apps = test_apps
app_label = 'order_with_respect_to'
count = 0

View File

@ -4,11 +4,11 @@ import unittest
import uuid
from django import forms
from django.apps.registry import Apps
from django.core import exceptions, serializers, validators
from django.core.management import call_command
from django.db import IntegrityError, connection, models
from django.test import TransactionTestCase, override_settings
from django.test.utils import isolate_apps
from django.utils import timezone
from . import PostgreSQLTestCase
@ -333,17 +333,13 @@ class TestOtherTypesExactQuerying(PostgreSQLTestCase):
)
@isolate_apps('postgres_tests')
class TestChecks(PostgreSQLTestCase):
def test_field_checks(self):
test_apps = Apps(['postgres_tests'])
class MyModel(PostgreSQLModel):
field = ArrayField(models.CharField())
class Meta:
apps = test_apps
model = MyModel()
errors = model.check()
self.assertEqual(len(errors), 1)
@ -352,14 +348,9 @@ class TestChecks(PostgreSQLTestCase):
self.assertIn('max_length', errors[0].msg)
def test_invalid_base_fields(self):
test_apps = Apps(['postgres_tests'])
class MyModel(PostgreSQLModel):
field = ArrayField(models.ManyToManyField('postgres_tests.IntegerArrayModel'))
class Meta:
apps = test_apps
model = MyModel()
errors = model.check()
self.assertEqual(len(errors), 1)
@ -369,14 +360,9 @@ class TestChecks(PostgreSQLTestCase):
"""
Nested ArrayFields are permitted.
"""
test_apps = Apps(['postgres_tests'])
class MyModel(PostgreSQLModel):
field = ArrayField(ArrayField(models.CharField()))
class Meta:
apps = test_apps
model = MyModel()
errors = model.check()
self.assertEqual(len(errors), 1)

View File

@ -2,7 +2,6 @@ from __future__ import unicode_literals
import datetime
from django.apps import apps
from django.contrib import admin
from django.contrib.auth.models import User as AuthUser
from django.contrib.contenttypes.models import ContentType
@ -10,6 +9,7 @@ from django.core import checks, management
from django.db import DEFAULT_DB_ALIAS, models
from django.db.models import signals
from django.test import TestCase, override_settings
from django.test.utils import isolate_apps
from django.urls import reverse
from .admin import admin as force_admin_model_registration # NOQA
@ -129,6 +129,7 @@ class ProxyModelTests(TestCase):
proxy = True
self.assertRaises(TypeError, build_abc)
@isolate_apps('proxy_models')
def test_no_cbc(self):
"""
The proxy must actually have one concrete base class
@ -139,6 +140,7 @@ class ProxyModelTests(TestCase):
proxy = True
self.assertRaises(TypeError, build_no_cbc)
@isolate_apps('proxy_models')
def test_no_base_classes(self):
def build_no_base_classes():
class NoBaseClasses(models.Model):
@ -146,15 +148,13 @@ class ProxyModelTests(TestCase):
proxy = True
self.assertRaises(TypeError, build_no_base_classes)
@isolate_apps('proxy_models')
def test_new_fields(self):
class NoNewFields(Person):
newfield = models.BooleanField()
class Meta:
proxy = True
# don't register this model in the app_cache for the current app,
# otherwise the check fails when other tests are being run.
app_label = 'no_such_app'
errors = NoNewFields.check()
expected = [
@ -168,30 +168,22 @@ class ProxyModelTests(TestCase):
self.assertEqual(errors, expected)
@override_settings(TEST_SWAPPABLE_MODEL='proxy_models.AlternateModel')
@isolate_apps('proxy_models')
def test_swappable(self):
# The models need to be removed after the test in order to prevent bad
# interactions with the flush operation in other tests.
_old_models = apps.app_configs['proxy_models'].models.copy()
class SwappableModel(models.Model):
try:
class SwappableModel(models.Model):
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
class AlternateModel(models.Model):
pass
# You can't proxy a swapped model
with self.assertRaises(TypeError):
class ProxyModel(SwappableModel):
class Meta:
swappable = 'TEST_SWAPPABLE_MODEL'
class AlternateModel(models.Model):
pass
# You can't proxy a swapped model
with self.assertRaises(TypeError):
class ProxyModel(SwappableModel):
class Meta:
proxy = True
finally:
apps.app_configs['proxy_models'].models = _old_models
apps.all_models['proxy_models'] = _old_models
apps.clear_cache()
proxy = True
def test_myperson_manager(self):
Person.objects.create(name="fred")

View File

@ -4,6 +4,7 @@ from django.db import models
from django.db.models import signals
from django.dispatch import receiver
from django.test import TestCase
from django.test.utils import isolate_apps
from django.utils import six
from .models import Author, Book, Car, Person
@ -285,6 +286,7 @@ class LazyModelRefTest(BaseSignalTest):
finally:
signals.post_init.disconnect(self.receiver, sender=Book)
@isolate_apps('signals')
def test_not_loaded_model(self):
signals.post_init.connect(
self.receiver, sender='signals.Created', weak=False

View File

@ -1,14 +1,12 @@
from django.apps import apps
from django.conf import settings
from django.contrib.sites.managers import CurrentSiteManager
from django.contrib.sites.models import Site
from django.core import checks
from django.db import models
from django.test import TestCase
from django.test import SimpleTestCase, TestCase
from django.test.utils import isolate_apps
from .models import (
AbstractArticle, CustomArticle, ExclusiveArticle, SyndicatedArticle,
)
from .models import CustomArticle, ExclusiveArticle, SyndicatedArticle
class SitesFrameworkTestCase(TestCase):
@ -16,13 +14,6 @@ class SitesFrameworkTestCase(TestCase):
Site.objects.get_or_create(id=settings.SITE_ID, domain="example.com", name="example.com")
Site.objects.create(id=settings.SITE_ID + 1, domain="example2.com", name="example2.com")
self._old_models = apps.app_configs['sites_framework'].models.copy()
def tearDown(self):
apps.app_configs['sites_framework'].models = self._old_models
apps.all_models['sites_framework'] = self._old_models
apps.clear_cache()
def test_site_fk(self):
article = ExclusiveArticle.objects.create(title="Breaking News!", site_id=settings.SITE_ID)
self.assertEqual(ExclusiveArticle.on_site.all().get(), article)
@ -42,12 +33,12 @@ class SitesFrameworkTestCase(TestCase):
)
self.assertEqual(CustomArticle.on_site.all().get(), article)
@isolate_apps('sites_framework')
class CurrentSiteManagerChecksTests(SimpleTestCase):
def test_invalid_name(self):
class InvalidArticle(AbstractArticle):
site = models.ForeignKey(Site, models.CASCADE)
objects = models.Manager()
class InvalidArticle(models.Model):
on_site = CurrentSiteManager("places_this_article_should_appear")
errors = InvalidArticle.check()
@ -64,8 +55,9 @@ class SitesFrameworkTestCase(TestCase):
def test_invalid_field_type(self):
class ConfusedArticle(AbstractArticle):
class ConfusedArticle(models.Model):
site = models.IntegerField()
on_site = CurrentSiteManager()
errors = ConfusedArticle.check()
expected = [

View File

@ -4,9 +4,9 @@ from __future__ import unicode_literals
import datetime
from unittest import skipIf
from django.apps.registry import Apps
from django.db import models
from django.test import TestCase
from django.test.utils import isolate_apps
from django.utils import six
from .models import Article, InternationalArticle
@ -36,16 +36,14 @@ class SimpleTests(TestCase):
# python_2_unicode_compatible decorator is used.
self.assertEqual(str(a), b'Girl wins \xe2\x82\xac12.500 in lottery')
@isolate_apps('str')
def test_defaults(self):
"""
The default implementation of __str__ and __repr__ should return
instances of str.
"""
test_apps = Apps(['str'])
class Default(models.Model):
class Meta:
apps = test_apps
pass
obj = Default()
# Explicit call to __str__/__repr__ to make sure str()/repr() don't