diff --git a/tests/admin_changelist/models.py b/tests/admin_changelist/models.py index 242e4b7b6c..76249b2cd3 100644 --- a/tests/admin_changelist/models.py +++ b/tests/admin_changelist/models.py @@ -1,26 +1,32 @@ from django.db import models from django.utils.encoding import python_2_unicode_compatible + class Event(models.Model): # Oracle can have problems with a column named "date" date = models.DateField(db_column="event_date") + class Parent(models.Model): name = models.CharField(max_length=128) + class Child(models.Model): parent = models.ForeignKey(Parent, editable=False, null=True) name = models.CharField(max_length=30, blank=True) age = models.IntegerField(null=True, blank=True) + class Genre(models.Model): name = models.CharField(max_length=20) + class Band(models.Model): name = models.CharField(max_length=20) nr_of_members = models.PositiveIntegerField() genres = models.ManyToManyField(Genre) + @python_2_unicode_compatible class Musician(models.Model): name = models.CharField(max_length=30) @@ -28,6 +34,7 @@ class Musician(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Group(models.Model): name = models.CharField(max_length=30) @@ -36,26 +43,32 @@ class Group(models.Model): def __str__(self): return self.name + class Membership(models.Model): music = models.ForeignKey(Musician) group = models.ForeignKey(Group) role = models.CharField(max_length=15) + class Quartet(Group): pass + class ChordsMusician(Musician): pass + class ChordsBand(models.Model): name = models.CharField(max_length=30) members = models.ManyToManyField(ChordsMusician, through='Invitation') + class Invitation(models.Model): player = models.ForeignKey(ChordsMusician) band = models.ForeignKey(ChordsBand) instrument = models.CharField(max_length=15) + class Swallow(models.Model): origin = models.CharField(max_length=255) load = models.FloatField() @@ -77,6 +90,7 @@ class OrderedObjectManager(models.Manager): def get_queryset(self): return super(OrderedObjectManager, self).get_queryset().order_by('number') + class OrderedObject(models.Model): """ Model with Manager that defines a default order. @@ -88,5 +102,6 @@ class OrderedObject(models.Model): objects = OrderedObjectManager() + class CustomIdUser(models.Model): uuid = models.AutoField(primary_key=True) diff --git a/tests/admin_custom_urls/models.py b/tests/admin_custom_urls/models.py index 55fc064835..121e03b860 100644 --- a/tests/admin_custom_urls/models.py +++ b/tests/admin_custom_urls/models.py @@ -54,6 +54,7 @@ class ActionAdmin(admin.ModelAdmin): class Person(models.Model): name = models.CharField(max_length=20) + class PersonAdmin(admin.ModelAdmin): def response_post_save_add(self, request, obj): @@ -68,6 +69,7 @@ class PersonAdmin(admin.ModelAdmin): class Car(models.Model): name = models.CharField(max_length=20) + class CarAdmin(admin.ModelAdmin): def response_add(self, request, obj, post_url_continue=None): diff --git a/tests/admin_docs/views.py b/tests/admin_docs/views.py index e47177c37f..9a2f81d45c 100644 --- a/tests/admin_docs/views.py +++ b/tests/admin_docs/views.py @@ -5,9 +5,11 @@ from django.contrib.admindocs.middleware import XViewMiddleware xview_dec = decorator_from_middleware(XViewMiddleware) + def xview(request): return HttpResponse() + class XViewClass(View): def get(self, request): return HttpResponse() diff --git a/tests/admin_filters/models.py b/tests/admin_filters/models.py index bd2e4e5e98..4634ebb535 100644 --- a/tests/admin_filters/models.py +++ b/tests/admin_filters/models.py @@ -27,6 +27,7 @@ class Department(models.Model): def __str__(self): return self.description + @python_2_unicode_compatible class Employee(models.Model): department = models.ForeignKey(Department, to_field="code") diff --git a/tests/admin_inlines/admin.py b/tests/admin_inlines/admin.py index da5ddc03b3..b46a045052 100644 --- a/tests/admin_inlines/admin.py +++ b/tests/admin_inlines/admin.py @@ -153,6 +153,7 @@ class ChildModel1Inline(admin.TabularInline): class ChildModel2Inline(admin.StackedInline): model = ChildModel2 + # admin for #19425 and #18388 class BinaryTreeAdmin(admin.TabularInline): model = BinaryTree @@ -169,10 +170,12 @@ class BinaryTreeAdmin(admin.TabularInline): return max_num - obj.binarytree_set.count() return max_num + # admin for #19524 class SightingInline(admin.TabularInline): model = Sighting + # admin and form for #18263 class SomeChildModelForm(forms.ModelForm): diff --git a/tests/admin_inlines/models.py b/tests/admin_inlines/models.py index 36e9e8e54d..d4374ec14b 100644 --- a/tests/admin_inlines/models.py +++ b/tests/admin_inlines/models.py @@ -89,6 +89,7 @@ class Inner2(models.Model): dummy = models.IntegerField() holder = models.ForeignKey(Holder2) + class Holder3(models.Model): dummy = models.IntegerField() @@ -99,38 +100,47 @@ class Inner3(models.Model): # Models for ticket #8190 + class Holder4(models.Model): dummy = models.IntegerField() + class Inner4Stacked(models.Model): dummy = models.IntegerField(help_text="Awesome stacked help text is awesome.") holder = models.ForeignKey(Holder4) + class Inner4Tabular(models.Model): dummy = models.IntegerField(help_text="Awesome tabular help text is awesome.") holder = models.ForeignKey(Holder4) # Models for #12749 + class Person(models.Model): firstname = models.CharField(max_length=15) + class OutfitItem(models.Model): name = models.CharField(max_length=15) + class Fashionista(models.Model): person = models.OneToOneField(Person, primary_key=True) weaknesses = models.ManyToManyField(OutfitItem, through='ShoppingWeakness', blank=True) + class ShoppingWeakness(models.Model): fashionista = models.ForeignKey(Fashionista) item = models.ForeignKey(OutfitItem) # Models for #13510 + class TitleCollection(models.Model): pass + class Title(models.Model): collection = models.ForeignKey(TitleCollection, blank=True, null=True) title1 = models.CharField(max_length=100) @@ -138,19 +148,24 @@ class Title(models.Model): # Models for #15424 + class Poll(models.Model): name = models.CharField(max_length=40) + class Question(models.Model): poll = models.ForeignKey(Poll) + class Novel(models.Model): name = models.CharField(max_length=40) + class Chapter(models.Model): name = models.CharField(max_length=40) novel = models.ForeignKey(Novel) + class FootNote(models.Model): """ Model added for ticket 19838 @@ -160,6 +175,7 @@ class FootNote(models.Model): # Models for #16838 + class CapoFamiglia(models.Model): name = models.CharField(max_length=100) @@ -211,12 +227,15 @@ class BinaryTree(models.Model): # Models for #19524 + class LifeForm(models.Model): pass + class ExtraTerrestrial(LifeForm): name = models.CharField(max_length=100) + class Sighting(models.Model): et = models.ForeignKey(ExtraTerrestrial) place = models.CharField(max_length=100) @@ -234,9 +253,11 @@ class SomeChildModel(models.Model): # Other models + class ProfileCollection(models.Model): pass + class Profile(models.Model): collection = models.ForeignKey(ProfileCollection, blank=True, null=True) first_name = models.CharField(max_length=100) diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index 2d0a7edd10..8d6fc97426 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -279,6 +279,7 @@ class TestInlineMedia(TestCase): self.assertContains(response, 'my_awesome_admin_scripts.js') self.assertContains(response, 'my_awesome_inline_scripts.js') + class TestInlineAdminForm(TestCase): urls = "admin_inlines.urls" @@ -465,9 +466,9 @@ class TestInlinePermissions(TestCase): self.assertContains(response, 'Add another Inner2') # 3 extra forms only, not the existing instance form self.assertContains(response, '', html=True) + 'value="3" name="inner2_set-TOTAL_FORMS" />', html=True) self.assertNotContains(response, '' % self.inner2_id, html=True) + 'value="%i" name="inner2_set-0-id" />' % self.inner2_id, html=True) def test_inline_change_fk_change_perm(self): permission = Permission.objects.get(codename='change_inner2', content_type=self.inner_ct) @@ -477,12 +478,12 @@ class TestInlinePermissions(TestCase): self.assertContains(response, '

Inner2s

') # Just the one form for existing instances self.assertContains(response, '', html=True) + 'value="1" name="inner2_set-TOTAL_FORMS" />', html=True) self.assertContains(response, '' % self.inner2_id, html=True) + 'value="%i" name="inner2_set-0-id" />' % self.inner2_id, html=True) # max-num 0 means we can't add new ones self.assertContains(response, '', html=True) + 'value="0" name="inner2_set-MAX_NUM_FORMS" />', html=True) def test_inline_change_fk_add_change_perm(self): permission = Permission.objects.get(codename='add_inner2', content_type=self.inner_ct) @@ -494,9 +495,9 @@ class TestInlinePermissions(TestCase): self.assertContains(response, '

Inner2s

') # One form for existing instance and three extra for new self.assertContains(response, '', html=True) + 'value="4" name="inner2_set-TOTAL_FORMS" />', html=True) self.assertContains(response, '' % self.inner2_id, html=True) + 'value="%i" name="inner2_set-0-id" />' % self.inner2_id, html=True) def test_inline_change_fk_change_del_perm(self): permission = Permission.objects.get(codename='change_inner2', content_type=self.inner_ct) @@ -508,9 +509,9 @@ class TestInlinePermissions(TestCase): self.assertContains(response, '

Inner2s

') # One form for existing instance only, no new self.assertContains(response, '', html=True) + 'value="1" name="inner2_set-TOTAL_FORMS" />', html=True) self.assertContains(response, '' % self.inner2_id, html=True) + 'value="%i" name="inner2_set-0-id" />' % self.inner2_id, html=True) self.assertContains(response, 'id="id_inner2_set-0-DELETE"') def test_inline_change_fk_all_perms(self): @@ -525,9 +526,9 @@ class TestInlinePermissions(TestCase): self.assertContains(response, '

Inner2s

') # One form for existing instance only, three for new self.assertContains(response, '', html=True) + 'value="4" name="inner2_set-TOTAL_FORMS" />', html=True) self.assertContains(response, '' % self.inner2_id, html=True) + 'value="%i" name="inner2_set-0-id" />' % self.inner2_id, html=True) self.assertContains(response, 'id="id_inner2_set-0-DELETE"') @@ -698,5 +699,6 @@ class SeleniumFirefoxTests(AdminSeleniumWebDriverTestCase): class SeleniumChromeTests(SeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class SeleniumIETests(SeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' diff --git a/tests/admin_ordering/models.py b/tests/admin_ordering/models.py index 3da52b1b00..fb99d2dac5 100644 --- a/tests/admin_ordering/models.py +++ b/tests/admin_ordering/models.py @@ -11,6 +11,7 @@ class Band(models.Model): class Meta: ordering = ('name',) + class Song(models.Model): band = models.ForeignKey(Band) name = models.CharField(max_length=100) @@ -20,13 +21,16 @@ class Song(models.Model): class Meta: ordering = ('name',) + class SongInlineDefaultOrdering(admin.StackedInline): model = Song + class SongInlineNewOrdering(admin.StackedInline): model = Song ordering = ('duration', ) + class DynOrderingBandAdmin(admin.ModelAdmin): def get_ordering(self, request): diff --git a/tests/admin_ordering/tests.py b/tests/admin_ordering/tests.py index 0085b35586..e58e3b5abf 100644 --- a/tests/admin_ordering/tests.py +++ b/tests/admin_ordering/tests.py @@ -12,6 +12,7 @@ from .models import (Band, Song, SongInlineDefaultOrdering, class MockRequest(object): pass + class MockSuperUser(object): def has_perm(self, perm): return True diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index dae1314982..73a91b6e7b 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -289,6 +289,7 @@ class DjangoAdminDefaultSettings(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:NoArgsCommand") + class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase): """A series of tests for django-admin.py when using a settings.py file that contains the test application specified using a full path. @@ -355,6 +356,7 @@ class DjangoAdminFullPathDefaultSettings(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:NoArgsCommand") + class DjangoAdminMinimalSettings(AdminScriptTestCase): """A series of tests for django-admin.py when using a settings.py file that doesn't contain the test application. @@ -421,6 +423,7 @@ class DjangoAdminMinimalSettings(AdminScriptTestCase): self.assertNoOutput(out) self.assertOutput(err, "Unknown command: 'noargs_command'") + class DjangoAdminAlternateSettings(AdminScriptTestCase): """A series of tests for django-admin.py when using a settings file with a name other than 'settings.py'. @@ -796,6 +799,7 @@ class ManageFullPathDefaultSettings(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "EXECUTE:NoArgsCommand") + class ManageMinimalSettings(AdminScriptTestCase): """A series of tests for manage.py when using a settings.py file that doesn't contain the test application. @@ -862,6 +866,7 @@ class ManageMinimalSettings(AdminScriptTestCase): self.assertNoOutput(out) self.assertOutput(err, "Unknown command: 'noargs_command'") + class ManageAlternateSettings(AdminScriptTestCase): """A series of tests for manage.py when using a settings file with a name other than 'settings.py'. @@ -1121,6 +1126,7 @@ class CustomTestRunner(DiscoverRunner): def run_tests(self, test_labels, extra_tests=None, **kwargs): pass + class ManageTestCommand(AdminScriptTestCase): def setUp(self): from django.core.management.commands.test import Command as TestCommand @@ -1214,6 +1220,7 @@ class ManageRunserver(AdminScriptTestCase): self.cmd.handle(addrport="deadbeef:7654") self.assertServerSettings('deadbeef', '7654') + class ManageRunserverEmptyAllowedHosts(AdminScriptTestCase): def setUp(self): self.write_settings('settings.py', sdict={ @@ -1464,6 +1471,7 @@ class CommandTypes(AdminScriptTestCase): self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=testlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) + class ArgumentOrder(AdminScriptTestCase): """Tests for 2-stage argument parsing scheme. @@ -1751,6 +1759,7 @@ class DiffSettings(AdminScriptTestCase): self.assertNoOutput(err) self.assertOutput(out, "### STATIC_URL = None") + class Dumpdata(AdminScriptTestCase): """Tests for dumpdata management command.""" diff --git a/tests/admin_util/models.py b/tests/admin_util/models.py index 32a6cd6291..5e86f55a3a 100644 --- a/tests/admin_util/models.py +++ b/tests/admin_util/models.py @@ -19,6 +19,7 @@ class Article(models.Model): return "nothing" test_from_model_with_override.short_description = "not What you Expect" + @python_2_unicode_compatible class Count(models.Model): num = models.PositiveSmallIntegerField() @@ -27,12 +28,15 @@ class Count(models.Model): def __str__(self): return six.text_type(self.num) + class Event(models.Model): date = models.DateTimeField(auto_now_add=True) + class Location(models.Model): event = models.OneToOneField(Event, verbose_name='awesome event') + class Guest(models.Model): event = models.OneToOneField(Event) name = models.CharField(max_length=255) @@ -40,5 +44,6 @@ class Guest(models.Model): class Meta: verbose_name = "awesome guest" + class EventGuide(models.Model): event = models.ForeignKey(Event, on_delete=models.DO_NOTHING) diff --git a/tests/admin_util/tests.py b/tests/admin_util/tests.py index 915dfced08..b978a4ab05 100644 --- a/tests/admin_util/tests.py +++ b/tests/admin_util/tests.py @@ -80,6 +80,7 @@ class NestedObjectsTests(TestCase): # One for Location, one for Guest, and no query for EventGuide n.collect(objs) + class UtilTests(SimpleTestCase): def test_values_from_lookup_field(self): """ @@ -228,9 +229,8 @@ class UtilTests(SimpleTestCase): ) self.assertEqual( label_for_field("test_from_model", Article, - model_admin = MockModelAdmin, - return_attr = True - ), + model_admin=MockModelAdmin, + return_attr=True), ("not Really the Model", MockModelAdmin.test_from_model) ) diff --git a/tests/admin_validation/tests.py b/tests/admin_validation/tests.py index f1346647ee..5e38af82f0 100644 --- a/tests/admin_validation/tests.py +++ b/tests/admin_validation/tests.py @@ -12,10 +12,12 @@ from .models import Song, Book, Album, TwoAlbumFKAndAnE, City class SongForm(forms.ModelForm): pass + class ValidFields(admin.ModelAdmin): form = SongForm fields = ['title'] + class ValidFormFieldsets(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): class ExtraFieldForm(SongForm): @@ -28,6 +30,7 @@ class ValidFormFieldsets(admin.ModelAdmin): }), ) + class ValidationTestCase(TestCase): def test_readonly_and_editable(self): diff --git a/tests/admin_views/models.py b/tests/admin_views/models.py index 4dcca9a4cb..e2b6a00261 100644 --- a/tests/admin_views/models.py +++ b/tests/admin_views/models.py @@ -120,11 +120,13 @@ class Color(models.Model): def __str__(self): return self.value + # we replicate Color to register with another ModelAdmin class Color2(Color): class Meta: proxy = True + @python_2_unicode_compatible class Thing(models.Model): title = models.CharField(max_length=20) @@ -613,10 +615,12 @@ class PrePopulatedPostLargeSlug(models.Model): published = models.BooleanField(default=False) slug = models.SlugField(max_length=1000) + class AdminOrderedField(models.Model): order = models.IntegerField() stuff = models.CharField(max_length=200) + class AdminOrderedModelMethod(models.Model): order = models.IntegerField() stuff = models.CharField(max_length=200) @@ -625,14 +629,17 @@ class AdminOrderedModelMethod(models.Model): return self.order some_order.admin_order_field = 'order' + class AdminOrderedAdminMethod(models.Model): order = models.IntegerField() stuff = models.CharField(max_length=200) + class AdminOrderedCallable(models.Model): order = models.IntegerField() stuff = models.CharField(max_length=200) + @python_2_unicode_compatible class Report(models.Model): title = models.CharField(max_length=100) @@ -651,6 +658,7 @@ class MainPrepopulated(models.Model): slug1 = models.SlugField(blank=True) slug2 = models.SlugField(blank=True) + class RelatedPrepopulated(models.Model): parent = models.ForeignKey(MainPrepopulated) name = models.CharField(max_length=75) @@ -671,6 +679,7 @@ class UnorderedObject(models.Model): name = models.CharField(max_length=255) bool = models.BooleanField(default=True) + class UndeletableObject(models.Model): """ Model whose show_delete in admin change_view has been disabled @@ -678,30 +687,36 @@ class UndeletableObject(models.Model): """ name = models.CharField(max_length=255) + class UnchangeableObject(models.Model): """ Model whose change_view is disabled in admin Refs #20640. """ + class UserMessenger(models.Model): """ Dummy class for testing message_user functions on ModelAdmin """ + class Simple(models.Model): """ Simple model with nothing on it for use in testing """ + class Choice(models.Model): choice = models.IntegerField(blank=True, null=True, choices=((1, 'Yes'), (0, 'No'), (None, 'No opinion'))) + class _Manager(models.Manager): def get_queryset(self): return super(_Manager, self).get_queryset().filter(pk__gt=1) + class FilteredManager(models.Model): def __str__(self): return "PK=%d" % self.pk @@ -709,26 +724,33 @@ class FilteredManager(models.Model): pk_gt_1 = _Manager() objects = models.Manager() + class EmptyModelVisible(models.Model): """ See ticket #11277. """ + class EmptyModelHidden(models.Model): """ See ticket #11277. """ + class EmptyModelMixin(models.Model): """ See ticket #11277. """ + class State(models.Model): name = models.CharField(max_length=100) + class City(models.Model): state = models.ForeignKey(State) name = models.CharField(max_length=100) + class Restaurant(models.Model): city = models.ForeignKey(City) name = models.CharField(max_length=100) + class Worker(models.Model): work_at = models.ForeignKey(Restaurant) name = models.CharField(max_length=50) diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 91af9521a3..0ec9f25479 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -84,8 +84,8 @@ class AdminViewBasicTestCase(TestCase): """ self.assertEqual(response.status_code, 200) self.assertTrue(response.content.index(force_bytes(text1)) < response.content.index(force_bytes(text2)), - failing_msg - ) + failing_msg) + class AdminViewBasicTest(AdminViewBasicTestCase): def testTrailingSlashRequired(self): @@ -94,8 +94,8 @@ class AdminViewBasicTest(AdminViewBasicTestCase): """ response = self.client.get('/test_admin/%s/admin_views/article/add' % self.urlbit) self.assertRedirects(response, - '/test_admin/%s/admin_views/article/add/' % self.urlbit, status_code=301 - ) + '/test_admin/%s/admin_views/article/add/' % self.urlbit, + status_code=301) def testBasicAddGet(self): """ @@ -109,8 +109,7 @@ class AdminViewBasicTest(AdminViewBasicTestCase): response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit, {'name': 'My Section'}) self.assertEqual(response.status_code, 200) self.assertContains(response, 'value="My Section"', - msg_prefix="Couldn't find an input with the right value in the response" - ) + msg_prefix="Couldn't find an input with the right value in the response") def testBasicEditGet(self): """ @@ -394,11 +393,9 @@ class AdminViewBasicTest(AdminViewBasicTestCase): response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit) self.assertEqual(response.status_code, 200) self.assertContains(response, '
', - msg_prefix="Expected filter not found in changelist view" - ) + msg_prefix="Expected filter not found in changelist view") self.assertNotContains(response, 'Blue', - msg_prefix="Changelist filter not correctly limited by limit_choices_to" - ) + msg_prefix="Changelist filter not correctly limited by limit_choices_to") def testRelationSpanningFilters(self): response = self.client.get('/test_admin/%s/admin_views/chapterxtra1/' % @@ -1557,7 +1554,7 @@ class AdminViewStringPrimaryKeyTest(TestCase): response = self.client.get('/test_admin/admin/') counted_presence_after = response.content.count(force_bytes(should_contain)) self.assertEqual(counted_presence_before - 1, - counted_presence_after) + counted_presence_after) def test_logentry_get_admin_url(self): "LogEntry.get_admin_url returns a URL to edit the entry's object or None for non-existent (possibly deleted) models" @@ -1612,13 +1609,13 @@ class AdminViewStringPrimaryKeyTest(TestCase): def test_change_view_history_link(self): """Object history button link should work and contain the pk value quoted.""" url = reverse('admin:%s_modelwithstringprimarykey_change' % - ModelWithStringPrimaryKey._meta.app_label, - args=(quote(self.pk),)) + ModelWithStringPrimaryKey._meta.app_label, + args=(quote(self.pk),)) response = self.client.get(url) self.assertEqual(response.status_code, 200) expected_link = reverse('admin:%s_modelwithstringprimarykey_history' % - ModelWithStringPrimaryKey._meta.app_label, - args=(quote(self.pk),)) + ModelWithStringPrimaryKey._meta.app_label, + args=(quote(self.pk),)) self.assertContains(response, ' response = self.client.get('/test_admin/admin/admin_views/oldsubscriber/') self.assertEqual(response.context["action_form"], None) self.assertContains(response, 'jquery.min.js', - msg_prefix="jQuery missing from admin pages for model with no admin actions" - ) + msg_prefix="jQuery missing from admin pages for model with no admin actions") def test_action_column_class(self): "Tests that the checkbox column class is present in the response" @@ -3631,8 +3627,7 @@ class ReadonlyTest(TestCase): self.assertContains(response, "InlineMultiline
test
string") self.assertContains(response, - formats.localize(datetime.date.today() - datetime.timedelta(days=7)) - ) + formats.localize(datetime.date.today() - datetime.timedelta(days=7))) self.assertContains(response, '
') self.assertContains(response, '
') @@ -3829,7 +3824,7 @@ class UserAdminTest(TestCase): adminform = response.context['adminform'] self.assertTrue('password' not in adminform.form.errors) self.assertEqual(adminform.form.errors['password2'], - ["The two password fields didn't match."]) + ["The two password fields didn't match."]) def test_user_fk_popup(self): """Quick user addition in a FK popup shouldn't invoke view for further user customization""" diff --git a/tests/admin_views/views.py b/tests/admin_views/views.py index bb5f24ebfe..cfae496aba 100644 --- a/tests/admin_views/views.py +++ b/tests/admin_views/views.py @@ -1,6 +1,7 @@ from django.contrib.admin.views.decorators import staff_member_required from django.http import HttpResponse + @staff_member_required def secure_view(request): return HttpResponse('%s' % request.POST) diff --git a/tests/admin_widgets/models.py b/tests/admin_widgets/models.py index 6a6c6e096b..5d295f0c9b 100644 --- a/tests/admin_widgets/models.py +++ b/tests/admin_widgets/models.py @@ -8,6 +8,7 @@ from django.utils.encoding import python_2_unicode_compatible class MyFileField(models.FileField): pass + @python_2_unicode_compatible class Member(models.Model): name = models.CharField(max_length=100) @@ -18,6 +19,7 @@ class Member(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Band(models.Model): name = models.CharField(max_length=100) @@ -27,6 +29,7 @@ class Band(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Album(models.Model): band = models.ForeignKey(Band) @@ -37,10 +40,12 @@ class Album(models.Model): def __str__(self): return self.name + class HiddenInventoryManager(models.Manager): def get_queryset(self): return super(HiddenInventoryManager, self).get_queryset().filter(hidden=False) + @python_2_unicode_compatible class Inventory(models.Model): barcode = models.PositiveIntegerField(unique=True) @@ -55,6 +60,7 @@ class Inventory(models.Model): def __str__(self): return self.name + class Event(models.Model): main_band = models.ForeignKey(Band, limit_choices_to=models.Q(pk__gt=0), related_name='events_main_band_at') supporting_bands = models.ManyToManyField(Band, null=True, blank=True, related_name='events_supporting_band_at') @@ -64,6 +70,7 @@ class Event(models.Model): link = models.URLField(blank=True) min_age = models.IntegerField(blank=True, null=True) + @python_2_unicode_compatible class Car(models.Model): owner = models.ForeignKey(User) @@ -73,15 +80,18 @@ class Car(models.Model): def __str__(self): return "%s %s" % (self.make, self.model) + class CarTire(models.Model): """ A single car tire. This to test that a user can only select their own cars. """ car = models.ForeignKey(Car) + class Honeycomb(models.Model): location = models.CharField(max_length=20) + class Bee(models.Model): """ A model with a FK to a model that won't be registered with the admin @@ -90,6 +100,7 @@ class Bee(models.Model): """ honeycomb = models.ForeignKey(Honeycomb) + class Individual(models.Model): """ A model with a FK to itself. It won't be registered with the admin, so the @@ -99,9 +110,11 @@ class Individual(models.Model): name = models.CharField(max_length=20) parent = models.ForeignKey('self', null=True) + class Company(models.Model): name = models.CharField(max_length=20) + class Advisor(models.Model): """ A model with a m2m to a model that won't be registered with the admin @@ -122,6 +135,7 @@ class Student(models.Model): class Meta: ordering = ('name',) + @python_2_unicode_compatible class School(models.Model): name = models.CharField(max_length=255) diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py index 4b36f8bd32..0dec3a2cfa 100644 --- a/tests/admin_widgets/tests.py +++ b/tests/admin_widgets/tests.py @@ -25,6 +25,7 @@ admin_static_prefix = lambda: { 'ADMIN_STATIC_PREFIX': "%sadmin/" % settings.STATIC_URL, } + class AdminFormfieldForDBFieldTests(TestCase): """ Tests for correct behavior of ModelAdmin.formfield_for_dbfield @@ -269,6 +270,7 @@ class FilteredSelectMultipleWidgetTest(DjangoTestCase): '\n' % admin_static_prefix() ) + class AdminDateWidgetTest(DjangoTestCase): def test_attrs(self): """ @@ -287,6 +289,7 @@ class AdminDateWidgetTest(DjangoTestCase): '', ) + class AdminTimeWidgetTest(DjangoTestCase): def test_attrs(self): """ @@ -305,6 +308,7 @@ class AdminTimeWidgetTest(DjangoTestCase): '', ) + class AdminSplitDateTimeWidgetTest(DjangoTestCase): def test_render(self): w = widgets.AdminSplitDateTime() @@ -495,6 +499,7 @@ class ManyToManyRawIdWidgetTest(DjangoTestCase): '' % {'c1pk': c1.pk} ) + class RelatedFieldWidgetWrapperTests(DjangoTestCase): def test_no_can_add_related(self): rel = models.Individual._meta.get_field('parent').rel @@ -631,6 +636,7 @@ class DateTimePickerSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase): class DateTimePickerSeleniumChromeTests(DateTimePickerSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class DateTimePickerSeleniumIETests(DateTimePickerSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' @@ -686,9 +692,11 @@ class DateTimePickerShortcutsSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase self.assertGreater(member.birthdate, now - error_margin) self.assertLess(member.birthdate, now + error_margin) + class DateTimePickerShortcutsSeleniumChromeTests(DateTimePickerShortcutsSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class DateTimePickerShortcutsSeleniumIETests(DateTimePickerShortcutsSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' @@ -714,7 +722,7 @@ class HorizontalVerticalFilterSeleniumFirefoxTests(AdminSeleniumWebDriverTestCas super(HorizontalVerticalFilterSeleniumFirefoxTests, self).setUp() def assertActiveButtons(self, mode, field_name, choose, remove, - choose_all=None, remove_all=None): + choose_all=None, remove_all=None): choose_link = '#id_%s_add_link' % field_name choose_all_link = '#id_%s_add_all_link' % field_name remove_link = '#id_%s_remove_link' % field_name @@ -928,9 +936,11 @@ class HorizontalVerticalFilterSeleniumFirefoxTests(AdminSeleniumWebDriverTestCas self.assertEqual(list(self.school.alumni.all()), [self.jason, self.peter]) + class HorizontalVerticalFilterSeleniumChromeTests(HorizontalVerticalFilterSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class HorizontalVerticalFilterSeleniumIETests(HorizontalVerticalFilterSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' @@ -1025,9 +1035,11 @@ class AdminRawIdWidgetSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase): self.selenium.find_element_by_id('id_supporting_bands').get_attribute('value'), '42,98') + class AdminRawIdWidgetSeleniumChromeTests(AdminRawIdWidgetSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class AdminRawIdWidgetSeleniumIETests(AdminRawIdWidgetSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' @@ -1072,8 +1084,10 @@ class RelatedFieldWidgetSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase): self.assertEqual(len(profiles), 1) self.assertEqual(profiles[0].user.username, username_value) + class RelatedFieldWidgetSeleniumChromeTests(RelatedFieldWidgetSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver' + class RelatedFieldWidgetSeleniumIETests(RelatedFieldWidgetSeleniumFirefoxTests): webdriver_class = 'selenium.webdriver.ie.webdriver.WebDriver' diff --git a/tests/aggregation/models.py b/tests/aggregation/models.py index 9710afaf11..691737c17e 100644 --- a/tests/aggregation/models.py +++ b/tests/aggregation/models.py @@ -12,6 +12,7 @@ class Author(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Publisher(models.Model): name = models.CharField(max_length=255) @@ -20,6 +21,7 @@ class Publisher(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Book(models.Model): isbn = models.CharField(max_length=9) @@ -35,6 +37,7 @@ class Book(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Store(models.Model): name = models.CharField(max_length=255) diff --git a/tests/aggregation_regress/models.py b/tests/aggregation_regress/models.py index a2dc060640..275e37c036 100644 --- a/tests/aggregation_regress/models.py +++ b/tests/aggregation_regress/models.py @@ -61,6 +61,7 @@ class Store(models.Model): def __str__(self): return self.name + class Entries(models.Model): EntryID = models.AutoField(primary_key=True, db_column='Entry ID') Entry = models.CharField(unique=True, max_length=50) @@ -69,7 +70,7 @@ class Entries(models.Model): class Clues(models.Model): ID = models.AutoField(primary_key=True) - EntryID = models.ForeignKey(Entries, verbose_name='Entry', db_column = 'Entry ID') + EntryID = models.ForeignKey(Entries, verbose_name='Entry', db_column='Entry ID') Clue = models.CharField(max_length=150) @@ -88,13 +89,16 @@ class HardbackBook(Book): def __str__(self): return "%s (hardback): %s" % (self.name, self.weight) + # Models for ticket #21150 class Alfa(models.Model): name = models.CharField(max_length=10, null=True) + class Bravo(models.Model): pass + class Charlie(models.Model): alfa = models.ForeignKey(Alfa, null=True) bravo = models.ForeignKey(Bravo, null=True) diff --git a/tests/backends/tests.py b/tests/backends/tests.py index 3c0cc67ea2..3a79b79411 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -432,6 +432,7 @@ class EscapingChecks(TestCase): # response should be an non-zero integer self.assertTrue(int(response)) + @override_settings(DEBUG=True) class EscapingChecksDebug(EscapingChecks): pass @@ -509,12 +510,12 @@ class BackendTestCase(TestCase): def test_cursor_executemany(self): #4896: Test cursor.executemany - args = [(i, i**2) for i in range(-5, 6)] + args = [(i, i ** 2) for i in range(-5, 6)] self.create_squares_with_executemany(args) self.assertEqual(models.Square.objects.count(), 11) for i in range(-5, 6): square = models.Square.objects.get(root=i) - self.assertEqual(square.square, i**2) + self.assertEqual(square.square, i ** 2) def test_cursor_executemany_with_empty_params_list(self): #4765: executemany with params=[] does nothing @@ -524,11 +525,11 @@ class BackendTestCase(TestCase): def test_cursor_executemany_with_iterator(self): #10320: executemany accepts iterators - args = iter((i, i**2) for i in range(-3, 2)) + args = iter((i, i ** 2) for i in range(-3, 2)) self.create_squares_with_executemany(args) self.assertEqual(models.Square.objects.count(), 5) - args = iter((i, i**2) for i in range(3, 7)) + args = iter((i, i ** 2) for i in range(3, 7)) with override_settings(DEBUG=True): # same test for DebugCursorWrapper self.create_squares_with_executemany(args) @@ -544,20 +545,20 @@ class BackendTestCase(TestCase): @skipUnlessDBFeature('supports_paramstyle_pyformat') def test_cursor_executemany_with_pyformat(self): #10070: Support pyformat style passing of paramters - args = [{'root': i, 'square': i**2} for i in range(-5, 6)] + args = [{'root': i, 'square': i ** 2} for i in range(-5, 6)] self.create_squares(args, 'pyformat', multiple=True) self.assertEqual(models.Square.objects.count(), 11) for i in range(-5, 6): square = models.Square.objects.get(root=i) - self.assertEqual(square.square, i**2) + self.assertEqual(square.square, i ** 2) @skipUnlessDBFeature('supports_paramstyle_pyformat') def test_cursor_executemany_with_pyformat_iterator(self): - args = iter({'root': i, 'square': i**2} for i in range(-3, 2)) + args = iter({'root': i, 'square': i ** 2} for i in range(-3, 2)) self.create_squares(args, 'pyformat', multiple=True) self.assertEqual(models.Square.objects.count(), 5) - args = iter({'root': i, 'square': i**2} for i in range(3, 7)) + args = iter({'root': i, 'square': i ** 2} for i in range(3, 7)) with override_settings(DEBUG=True): # same test for DebugCursorWrapper self.create_squares(args, 'pyformat', multiple=True) @@ -987,6 +988,7 @@ class BackendUtilTests(TestCase): equal('0.1234567890', 12, 0, '0') + @unittest.skipUnless( connection.vendor == 'postgresql', "This test applies only to PostgreSQL") diff --git a/tests/basic/models.py b/tests/basic/models.py index 38cb813d42..5e67b0dca9 100644 --- a/tests/basic/models.py +++ b/tests/basic/models.py @@ -19,11 +19,13 @@ class Article(models.Model): def __str__(self): return self.headline + class ArticleSelectOnSave(Article): class Meta: proxy = True select_on_save = True + @python_2_unicode_compatible class SelfRef(models.Model): selfref = models.ForeignKey('self', null=True, blank=True, diff --git a/tests/basic/tests.py b/tests/basic/tests.py index e4559dc7d7..976fb1124d 100644 --- a/tests/basic/tests.py +++ b/tests/basic/tests.py @@ -87,7 +87,8 @@ class ModelTest(TestCase): # Django raises an Article.DoesNotExist exception for get() if the # parameters don't match any object. - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, ObjectDoesNotExist, "Article matching query does not exist.", Article.objects.get, @@ -102,7 +103,8 @@ class ModelTest(TestCase): pub_date__month=8, ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, ObjectDoesNotExist, "Article matching query does not exist.", Article.objects.get, @@ -135,21 +137,24 @@ class ModelTest(TestCase): # Django raises an Article.MultipleObjectsReturned exception if the # lookup matches more than one object - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, headline__startswith='Area', ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, pub_date__year=2005, ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned 2!", Article.objects.get, @@ -165,14 +170,16 @@ class ModelTest(TestCase): Article(headline='Area %s' % i, pub_date=datetime(2005, 7, 28)) for i in range(MAX_GET_RESULTS) ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned %d!" % MAX_GET_RESULTS, Article.objects.get, headline__startswith='Area', ) Article.objects.create(headline='Area %s' % MAX_GET_RESULTS, pub_date=datetime(2005, 7, 28)) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, MultipleObjectsReturned, "get\(\) returned more than one Article -- it returned more than %d!" % MAX_GET_RESULTS, Article.objects.get, @@ -219,7 +226,8 @@ class ModelTest(TestCase): self.assertEqual(a4.headline, 'Fourth article') # Don't use invalid keyword arguments. - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, TypeError, "'foo' is an invalid keyword argument for this function", Article, @@ -315,7 +323,8 @@ class ModelTest(TestCase): Article.objects.dates, ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, FieldDoesNotExist, "Article has no field named 'invalid_field'", Article.objects.dates, @@ -323,7 +332,8 @@ class ModelTest(TestCase): "year", ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, AssertionError, "'kind' must be one of 'year', 'month' or 'day'.", Article.objects.dates, @@ -331,7 +341,8 @@ class ModelTest(TestCase): "bad_kind", ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, AssertionError, "'order' must be either 'ASC' or 'DESC'.", Article.objects.dates, @@ -419,14 +430,16 @@ class ModelTest(TestCase): ""]) # Also, once you have sliced you can't filter, re-order or combine - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, AssertionError, "Cannot filter a query once a slice has been taken.", Article.objects.all()[0:5].filter, id=a.id, ) - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, AssertionError, "Cannot reorder a query once a slice has been taken.", Article.objects.all()[0:5].order_by, @@ -461,7 +474,8 @@ class ModelTest(TestCase): # An Article instance doesn't have access to the "objects" attribute. # That's only available on the class. - six.assertRaisesRegex(self, + six.assertRaisesRegex( + self, AttributeError, "Manager isn't accessible via Article instances", getattr, @@ -605,8 +619,8 @@ class ModelTest(TestCase): ) dicts = Article.objects.filter( - pub_date__year=2008).extra(select={'dashed-value': '1'} - ).values('headline', 'dashed-value') + pub_date__year=2008).extra( + select={'dashed-value': '1'}).values('headline', 'dashed-value') self.assertEqual([sorted(d.items()) for d in dicts], [[('dashed-value', 1), ('headline', 'Article 11')], [('dashed-value', 1), ('headline', 'Article 12')]]) @@ -723,6 +737,7 @@ class ModelTest(TestCase): # hash) hash(Article()) + class ConcurrentSaveTests(TransactionTestCase): available_apps = ['basic'] @@ -808,6 +823,7 @@ class ManagerTest(TestCase): sorted(self.QUERYSET_PROXY_METHODS), ) + class SelectOnSaveTests(TestCase): def test_select_on_save(self): a1 = Article.objects.create(pub_date=datetime.now()) diff --git a/tests/bug639/models.py b/tests/bug639/models.py index fa8e7d2c07..3b6a007f6b 100644 --- a/tests/bug639/models.py +++ b/tests/bug639/models.py @@ -8,6 +8,7 @@ from django.forms import ModelForm temp_storage_dir = tempfile.mkdtemp() temp_storage = FileSystemStorage(temp_storage_dir) + class Photo(models.Model): title = models.CharField(max_length=30) image = models.FileField(storage=temp_storage, upload_to='tests') @@ -22,6 +23,7 @@ class Photo(models.Model): super(Photo, self).save(force_insert, force_update) self._savecount += 1 + class PhotoForm(ModelForm): class Meta: model = Photo diff --git a/tests/bulk_create/models.py b/tests/bulk_create/models.py index bc685bbbe4..fcc4b4177e 100644 --- a/tests/bulk_create/models.py +++ b/tests/bulk_create/models.py @@ -5,21 +5,26 @@ class Country(models.Model): name = models.CharField(max_length=255) iso_two_letter = models.CharField(max_length=2) + class Place(models.Model): name = models.CharField(max_length=100) class Meta: abstract = True + class Restaurant(Place): pass + class Pizzeria(Restaurant): pass + class State(models.Model): two_letter_code = models.CharField(max_length=2, primary_key=True) + class TwoFields(models.Model): f1 = models.IntegerField(unique=True) f2 = models.IntegerField(unique=True) diff --git a/tests/cache/closeable_cache.py b/tests/cache/closeable_cache.py index 83073850b7..1ac868dde9 100644 --- a/tests/cache/closeable_cache.py +++ b/tests/cache/closeable_cache.py @@ -7,5 +7,6 @@ class CloseHookMixin(object): def close(self, **kwargs): self.closed = True + class CacheClass(CloseHookMixin, LocMemCache): pass diff --git a/tests/cache/liberal_backend.py b/tests/cache/liberal_backend.py index 3e3ce3beeb..339066b0ff 100644 --- a/tests/cache/liberal_backend.py +++ b/tests/cache/liberal_backend.py @@ -5,5 +5,6 @@ class LiberalKeyValidationMixin(object): def validate_key(self, key): pass + class CacheClass(LiberalKeyValidationMixin, LocMemCache): pass diff --git a/tests/cache/models.py b/tests/cache/models.py index 2cd648b780..4fccbb664b 100644 --- a/tests/cache/models.py +++ b/tests/cache/models.py @@ -7,6 +7,7 @@ def expensive_calculation(): expensive_calculation.num_runs += 1 return timezone.now() + class Poll(models.Model): question = models.CharField(max_length=200) answer = models.CharField(max_length=200) diff --git a/tests/cache/tests.py b/tests/cache/tests.py index a79d4d9fac..a93ed4418a 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -40,10 +40,12 @@ from django.views.decorators.cache import cache_page from .models import Poll, expensive_calculation + # functions/classes for complex data type tests def f(): return 42 + class C: def m(n): return 24 @@ -823,6 +825,7 @@ class BaseCacheTests(object): self.assertEqual(get_cache_data.content, content.encode('utf-8')) self.assertEqual(get_cache_data.cookies, response.cookies) + def custom_key_func(key, key_prefix, version): "A customized cache key function" return 'CUSTOM-' + '-'.join([key_prefix, str(version), key]) @@ -1004,6 +1007,7 @@ class LocMemCacheTests(unittest.TestCase, BaseCacheTests): self.cache.decr(key) self.assertEqual(expire, self.cache._expire_info[_key]) + # memcached backend isn't guaranteed to be available. # To check the memcached backend, the test settings file will # need to contain at least one cache backend setting that points at @@ -1581,6 +1585,7 @@ class CacheI18nTest(TestCase): get_cache_data = FetchFromCacheMiddleware().process_request(request) self.assertIsNone(get_cache_data) + @override_settings( CACHES={ 'default': { @@ -1816,6 +1821,7 @@ class CacheMiddlewareTest(IgnoreDeprecationWarningsMixin, TestCase): response = other_with_prefix_view(request, '16') self.assertEqual(response.content, b'Hello World 16') + @override_settings( CACHE_MIDDLEWARE_KEY_PREFIX='settingsprefix', CACHE_MIDDLEWARE_SECONDS=1, diff --git a/tests/check/models.py b/tests/check/models.py index 212b01bdd2..ddeed23982 100644 --- a/tests/check/models.py +++ b/tests/check/models.py @@ -1,9 +1,11 @@ from django.db import models + class Book(models.Model): title = models.CharField(max_length=250) is_published = models.BooleanField(default=False) + class BlogPost(models.Model): title = models.CharField(max_length=250) is_published = models.BooleanField(default=False) diff --git a/tests/check/tests.py b/tests/check/tests.py index 19b3840a9a..577dcd610b 100644 --- a/tests/check/tests.py +++ b/tests/check/tests.py @@ -7,6 +7,7 @@ from django.test import TestCase from .models import Book + class StubCheckModule(object): # Has no ``run_checks`` attribute & will trigger a warning. __name__ = 'StubCheckModule' diff --git a/tests/choices/models.py b/tests/choices/models.py index 2fa33a9680..4fcef6f48f 100644 --- a/tests/choices/models.py +++ b/tests/choices/models.py @@ -18,6 +18,7 @@ GENDER_CHOICES = ( ('F', 'Female'), ) + @python_2_unicode_compatible class Person(models.Model): name = models.CharField(max_length=20) diff --git a/tests/commands_sql/tests.py b/tests/commands_sql/tests.py index 1a1a190ec5..3a0b5527f4 100644 --- a/tests/commands_sql/tests.py +++ b/tests/commands_sql/tests.py @@ -58,6 +58,7 @@ class TestRouter(object): def allow_migrate(self, db, model): return False + class SQLCommandsRouterTestCase(TestCase): def setUp(self): self._old_routers = router.routers diff --git a/tests/conditional_processing/tests.py b/tests/conditional_processing/tests.py index 77f1ff54ed..2c832e527c 100644 --- a/tests/conditional_processing/tests.py +++ b/tests/conditional_processing/tests.py @@ -15,6 +15,7 @@ EXPIRED_LAST_MODIFIED_STR = 'Sat, 20 Oct 2007 23:21:47 GMT' ETAG = 'b4246ffc4f62314ca13147c9d4f76974' EXPIRED_ETAG = '7fae4cd4b0f81e7d2914700043aa8ed6' + class ConditionalGet(TestCase): urls = 'conditional_processing.urls' diff --git a/tests/conditional_processing/views.py b/tests/conditional_processing/views.py index 2960e0533d..496e79fd34 100644 --- a/tests/conditional_processing/views.py +++ b/tests/conditional_processing/views.py @@ -8,18 +8,22 @@ def index(request): return HttpResponse(FULL_RESPONSE) index = condition(lambda r: ETAG, lambda r: LAST_MODIFIED)(index) + def last_modified_view1(request): return HttpResponse(FULL_RESPONSE) last_modified_view1 = condition(last_modified_func=lambda r: LAST_MODIFIED)(last_modified_view1) + def last_modified_view2(request): return HttpResponse(FULL_RESPONSE) last_modified_view2 = last_modified(lambda r: LAST_MODIFIED)(last_modified_view2) + def etag_view1(request): return HttpResponse(FULL_RESPONSE) etag_view1 = condition(etag_func=lambda r: ETAG)(etag_view1) + def etag_view2(request): return HttpResponse(FULL_RESPONSE) etag_view2 = etag(lambda r: ETAG)(etag_view2) diff --git a/tests/contenttypes_tests/models.py b/tests/contenttypes_tests/models.py index 5d21ad5b96..b2669367eb 100644 --- a/tests/contenttypes_tests/models.py +++ b/tests/contenttypes_tests/models.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.db import models from django.utils.encoding import python_2_unicode_compatible + @python_2_unicode_compatible class Author(models.Model): name = models.CharField(max_length=100) @@ -13,6 +14,7 @@ class Author(models.Model): def get_absolute_url(self): return '/views/authors/%s/' % self.id + @python_2_unicode_compatible class Article(models.Model): title = models.CharField(max_length=100) diff --git a/tests/contenttypes_tests/tests.py b/tests/contenttypes_tests/tests.py index 63f02697df..29ae6c5336 100644 --- a/tests/contenttypes_tests/tests.py +++ b/tests/contenttypes_tests/tests.py @@ -5,6 +5,7 @@ from django.test import TestCase from .models import Author, Article + class ContentTypesViewsTests(TestCase): fixtures = ['testdata.json'] urls = 'contenttypes_tests.urls' diff --git a/tests/csrf_tests/tests.py b/tests/csrf_tests/tests.py index 57f8359cc7..ac48c17af6 100644 --- a/tests/csrf_tests/tests.py +++ b/tests/csrf_tests/tests.py @@ -19,10 +19,12 @@ def post_form_response(): """, mimetype="text/html") return resp + def post_form_view(request): """A view that returns a POST form (without a token)""" return post_form_response() + # Response/views used for template tag tests def token_view(request): @@ -31,6 +33,7 @@ def token_view(request): template = Template("{% csrf_token %}") return HttpResponse(template.render(context)) + def non_token_view_using_request_processor(request): """ A view that doesn't use the token, but does use the csrf view processor. @@ -39,6 +42,7 @@ def non_token_view_using_request_processor(request): template = Template("") return HttpResponse(template.render(context)) + class TestingHttpRequest(HttpRequest): """ A version of HttpRequest that allows us to change some things @@ -47,6 +51,7 @@ class TestingHttpRequest(HttpRequest): def is_secure(self): return getattr(self, '_is_secure_override', False) + class CsrfViewMiddlewareTest(TestCase): # The csrf token is potentially from an untrusted source, so could have # characters that need dealing with. diff --git a/tests/custom_columns/models.py b/tests/custom_columns/models.py index 2549dde749..df1e743be9 100644 --- a/tests/custom_columns/models.py +++ b/tests/custom_columns/models.py @@ -33,6 +33,7 @@ class Author(models.Model): db_table = 'my_author_table' ordering = ('last_name', 'first_name') + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100) diff --git a/tests/custom_columns_regress/models.py b/tests/custom_columns_regress/models.py index e848b8ec23..1c026a44c0 100644 --- a/tests/custom_columns_regress/models.py +++ b/tests/custom_columns_regress/models.py @@ -24,6 +24,7 @@ class Article(models.Model): class Meta: ordering = ('headline',) + @python_2_unicode_compatible class Author(models.Model): Author_ID = models.AutoField(primary_key=True, db_column='Author ID') diff --git a/tests/custom_columns_regress/tests.py b/tests/custom_columns_regress/tests.py index 034de08d45..24297b9fa5 100644 --- a/tests/custom_columns_regress/tests.py +++ b/tests/custom_columns_regress/tests.py @@ -10,6 +10,7 @@ def pks(objects): """ Return pks to be able to compare lists""" return [o.pk for o in objects] + class CustomColumnRegression(TestCase): def setUp(self): diff --git a/tests/custom_managers/models.py b/tests/custom_managers/models.py index 26d848b7c0..c6a99620e9 100644 --- a/tests/custom_managers/models.py +++ b/tests/custom_managers/models.py @@ -17,18 +17,21 @@ from django.utils.encoding import python_2_unicode_compatible # An example of a custom manager called "objects". + class PersonManager(models.Manager): def get_fun_people(self): return self.filter(fun=True) # An example of a custom manager that sets get_queryset(). + class PublishedBookManager(models.Manager): def get_queryset(self): return super(PublishedBookManager, self).get_queryset().filter(is_published=True) # An example of a custom queryset that copies its methods onto the manager. + class CustomQuerySet(models.QuerySet): def filter(self, *args, **kwargs): queryset = super(CustomQuerySet, self).filter(fun=True) @@ -49,6 +52,7 @@ class CustomQuerySet(models.QuerySet): return self.all() _optin_private_method.queryset_only = False + class BaseCustomManager(models.Manager): def __init__(self, arg): super(BaseCustomManager, self).__init__() @@ -64,14 +68,17 @@ class BaseCustomManager(models.Manager): CustomManager = BaseCustomManager.from_queryset(CustomQuerySet) + class FunPeopleManager(models.Manager): def get_queryset(self): return super(FunPeopleManager, self).get_queryset().filter(fun=True) + class BoringPeopleManager(models.Manager): def get_queryset(self): return super(BoringPeopleManager, self).get_queryset().filter(fun=False) + @python_2_unicode_compatible class Person(models.Model): first_name = models.CharField(max_length=30) @@ -93,6 +100,7 @@ class Person(models.Model): def __str__(self): return "%s %s" % (self.first_name, self.last_name) + @python_2_unicode_compatible class Book(models.Model): title = models.CharField(max_length=50) @@ -109,10 +117,12 @@ class Book(models.Model): # An example of providing multiple custom managers. + class FastCarManager(models.Manager): def get_queryset(self): return super(FastCarManager, self).get_queryset().filter(top_speed__gt=150) + @python_2_unicode_compatible class Car(models.Model): name = models.CharField(max_length=10) diff --git a/tests/custom_managers_regress/models.py b/tests/custom_managers_regress/models.py index 95cf6e8ca1..eda711f8d7 100644 --- a/tests/custom_managers_regress/models.py +++ b/tests/custom_managers_regress/models.py @@ -13,6 +13,7 @@ class RestrictedManager(models.Manager): def get_queryset(self): return super(RestrictedManager, self).get_queryset().filter(is_public=True) + @python_2_unicode_compatible class RelatedModel(models.Model): name = models.CharField(max_length=50) @@ -20,6 +21,7 @@ class RelatedModel(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class RestrictedModel(models.Model): name = models.CharField(max_length=50) @@ -32,6 +34,7 @@ class RestrictedModel(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class OneToOneRestrictedModel(models.Model): name = models.CharField(max_length=50) diff --git a/tests/custom_pk/fields.py b/tests/custom_pk/fields.py index 92096a0ff7..2aa3bad963 100644 --- a/tests/custom_pk/fields.py +++ b/tests/custom_pk/fields.py @@ -22,6 +22,7 @@ class MyWrapper(object): return self.value == other.value return self.value == other + class MyAutoField(six.with_metaclass(models.SubfieldBase, models.CharField)): def __init__(self, *args, **kwargs): diff --git a/tests/custom_pk/models.py b/tests/custom_pk/models.py index 5fffb84641..bfa6777b10 100644 --- a/tests/custom_pk/models.py +++ b/tests/custom_pk/models.py @@ -16,7 +16,7 @@ from django.utils.encoding import python_2_unicode_compatible @python_2_unicode_compatible class Employee(models.Model): - employee_code = models.IntegerField(primary_key=True, db_column = 'code') + employee_code = models.IntegerField(primary_key=True, db_column='code') first_name = models.CharField(max_length=20) last_name = models.CharField(max_length=20) @@ -26,6 +26,7 @@ class Employee(models.Model): def __str__(self): return "%s %s" % (self.first_name, self.last_name) + @python_2_unicode_compatible class Business(models.Model): name = models.CharField(max_length=20, primary_key=True) @@ -37,6 +38,7 @@ class Business(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Bar(models.Model): id = MyAutoField(primary_key=True, db_index=True) diff --git a/tests/datatypes/models.py b/tests/datatypes/models.py index 8e6027dd0f..cabe5297bd 100644 --- a/tests/datatypes/models.py +++ b/tests/datatypes/models.py @@ -23,6 +23,7 @@ class Donut(models.Model): def __str__(self): return self.name + class RumBaba(models.Model): baked_date = models.DateField(auto_now_add=True) baked_timestamp = models.DateTimeField(auto_now_add=True) diff --git a/tests/dates/models.py b/tests/dates/models.py index 23350755e7..d27c22ff67 100644 --- a/tests/dates/models.py +++ b/tests/dates/models.py @@ -14,6 +14,7 @@ class Article(models.Model): def __str__(self): return self.title + @python_2_unicode_compatible class Comment(models.Model): article = models.ForeignKey(Article, related_name="comments") @@ -24,5 +25,6 @@ class Comment(models.Model): def __str__(self): return 'Comment to %s (%s)' % (self.article.title, self.pub_date) + class Category(models.Model): name = models.CharField(max_length=255) diff --git a/tests/datetimes/models.py b/tests/datetimes/models.py index f21376aa1c..cfdd521b53 100644 --- a/tests/datetimes/models.py +++ b/tests/datetimes/models.py @@ -14,6 +14,7 @@ class Article(models.Model): def __str__(self): return self.title + @python_2_unicode_compatible class Comment(models.Model): article = models.ForeignKey(Article, related_name="comments") @@ -24,5 +25,6 @@ class Comment(models.Model): def __str__(self): return 'Comment to %s (%s)' % (self.article.title, self.pub_date) + class Category(models.Model): name = models.CharField(max_length=255) diff --git a/tests/db_typecasts/tests.py b/tests/db_typecasts/tests.py index 27b89c0c8c..e391743028 100644 --- a/tests/db_typecasts/tests.py +++ b/tests/db_typecasts/tests.py @@ -48,6 +48,7 @@ TEST_CASES = { ), } + class DBTypeCasts(unittest.TestCase): def test_typeCasts(self): for k, v in six.iteritems(TEST_CASES): diff --git a/tests/defer_regress/tests.py b/tests/defer_regress/tests.py index ffb47a8133..c03388b50e 100644 --- a/tests/defer_regress/tests.py +++ b/tests/defer_regress/tests.py @@ -245,6 +245,7 @@ class DeferRegressionTest(TestCase): new_class.__name__, 'Item_Deferred_this_is_some_very_long_attribute_nac34b1f495507dad6b02e2cb235c875e') + class DeferAnnotateSelectRelatedTest(TestCase): def test_defer_annotate_select_related(self): location = Location.objects.create() diff --git a/tests/delete/models.py b/tests/delete/models.py index 65d4e6f725..408b6b83f8 100644 --- a/tests/delete/models.py +++ b/tests/delete/models.py @@ -109,20 +109,26 @@ class HiddenUser(models.Model): class HiddenUserProfile(models.Model): user = models.ForeignKey(HiddenUser) + class M2MTo(models.Model): pass + class M2MFrom(models.Model): m2m = models.ManyToManyField(M2MTo) + class Parent(models.Model): pass + class Child(Parent): pass + class Base(models.Model): pass + class RelToBase(models.Model): base = models.ForeignKey(Base, on_delete=models.DO_NOTHING) diff --git a/tests/delete/tests.py b/tests/delete/tests.py index 7bef83a670..6ecdb01e65 100644 --- a/tests/delete/tests.py +++ b/tests/delete/tests.py @@ -167,7 +167,7 @@ class DeletionTests(TestCase): def test_bulk(self): from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE s = S.objects.create(r=R.objects.create()) - for i in xrange(2*GET_ITERATOR_CHUNK_SIZE): + for i in xrange(2 * GET_ITERATOR_CHUNK_SIZE): T.objects.create(s=s) # 1 (select related `T` instances) # + 1 (select related `U` instances) @@ -311,6 +311,7 @@ class DeletionTests(TestCase): r.delete() self.assertEqual(HiddenUserProfile.objects.count(), 0) + class FastDeleteTests(TestCase): def test_fast_delete_fk(self): diff --git a/tests/delete_regress/models.py b/tests/delete_regress/models.py index 3632a7dbc1..033689519a 100644 --- a/tests/delete_regress/models.py +++ b/tests/delete_regress/models.py @@ -2,51 +2,64 @@ from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType from django.db import models + class Award(models.Model): name = models.CharField(max_length=25) object_id = models.PositiveIntegerField() content_type = models.ForeignKey(ContentType) content_object = generic.GenericForeignKey() + class AwardNote(models.Model): award = models.ForeignKey(Award) note = models.CharField(max_length=100) + class Person(models.Model): name = models.CharField(max_length=25) awards = generic.GenericRelation(Award) + class Book(models.Model): pagecount = models.IntegerField() + class Toy(models.Model): name = models.CharField(max_length=50) + class Child(models.Model): name = models.CharField(max_length=50) toys = models.ManyToManyField(Toy, through='PlayedWith') + class PlayedWith(models.Model): child = models.ForeignKey(Child) toy = models.ForeignKey(Toy) date = models.DateField(db_column='date_col') + class PlayedWithNote(models.Model): played = models.ForeignKey(PlayedWith) note = models.TextField() + class Contact(models.Model): label = models.CharField(max_length=100) + class Email(Contact): email_address = models.EmailField(max_length=100) + class Researcher(models.Model): contacts = models.ManyToManyField(Contact, related_name="research_contacts") + class Food(models.Model): name = models.CharField(max_length=20, unique=True) + class Eaten(models.Model): food = models.ForeignKey(Food, to_field="name") meal = models.CharField(max_length=20) @@ -54,55 +67,70 @@ class Eaten(models.Model): # Models for #15776 + class Policy(models.Model): policy_number = models.CharField(max_length=10) + class Version(models.Model): policy = models.ForeignKey(Policy) + class Location(models.Model): version = models.ForeignKey(Version, blank=True, null=True) + class Item(models.Model): version = models.ForeignKey(Version) location = models.ForeignKey(Location, blank=True, null=True) # Models for #16128 + class File(models.Model): pass + class Image(File): class Meta: proxy = True + class Photo(Image): class Meta: proxy = True + class FooImage(models.Model): my_image = models.ForeignKey(Image) + class FooFile(models.Model): my_file = models.ForeignKey(File) + class FooPhoto(models.Model): my_photo = models.ForeignKey(Photo) + class FooFileProxy(FooFile): class Meta: proxy = True + class OrgUnit(models.Model): name = models.CharField(max_length=64, unique=True) + class Login(models.Model): description = models.CharField(max_length=32) orgunit = models.ForeignKey(OrgUnit) + class House(models.Model): address = models.CharField(max_length=32) + class OrderedPerson(models.Model): name = models.CharField(max_length=32) lives_in = models.ForeignKey(House) diff --git a/tests/delete_regress/tests.py b/tests/delete_regress/tests.py index ecc754920c..e1cbe7070f 100644 --- a/tests/delete_regress/tests.py +++ b/tests/delete_regress/tests.py @@ -146,7 +146,7 @@ class LargeDeleteTests(TestCase): def test_large_deletes(self): "Regression for #13309 -- if the number of objects > chunk size, deletion still occurs" for x in range(300): - Book.objects.create(pagecount=x+100) + Book.objects.create(pagecount=x + 100) # attach a signal to make sure we will not fast-delete def noop(*args, **kwargs): @@ -268,6 +268,7 @@ class ProxyDeleteTest(TestCase): with self.assertRaises(TypeError): Image.objects.values_list().delete() + class Ticket19102Tests(TestCase): """ Test different queries which alter the SELECT clause of the query. We diff --git a/tests/dispatch/tests/test_dispatcher.py b/tests/dispatch/tests/test_dispatcher.py index 9a8d7146cf..1ab4a69d33 100644 --- a/tests/dispatch/tests/test_dispatcher.py +++ b/tests/dispatch/tests/test_dispatcher.py @@ -23,9 +23,11 @@ else: def garbage_collect(): gc.collect() + def receiver_1_arg(val, **kwargs): return val + class Callable(object): def __call__(self, val, **kwargs): return val @@ -116,10 +118,10 @@ class DispatcherTests(unittest.TestCase): def uid_based_receiver_2(**kwargs): pass - a_signal.connect(uid_based_receiver_1, dispatch_uid = "uid") - a_signal.connect(uid_based_receiver_2, dispatch_uid = "uid") + a_signal.connect(uid_based_receiver_1, dispatch_uid="uid") + a_signal.connect(uid_based_receiver_2, dispatch_uid="uid") self.assertEqual(len(a_signal.receivers), 1) - a_signal.disconnect(dispatch_uid = "uid") + a_signal.disconnect(dispatch_uid="uid") self._testIsClean(a_signal) def testRobust(self): diff --git a/tests/dispatch/tests/test_saferef.py b/tests/dispatch/tests/test_saferef.py index 531e8f43de..6da756362a 100644 --- a/tests/dispatch/tests/test_saferef.py +++ b/tests/dispatch/tests/test_saferef.py @@ -3,17 +3,21 @@ import unittest from django.dispatch.saferef import safeRef from django.utils.six.moves import xrange + class Test1(object): def x(self): pass + def test2(obj): pass + class Test2(object): def __call__(self, obj): pass + class SaferefTests(unittest.TestCase): def setUp(self): ts = [] diff --git a/tests/distinct_on_fields/models.py b/tests/distinct_on_fields/models.py index 7982f435d0..053fd9cc5f 100644 --- a/tests/distinct_on_fields/models.py +++ b/tests/distinct_on_fields/models.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.db import models from django.utils.encoding import python_2_unicode_compatible + @python_2_unicode_compatible class Tag(models.Model): name = models.CharField(max_length=10) @@ -15,6 +16,7 @@ class Tag(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Celebrity(models.Model): name = models.CharField("Name", max_length=20) @@ -23,9 +25,11 @@ class Celebrity(models.Model): def __str__(self): return self.name + class Fan(models.Model): fan_of = models.ForeignKey(Celebrity) + @python_2_unicode_compatible class Staff(models.Model): id = models.IntegerField(primary_key=True) @@ -37,6 +41,7 @@ class Staff(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class StaffTag(models.Model): staff = models.ForeignKey(Staff) diff --git a/tests/distinct_on_fields/tests.py b/tests/distinct_on_fields/tests.py index e14f06f2ed..9dedd98f81 100644 --- a/tests/distinct_on_fields/tests.py +++ b/tests/distinct_on_fields/tests.py @@ -6,6 +6,7 @@ from django.test.utils import str_prefix from .models import Tag, Celebrity, Fan, Staff, StaffTag + @skipUnlessDBFeature('can_distinct_on_fields') class DistinctOnTests(TestCase): def setUp(self): @@ -77,7 +78,7 @@ class DistinctOnTests(TestCase): # Fetch the alphabetically first coworker for each worker ( (Staff.objects.distinct('id').order_by('id', 'coworkers__name'). - values_list('id', 'coworkers__name')), + values_list('id', 'coworkers__name')), [str_prefix("(1, %(_)s'p2')"), str_prefix("(2, %(_)s'p1')"), str_prefix("(3, %(_)s'p1')"), "(4, None)"] ), diff --git a/tests/expressions/models.py b/tests/expressions/models.py index f592a0eb13..e66bb0a135 100644 --- a/tests/expressions/models.py +++ b/tests/expressions/models.py @@ -15,6 +15,7 @@ class Employee(models.Model): def __str__(self): return '%s %s' % (self.firstname, self.lastname) + @python_2_unicode_compatible class Company(models.Model): name = models.CharField(max_length=100) diff --git a/tests/expressions_regress/models.py b/tests/expressions_regress/models.py index bd3e52f54d..c70338933a 100644 --- a/tests/expressions_regress/models.py +++ b/tests/expressions_regress/models.py @@ -14,6 +14,7 @@ class Number(models.Model): def __str__(self): return '%i, %.3f' % (self.integer, self.float) + class Experiment(models.Model): name = models.CharField(max_length=24) assigned = models.DateField() diff --git a/tests/expressions_regress/tests.py b/tests/expressions_regress/tests.py index 0e168e924a..e603c410ac 100644 --- a/tests/expressions_regress/tests.py +++ b/tests/expressions_regress/tests.py @@ -79,12 +79,12 @@ class ExpressionsRegressTests(TestCase): """ n = Number.objects.create(integer=10, float=123.45) self.assertEqual(Number.objects.filter(pk=n.pk) - .update(float=F('integer') + F('float') * 2), - 1) + .update(float=F('integer') + F('float') * 2), 1) self.assertEqual(Number.objects.get(pk=n.pk).integer, 10) self.assertEqual(Number.objects.get(pk=n.pk).float, Approximate(256.900, places=3)) + class ExpressionOperatorTests(TestCase): def setUp(self): self.n = Number.objects.create(integer=42, float=15.5) @@ -220,13 +220,13 @@ class FTimeDeltaTests(TestCase): self.days_long = [] # e0: started same day as assigned, zero duration - end = stime+delta0 + end = stime + delta0 e0 = Experiment.objects.create(name='e0', assigned=sday, start=stime, end=end, completed=end.date()) self.deltas.append(delta0) self.delays.append(e0.start - datetime.datetime.combine(e0.assigned, midnight)) - self.days_long.append(e0.completed-e0.assigned) + self.days_long.append(e0.completed - e0.assigned) # e1: started one day after assigned, tiny duration, data # set so that end time has no fractional seconds, which @@ -237,86 +237,86 @@ class FTimeDeltaTests(TestCase): delay = datetime.timedelta(1) end = stime + delay + delta1 e1 = Experiment.objects.create(name='e1', assigned=sday, - start=stime+delay, end=end, completed=end.date()) + start=stime + delay, end=end, completed=end.date()) self.deltas.append(delta1) self.delays.append(e1.start - datetime.datetime.combine(e1.assigned, midnight)) - self.days_long.append(e1.completed-e1.assigned) + self.days_long.append(e1.completed - e1.assigned) # e2: started three days after assigned, small duration - end = stime+delta2 + end = stime + delta2 e2 = Experiment.objects.create(name='e2', - assigned=sday-datetime.timedelta(3), start=stime, end=end, + assigned=sday - datetime.timedelta(3), start=stime, end=end, completed=end.date()) self.deltas.append(delta2) self.delays.append(e2.start - datetime.datetime.combine(e2.assigned, midnight)) - self.days_long.append(e2.completed-e2.assigned) + self.days_long.append(e2.completed - e2.assigned) # e3: started four days after assigned, medium duration delay = datetime.timedelta(4) end = stime + delay + delta3 e3 = Experiment.objects.create(name='e3', - assigned=sday, start=stime+delay, end=end, completed=end.date()) + assigned=sday, start=stime + delay, end=end, completed=end.date()) self.deltas.append(delta3) self.delays.append(e3.start - datetime.datetime.combine(e3.assigned, midnight)) - self.days_long.append(e3.completed-e3.assigned) + self.days_long.append(e3.completed - e3.assigned) # e4: started 10 days after assignment, long duration end = stime + delta4 e4 = Experiment.objects.create(name='e4', - assigned=sday-datetime.timedelta(10), start=stime, end=end, + assigned=sday - datetime.timedelta(10), start=stime, end=end, completed=end.date()) self.deltas.append(delta4) self.delays.append(e4.start - datetime.datetime.combine(e4.assigned, midnight)) - self.days_long.append(e4.completed-e4.assigned) + self.days_long.append(e4.completed - e4.assigned) self.expnames = [e.name for e in Experiment.objects.all()] def test_delta_add(self): for i in range(len(self.deltas)): delta = self.deltas[i] test_set = [e.name for e in - Experiment.objects.filter(end__lt=F('start')+delta)] + Experiment.objects.filter(end__lt=F('start') + delta)] self.assertEqual(test_set, self.expnames[:i]) test_set = [e.name for e in - Experiment.objects.filter(end__lte=F('start')+delta)] - self.assertEqual(test_set, self.expnames[:i+1]) + Experiment.objects.filter(end__lte=F('start') + delta)] + self.assertEqual(test_set, self.expnames[:i + 1]) def test_delta_subtract(self): for i in range(len(self.deltas)): delta = self.deltas[i] test_set = [e.name for e in - Experiment.objects.filter(start__gt=F('end')-delta)] + Experiment.objects.filter(start__gt=F('end') - delta)] self.assertEqual(test_set, self.expnames[:i]) test_set = [e.name for e in - Experiment.objects.filter(start__gte=F('end')-delta)] - self.assertEqual(test_set, self.expnames[:i+1]) + Experiment.objects.filter(start__gte=F('end') - delta)] + self.assertEqual(test_set, self.expnames[:i + 1]) def test_exclude(self): for i in range(len(self.deltas)): delta = self.deltas[i] test_set = [e.name for e in - Experiment.objects.exclude(end__lt=F('start')+delta)] + Experiment.objects.exclude(end__lt=F('start') + delta)] self.assertEqual(test_set, self.expnames[i:]) test_set = [e.name for e in - Experiment.objects.exclude(end__lte=F('start')+delta)] - self.assertEqual(test_set, self.expnames[i+1:]) + Experiment.objects.exclude(end__lte=F('start') + delta)] + self.assertEqual(test_set, self.expnames[i + 1:]) def test_date_comparison(self): for i in range(len(self.days_long)): days = self.days_long[i] test_set = [e.name for e in - Experiment.objects.filter(completed__lt=F('assigned')+days)] + Experiment.objects.filter(completed__lt=F('assigned') + days)] self.assertEqual(test_set, self.expnames[:i]) test_set = [e.name for e in - Experiment.objects.filter(completed__lte=F('assigned')+days)] - self.assertEqual(test_set, self.expnames[:i+1]) + Experiment.objects.filter(completed__lte=F('assigned') + days)] + self.assertEqual(test_set, self.expnames[:i + 1]) @skipUnlessDBFeature("supports_mixed_date_datetime_comparisons") def test_mixed_comparisons1(self): @@ -325,35 +325,35 @@ class FTimeDeltaTests(TestCase): if not connection.features.supports_microsecond_precision: delay = datetime.timedelta(delay.days, delay.seconds) test_set = [e.name for e in - Experiment.objects.filter(assigned__gt=F('start')-delay)] + Experiment.objects.filter(assigned__gt=F('start') - delay)] self.assertEqual(test_set, self.expnames[:i]) test_set = [e.name for e in - Experiment.objects.filter(assigned__gte=F('start')-delay)] - self.assertEqual(test_set, self.expnames[:i+1]) + Experiment.objects.filter(assigned__gte=F('start') - delay)] + self.assertEqual(test_set, self.expnames[:i + 1]) def test_mixed_comparisons2(self): delays = [datetime.timedelta(delay.days) for delay in self.delays] for i in range(len(delays)): delay = delays[i] test_set = [e.name for e in - Experiment.objects.filter(start__lt=F('assigned')+delay)] + Experiment.objects.filter(start__lt=F('assigned') + delay)] self.assertEqual(test_set, self.expnames[:i]) test_set = [e.name for e in Experiment.objects.filter(start__lte=F('assigned') + delay + datetime.timedelta(1))] - self.assertEqual(test_set, self.expnames[:i+1]) + self.assertEqual(test_set, self.expnames[:i + 1]) def test_delta_update(self): for i in range(len(self.deltas)): delta = self.deltas[i] exps = Experiment.objects.all() expected_durations = [e.duration() for e in exps] - expected_starts = [e.start+delta for e in exps] - expected_ends = [e.end+delta for e in exps] + expected_starts = [e.start + delta for e in exps] + expected_ends = [e.end + delta for e in exps] - Experiment.objects.update(start=F('start')+delta, end=F('end')+delta) + Experiment.objects.update(start=F('start') + delta, end=F('end') + delta) exps = Experiment.objects.all() new_starts = [e.start for e in exps] new_ends = [e.end for e in exps] @@ -365,7 +365,7 @@ class FTimeDeltaTests(TestCase): def test_delta_invalid_op_mult(self): raised = False try: - repr(Experiment.objects.filter(end__lt=F('start')*self.deltas[0])) + repr(Experiment.objects.filter(end__lt=F('start') * self.deltas[0])) except TypeError: raised = True self.assertTrue(raised, "TypeError not raised on attempt to multiply datetime by timedelta.") @@ -373,7 +373,7 @@ class FTimeDeltaTests(TestCase): def test_delta_invalid_op_div(self): raised = False try: - repr(Experiment.objects.filter(end__lt=F('start')/self.deltas[0])) + repr(Experiment.objects.filter(end__lt=F('start') / self.deltas[0])) except TypeError: raised = True self.assertTrue(raised, "TypeError not raised on attempt to divide datetime by timedelta.") diff --git a/tests/extra_regress/models.py b/tests/extra_regress/models.py index 5523a06a8a..432aa02963 100644 --- a/tests/extra_regress/models.py +++ b/tests/extra_regress/models.py @@ -30,10 +30,12 @@ class RevisionableModel(models.Model): new_revision.pk = None return new_revision + class Order(models.Model): created_by = models.ForeignKey(User) text = models.TextField() + @python_2_unicode_compatible class TestObject(models.Model): first = models.CharField(max_length=20) diff --git a/tests/field_subclassing/fields.py b/tests/field_subclassing/fields.py index a3867e3671..e9c7a982e8 100644 --- a/tests/field_subclassing/fields.py +++ b/tests/field_subclassing/fields.py @@ -20,6 +20,7 @@ class Small(object): def __str__(self): return '%s%s' % (force_text(self.first), force_text(self.second)) + class SmallField(six.with_metaclass(models.SubfieldBase, models.Field)): """ Turns the "Small" class into a Django field. Because of the similarities @@ -51,6 +52,7 @@ class SmallField(six.with_metaclass(models.SubfieldBase, models.Field)): return [] raise TypeError('Invalid lookup type: %r' % lookup_type) + class SmallerField(SmallField): pass diff --git a/tests/field_subclassing/models.py b/tests/field_subclassing/models.py index 67a95b02f2..c2f7e4f66b 100644 --- a/tests/field_subclassing/models.py +++ b/tests/field_subclassing/models.py @@ -17,8 +17,10 @@ class MyModel(models.Model): def __str__(self): return force_text(self.name) + class OtherModel(models.Model): data = SmallerField() + class DataModel(models.Model): data = JSONField() diff --git a/tests/file_storage/models.py b/tests/file_storage/models.py index eea3ddaf09..738a3a1772 100644 --- a/tests/file_storage/models.py +++ b/tests/file_storage/models.py @@ -15,6 +15,7 @@ from django.core.files.storage import FileSystemStorage temp_storage_location = tempfile.mkdtemp() temp_storage = FileSystemStorage(location=temp_storage_location) + class Storage(models.Model): def custom_upload_to(self, filename): return 'foo' diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py index 1f676d04b1..20eaf4c89c 100644 --- a/tests/file_storage/tests.py +++ b/tests/file_storage/tests.py @@ -69,6 +69,7 @@ class GetStorageClassTests(SimpleTestCase): get_storage_class( 'django.core.files.non_existing_storage.NonExistingStorage') + class FileStorageTests(unittest.TestCase): storage_class = FileSystemStorage @@ -379,6 +380,7 @@ class CustomStorage(FileSystemStorage): return name + class CustomStorageTests(FileStorageTests): storage_class = CustomStorage @@ -531,6 +533,7 @@ class SlowFile(ContentFile): time.sleep(1) return super(ContentFile, self).chunks() + class FileSaveRaceConditionTest(unittest.TestCase): def setUp(self): self.storage_dir = tempfile.mkdtemp() @@ -552,6 +555,7 @@ class FileSaveRaceConditionTest(unittest.TestCase): self.storage.delete('conflict') self.storage.delete('conflict_1') + @unittest.skipIf(sys.platform.startswith('win'), "Windows only partially supports umasks and chmod.") class FileStoragePermissions(unittest.TestCase): def setUp(self): @@ -591,6 +595,7 @@ class FileStoragePermissions(unittest.TestCase): dir_mode = os.stat(os.path.dirname(self.storage.path(name)))[0] & 0o777 self.assertEqual(dir_mode, 0o777 & ~self.umask) + class FileStoragePathParsing(unittest.TestCase): def setUp(self): self.storage_dir = tempfile.mkdtemp() diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py index 72f9d7a77c..7aa6797630 100644 --- a/tests/file_uploads/tests.py +++ b/tests/file_uploads/tests.py @@ -397,6 +397,7 @@ class FileUploadTests(TestCase): # shouldn't differ. self.assertEqual(os.path.basename(obj.testfile.path), 'MiXeD_cAsE.txt') + @override_settings(MEDIA_ROOT=MEDIA_ROOT) class DirectoryCreationTests(TestCase): """ @@ -436,7 +437,7 @@ class DirectoryCreationTests(TestCase): # The test needs to be done on a specific string as IOError # is raised even without the patch (just not early enough) self.assertEqual(exc_info.exception.args[0], - "%s exists and is not a directory." % UPLOAD_TO) + "%s exists and is not a directory." % UPLOAD_TO) class MultiParserTests(unittest.TestCase): diff --git a/tests/file_uploads/uploadhandler.py b/tests/file_uploads/uploadhandler.py index 2d4e52e4d5..b69cc751cb 100644 --- a/tests/file_uploads/uploadhandler.py +++ b/tests/file_uploads/uploadhandler.py @@ -11,7 +11,7 @@ class QuotaUploadHandler(FileUploadHandler): (5MB) is uploaded. """ - QUOTA = 5 * 2**20 # 5 MB + QUOTA = 5 * 2 ** 20 # 5 MB def __init__(self, request=None): super(QuotaUploadHandler, self).__init__(request) @@ -26,9 +26,11 @@ class QuotaUploadHandler(FileUploadHandler): def file_complete(self, file_size): return None + class CustomUploadError(Exception): pass + class ErroringUploadHandler(FileUploadHandler): """A handler that raises an exception.""" def receive_data_chunk(self, raw_data, start): diff --git a/tests/file_uploads/views.py b/tests/file_uploads/views.py index 1940987815..a29391af6e 100644 --- a/tests/file_uploads/views.py +++ b/tests/file_uploads/views.py @@ -30,6 +30,7 @@ def file_upload_view(request): else: return HttpResponseServerError() + def file_upload_view_verify(request): """ Use the sha digest hash to verify the uploaded contents. @@ -57,6 +58,7 @@ def file_upload_view_verify(request): return HttpResponse('') + def file_upload_unicode_name(request): # Check to see if unicode name came through properly. @@ -85,6 +87,7 @@ def file_upload_unicode_name(request): else: return HttpResponse('') + def file_upload_echo(request): """ Simple view to echo back info about uploaded files for tests. @@ -92,6 +95,7 @@ def file_upload_echo(request): r = dict((k, f.name) for k, f in request.FILES.items()) return HttpResponse(json.dumps(r)) + def file_upload_echo_content(request): """ Simple view to echo back the content of uploaded files for tests. @@ -99,6 +103,7 @@ def file_upload_echo_content(request): r = dict((k, f.read().decode('utf-8')) for k, f in request.FILES.items()) return HttpResponse(json.dumps(r)) + def file_upload_quota(request): """ Dynamically add in an upload handler. @@ -106,6 +111,7 @@ def file_upload_quota(request): request.upload_handlers.insert(0, QuotaUploadHandler()) return file_upload_echo(request) + def file_upload_quota_broken(request): """ You can't change handlers after reading FILES; this view shouldn't work. @@ -114,6 +120,7 @@ def file_upload_quota_broken(request): request.upload_handlers.insert(0, QuotaUploadHandler()) return response + def file_upload_getlist_count(request): """ Check the .getlist() function to ensure we receive the correct number of files. @@ -124,10 +131,12 @@ def file_upload_getlist_count(request): file_counts[key] = len(request.FILES.getlist(key)) return HttpResponse(json.dumps(file_counts)) + def file_upload_errors(request): request.upload_handlers.insert(0, ErroringUploadHandler()) return file_upload_echo(request) + def file_upload_filename_case_view(request): """ Check adding the file to the database will preserve the filename case. @@ -137,6 +146,7 @@ def file_upload_filename_case_view(request): obj.testfile.save(file.name, file) return HttpResponse('%d' % obj.pk) + def file_upload_content_type_extra(request): """ Simple view to echo back extra content-type parameters. diff --git a/tests/fixtures/models.py b/tests/fixtures/models.py index 56bb601c27..08cb02ce72 100644 --- a/tests/fixtures/models.py +++ b/tests/fixtures/models.py @@ -26,6 +26,7 @@ class Category(models.Model): class Meta: ordering = ('title',) + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100, default='Default headline') @@ -37,6 +38,7 @@ class Article(models.Model): class Meta: ordering = ('-pub_date', 'headline') + @python_2_unicode_compatible class Blog(models.Model): name = models.CharField(max_length=100) @@ -60,10 +62,12 @@ class Tag(models.Model): return '<%s: %s> tagged "%s"' % (self.tagged.__class__.__name__, self.tagged, self.name) + class PersonManager(models.Manager): def get_by_natural_key(self, name): return self.get(name=name) + @python_2_unicode_compatible class Person(models.Model): objects = PersonManager() @@ -78,14 +82,17 @@ class Person(models.Model): def natural_key(self): return (self.name,) + class SpyManager(PersonManager): def get_queryset(self): return super(SpyManager, self).get_queryset().filter(cover_blown=False) + class Spy(Person): objects = SpyManager() cover_blown = models.BooleanField(default=False) + @python_2_unicode_compatible class Visa(models.Model): person = models.ForeignKey(Person) @@ -95,6 +102,7 @@ class Visa(models.Model): return '%s %s' % (self.person.name, ', '.join(p.name for p in self.permissions.all())) + @python_2_unicode_compatible class Book(models.Model): name = models.CharField(max_length=100) diff --git a/tests/fixtures_model_package/models/__init__.py b/tests/fixtures_model_package/models/__init__.py index deeba48aa9..c48cfd451d 100644 --- a/tests/fixtures_model_package/models/__init__.py +++ b/tests/fixtures_model_package/models/__init__.py @@ -14,6 +14,7 @@ class Article(models.Model): app_label = 'fixtures_model_package' ordering = ('-pub_date', 'headline') + class Book(models.Model): name = models.CharField(max_length=100) diff --git a/tests/fixtures_regress/models.py b/tests/fixtures_regress/models.py index 4b33cef09b..95f9488ab7 100644 --- a/tests/fixtures_regress/models.py +++ b/tests/fixtures_regress/models.py @@ -27,6 +27,7 @@ class Plant(models.Model): # For testing when upper case letter in app name; regression for #4057 db_table = "Fixtures_regress_plant" + @python_2_unicode_compatible class Stuff(models.Model): name = models.CharField(max_length=20, null=True) diff --git a/tests/force_insert_update/models.py b/tests/force_insert_update/models.py index 56d6624e0d..7067613ccd 100644 --- a/tests/force_insert_update/models.py +++ b/tests/force_insert_update/models.py @@ -9,16 +9,20 @@ class Counter(models.Model): name = models.CharField(max_length = 10) value = models.IntegerField() + class InheritedCounter(Counter): tag = models.CharField(max_length=10) + class ProxyCounter(Counter): class Meta: proxy = True + class SubCounter(Counter): pass + class WithCustomPK(models.Model): name = models.IntegerField(primary_key=True) value = models.IntegerField() diff --git a/tests/foreign_object/models.py b/tests/foreign_object/models.py index d8c3bc10d4..7673d27af6 100644 --- a/tests/foreign_object/models.py +++ b/tests/foreign_object/models.py @@ -5,6 +5,7 @@ from django.db.models.fields.related import ReverseSingleRelatedObjectDescriptor from django.utils.encoding import python_2_unicode_compatible from django.utils.translation import get_language + @python_2_unicode_compatible class Country(models.Model): # Table Column Fields @@ -13,6 +14,7 @@ class Country(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Person(models.Model): # Table Column Fields @@ -30,6 +32,7 @@ class Person(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Group(models.Model): # Table Column Fields @@ -96,6 +99,7 @@ class Friendship(models.Model): to_fields=['person_country_id', 'id'], related_name='to_friend') + class ArticleTranslationDescriptor(ReverseSingleRelatedObjectDescriptor): """ The set of articletranslation should not set any local fields. @@ -107,6 +111,7 @@ class ArticleTranslationDescriptor(ReverseSingleRelatedObjectDescriptor): if value is not None and not self.field.rel.multiple: setattr(value, self.field.related.get_cache_name(), instance) + class ColConstraint(object): # Antyhing with as_sql() method works in get_extra_restriction(). def __init__(self, alias, col, value): @@ -115,6 +120,7 @@ class ColConstraint(object): def as_sql(self, qn, connection): return '%s.%s = %%s' % (qn(self.alias), qn(self.col)), [self.value] + class ActiveTranslationField(models.ForeignObject): """ This field will allow querying and fetching the currently active translation @@ -132,6 +138,7 @@ class ActiveTranslationField(models.ForeignObject): super(ActiveTranslationField, self).contribute_to_class(cls, name) setattr(cls, self.name, ArticleTranslationDescriptor(self)) + @python_2_unicode_compatible class Article(models.Model): active_translation = ActiveTranslationField( @@ -148,9 +155,11 @@ class Article(models.Model): except ArticleTranslation.DoesNotExist: return '[No translation found]' + class NewsArticle(Article): pass + class ArticleTranslation(models.Model): article = models.ForeignKey(Article) lang = models.CharField(max_length='2') @@ -162,10 +171,12 @@ class ArticleTranslation(models.Model): unique_together = ('article', 'lang') ordering = ('active_translation__title',) + class ArticleTag(models.Model): article = models.ForeignKey(Article, related_name="tags", related_query_name="tag") name = models.CharField(max_length=255) + class ArticleIdea(models.Model): articles = models.ManyToManyField(Article, related_name="ideas", related_query_name="idea_things") diff --git a/tests/foreign_object/tests.py b/tests/foreign_object/tests.py index 77582162a8..66f57b6f3c 100644 --- a/tests/foreign_object/tests.py +++ b/tests/foreign_object/tests.py @@ -12,6 +12,7 @@ from django import forms # Note that these tests are testing internal implementation details. # ForeignObject is not part of public API. + class MultiColumnFKTests(TestCase): def setUp(self): # Creating countries @@ -379,6 +380,7 @@ class MultiColumnFKTests(TestCase): 'active_translation')[0].active_translation.title, "foo") + class FormsTests(TestCase): # ForeignObjects should not have any form fields, currently the user needs # to manually deal with the foreignobject relation. diff --git a/tests/forms_tests/models.py b/tests/forms_tests/models.py index 33898ffbb8..8ade923a91 100644 --- a/tests/forms_tests/models.py +++ b/tests/forms_tests/models.py @@ -19,6 +19,8 @@ class BoundaryModel(models.Model): callable_default_value = 0 + + def callable_default(): global callable_default_value callable_default_value = callable_default_value + 1 @@ -27,7 +29,7 @@ def callable_default(): class Defaults(models.Model): name = models.CharField(max_length=255, default='class default value') - def_date = models.DateField(default = datetime.date(1980, 1, 1)) + def_date = models.DateField(default=datetime.date(1980, 1, 1)) value = models.IntegerField(default=42) callable_default = models.IntegerField(default=callable_default) @@ -86,6 +88,7 @@ class ChoiceFieldModel(models.Model): multi_choice_int = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='multi_choice_int', default=lambda: [1]) + class OptionalMultiChoiceModel(models.Model): multi_choice = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='not_relevant', default=lambda: ChoiceOptionModel.objects.filter(name='default')) diff --git a/tests/forms_tests/tests/test_error_messages.py b/tests/forms_tests/tests/test_error_messages.py index 2d532c7cf9..86f26df3bc 100644 --- a/tests/forms_tests/tests/test_error_messages.py +++ b/tests/forms_tests/tests/test_error_messages.py @@ -24,6 +24,7 @@ class AssertFormErrorsMixin(object): except ValidationError as e: self.assertEqual(e.messages, expected) + class FormsErrorMessagesTestCase(TestCase, AssertFormErrorsMixin): def test_charfield(self): e = { diff --git a/tests/forms_tests/tests/test_extra.py b/tests/forms_tests/tests/test_extra.py index 183b5dabdf..4585a4e6ef 100644 --- a/tests/forms_tests/tests/test_extra.py +++ b/tests/forms_tests/tests/test_extra.py @@ -25,12 +25,15 @@ from .test_error_messages import AssertFormErrorsMixin class GetDate(Form): mydate = DateField(widget=SelectDateWidget) + class GetNotRequiredDate(Form): mydate = DateField(widget=SelectDateWidget, required=False) + class GetDateShowHiddenInitial(Form): mydate = DateField(widget=SelectDateWidget, show_hidden_initial=True) + class FormsExtraTestCase(TestCase, AssertFormErrorsMixin): ############### # Extra stuff # diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py index cf721b5510..52dfdf4044 100644 --- a/tests/forms_tests/tests/test_formsets.py +++ b/tests/forms_tests/tests/test_formsets.py @@ -57,7 +57,7 @@ SplitDateTimeFormSet = formset_factory(SplitDateTimeForm) class FormsFormsetTestCase(TestCase): def make_choiceformset(self, formset_data=None, formset_class=ChoiceFormSet, - total_forms=None, initial_forms=0, max_num_forms=0, min_num_forms=0, **kwargs): + total_forms=None, initial_forms=0, max_num_forms=0, min_num_forms=0, **kwargs): """ Make a ChoiceFormset from the given formset_data. The data should be given as a list of (choice, votes) tuples. @@ -1097,12 +1097,14 @@ data = { 'choices-0-votes': '100', } + class Choice(Form): choice = CharField() votes = IntegerField() ChoiceFormSet = formset_factory(Choice) + class FormsetAsFooTests(TestCase): def test_as_table(self): formset = ChoiceFormSet(data, auto_id=False, prefix='choices') @@ -1130,6 +1132,7 @@ class ArticleForm(Form): ArticleFormSet = formset_factory(ArticleForm) + class TestIsBoundBehavior(TestCase): def test_no_data_raises_validation_error(self): with self.assertRaises(ValidationError): @@ -1184,6 +1187,7 @@ class TestIsBoundBehavior(TestCase): # The empty forms should be equal. self.assertHTMLEqual(empty_forms[0].as_p(), empty_forms[1].as_p()) + class TestEmptyFormSet(TestCase): def test_empty_formset_is_valid(self): """Test that an empty formset still calls clean()""" diff --git a/tests/forms_tests/tests/test_input_formats.py b/tests/forms_tests/tests/test_input_formats.py index 25b491a499..b9c29c7609 100644 --- a/tests/forms_tests/tests/test_input_formats.py +++ b/tests/forms_tests/tests/test_input_formats.py @@ -490,6 +490,7 @@ class CustomDateInputFormatsTests(SimpleTestCase): text = f.widget._format_value(result) self.assertEqual(text, "21.12.2010") + class SimpleDateFormatTests(SimpleTestCase): def test_dateField(self): "DateFields can parse dates in the default format" @@ -776,6 +777,7 @@ class CustomDateTimeInputFormatsTests(SimpleTestCase): text = f.widget._format_value(result) self.assertEqual(text, "01:30:00 PM 21/12/2010") + class SimpleDateTimeFormatTests(SimpleTestCase): def test_dateTimeField(self): "DateTimeFields can parse dates in the default format" diff --git a/tests/forms_tests/tests/test_widgets.py b/tests/forms_tests/tests/test_widgets.py index c601a3ad58..21134d1a24 100644 --- a/tests/forms_tests/tests/test_widgets.py +++ b/tests/forms_tests/tests/test_widgets.py @@ -286,7 +286,7 @@ class FormsWidgetTestCase(TestCase): things = ({'id': 1, 'name': 'And Boom'}, {'id': 2, 'name': 'One More Thing!'}) class SomeForm(Form): - somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things])) + somechoice = ChoiceField(choices=chain((('', '-' * 9),), [(thing['id'], thing['name']) for thing in things])) f = SomeForm() self.assertHTMLEqual(f.as_table(), '') self.assertHTMLEqual(f.as_table(), '') @@ -1003,6 +1003,7 @@ class NullBooleanSelectLazyForm(Form): """Form to test for lazy evaluation. Refs #17190""" bool = BooleanField(widget=NullBooleanSelect()) + @override_settings(USE_L10N=True) class FormsI18NWidgetsTestCase(TestCase): def setUp(self): @@ -1136,6 +1137,7 @@ class FakeFieldFile(object): def __str__(self): return self.url + class ClearableFileInputTests(TestCase): def test_clear_input_renders(self): """ diff --git a/tests/forms_tests/tests/tests.py b/tests/forms_tests/tests/tests.py index 8212d4ee5c..622b6386e9 100644 --- a/tests/forms_tests/tests/tests.py +++ b/tests/forms_tests/tests/tests.py @@ -217,6 +217,7 @@ class FormsModelTestCase(TestCase): self.assertEqual(obj.value, 99) self.assertEqual(obj.def_date, datetime.date(1999, 3, 2)) + class RelatedModelFormTests(TestCase): def test_invalid_loading_order(self): """ diff --git a/tests/generic_inline_admin/admin.py b/tests/generic_inline_admin/admin.py index 1917024fa5..c701e4a9eb 100644 --- a/tests/generic_inline_admin/admin.py +++ b/tests/generic_inline_admin/admin.py @@ -7,6 +7,7 @@ from .models import (Media, PhoneNumber, Episode, EpisodeExtra, Contact, site = admin.AdminSite(name="admin") + class MediaInline(generic.GenericTabularInline): model = Media diff --git a/tests/generic_inline_admin/models.py b/tests/generic_inline_admin/models.py index cc7de62454..af3a474cdf 100644 --- a/tests/generic_inline_admin/models.py +++ b/tests/generic_inline_admin/models.py @@ -34,6 +34,7 @@ class Media(models.Model): # Generic inline with extra = 0 # + class EpisodeExtra(Episode): pass @@ -67,6 +68,7 @@ class Contact(models.Model): name = models.CharField(max_length=50) phone_numbers = generic.GenericRelation(PhoneNumber) + # # Generic inline with can_delete=False # diff --git a/tests/generic_inline_admin/tests.py b/tests/generic_inline_admin/tests.py index 23f17f7b22..09a802a1bc 100644 --- a/tests/generic_inline_admin/tests.py +++ b/tests/generic_inline_admin/tests.py @@ -129,6 +129,7 @@ class GenericAdminViewTest(TestCase): formset = inline_formset(instance=e) self.assertTrue(formset.get_queryset().ordered) + @override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',)) class GenericInlineAdminParametersTest(TestCase): urls = "generic_inline_admin.urls" @@ -210,6 +211,7 @@ class GenericInlineAdminWithUniqueTogetherTest(TestCase): response = self.client.post('/generic_inline_admin/admin/generic_inline_admin/contact/add/', post_data) self.assertEqual(response.status_code, 302) # redirect somewhere + class NoInlineDeletionTest(TestCase): urls = "generic_inline_admin.urls" @@ -224,6 +226,7 @@ class NoInlineDeletionTest(TestCase): class MockRequest(object): pass + class MockSuperUser(object): def has_perm(self, perm): return True diff --git a/tests/generic_relations/tests.py b/tests/generic_relations/tests.py index 60821903d9..8cd319bf03 100644 --- a/tests/generic_relations/tests.py +++ b/tests/generic_relations/tests.py @@ -290,12 +290,14 @@ class GenericRelationsTests(TestCase): class CustomWidget(forms.TextInput): pass + class TaggedItemForm(forms.ModelForm): class Meta: model = TaggedItem fields = '__all__' widgets = {'tag': CustomWidget} + class GenericInlineFormsetTest(TestCase): def test_generic_inlineformset_factory(self): """ diff --git a/tests/generic_relations_regress/models.py b/tests/generic_relations_regress/models.py index d716f09058..300ed9d54a 100644 --- a/tests/generic_relations_regress/models.py +++ b/tests/generic_relations_regress/models.py @@ -8,6 +8,7 @@ __all__ = ('Link', 'Place', 'Restaurant', 'Person', 'Address', 'CharLink', 'TextLink', 'OddRelation1', 'OddRelation2', 'Contact', 'Organization', 'Note', 'Company') + @python_2_unicode_compatible class Link(models.Model): content_type = models.ForeignKey(ContentType) @@ -17,6 +18,7 @@ class Link(models.Model): def __str__(self): return "Link to %s id=%s" % (self.content_type, self.object_id) + @python_2_unicode_compatible class Place(models.Model): name = models.CharField(max_length=100) @@ -25,11 +27,13 @@ class Place(models.Model): def __str__(self): return "Place: %s" % self.name + @python_2_unicode_compatible class Restaurant(Place): def __str__(self): return "Restaurant: %s" % self.name + @python_2_unicode_compatible class Address(models.Model): street = models.CharField(max_length=80) @@ -43,6 +47,7 @@ class Address(models.Model): def __str__(self): return '%s %s, %s %s' % (self.street, self.city, self.state, self.zipcode) + @python_2_unicode_compatible class Person(models.Model): account = models.IntegerField(primary_key=True) @@ -52,24 +57,29 @@ class Person(models.Model): def __str__(self): return self.name + class CharLink(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.CharField(max_length=100) content_object = generic.GenericForeignKey() + class TextLink(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.TextField() content_object = generic.GenericForeignKey() + class OddRelation1(models.Model): name = models.CharField(max_length=100) clinks = generic.GenericRelation(CharLink) + class OddRelation2(models.Model): name = models.CharField(max_length=100) tlinks = generic.GenericRelation(TextLink) + # models for test_q_object_or: class Note(models.Model): content_type = models.ForeignKey(ContentType) @@ -77,13 +87,16 @@ class Note(models.Model): content_object = generic.GenericForeignKey() note = models.TextField() + class Contact(models.Model): notes = generic.GenericRelation(Note) + class Organization(models.Model): name = models.CharField(max_length=255) contacts = models.ManyToManyField(Contact, related_name='organizations') + @python_2_unicode_compatible class Company(models.Model): name = models.CharField(max_length=100) @@ -92,10 +105,12 @@ class Company(models.Model): def __str__(self): return "Company: %s" % self.name + # For testing #13085 fix, we also use Note model defined above class Developer(models.Model): name = models.CharField(max_length=15) + @python_2_unicode_compatible class Team(models.Model): name = models.CharField(max_length=15) @@ -107,49 +122,59 @@ class Team(models.Model): def __len__(self): return self.members.count() + class Guild(models.Model): name = models.CharField(max_length=15) members = models.ManyToManyField(Developer) def __nonzero__(self): + return self.members.count() + class Tag(models.Model): content_type = models.ForeignKey(ContentType, related_name='g_r_r_tags') object_id = models.CharField(max_length=15) content_object = generic.GenericForeignKey() label = models.CharField(max_length=15) + class Board(models.Model): name = models.CharField(primary_key=True, max_length=15) + class HasLinks(models.Model): links = generic.GenericRelation(Link) class Meta: abstract = True + class HasLinkThing(HasLinks): pass + class A(models.Model): flag = models.NullBooleanField() content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') + class B(models.Model): a = generic.GenericRelation(A) class Meta: ordering = ('id',) + class C(models.Model): b = models.ForeignKey(B) class Meta: ordering = ('id',) + class D(models.Model): b = models.ForeignKey(B, null=True) diff --git a/tests/generic_views/models.py b/tests/generic_views/models.py index 30c73d67ca..f5554d1a20 100644 --- a/tests/generic_views/models.py +++ b/tests/generic_views/models.py @@ -18,6 +18,7 @@ class Artist(models.Model): def get_absolute_url(self): return reverse('artist_detail', kwargs={'pk': self.id}) + @python_2_unicode_compatible class Author(models.Model): name = models.CharField(max_length=100) @@ -29,6 +30,7 @@ class Author(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Book(models.Model): name = models.CharField(max_length=300) @@ -43,9 +45,11 @@ class Book(models.Model): def __str__(self): return self.name + class Page(models.Model): content = models.TextField() template = models.CharField(max_length=300) + class BookSigning(models.Model): event_date = models.DateTimeField() diff --git a/tests/generic_views/test_base.py b/tests/generic_views/test_base.py index eafa61a271..66ce224162 100644 --- a/tests/generic_views/test_base.py +++ b/tests/generic_views/test_base.py @@ -10,6 +10,7 @@ from django.views.generic import View, TemplateView, RedirectView from . import views + class SimpleView(View): """ A simple view with a docstring. diff --git a/tests/generic_views/test_dates.py b/tests/generic_views/test_dates.py index 58ee0dfcbe..944a3dcfe3 100644 --- a/tests/generic_views/test_dates.py +++ b/tests/generic_views/test_dates.py @@ -15,9 +15,10 @@ def _make_books(n, base_date): Book.objects.create( name='Book %d' % i, slug='book-%d' % i, - pages=100+i, + pages=100 + i, pubdate=base_date - datetime.timedelta(days=i)) + class ArchiveIndexViewTests(TestCase): fixtures = ['generic-views-test-data.json'] urls = 'generic_views.urls' diff --git a/tests/generic_views/views.py b/tests/generic_views/views.py index fd88debc0f..00e74d4708 100644 --- a/tests/generic_views/views.py +++ b/tests/generic_views/views.py @@ -65,6 +65,7 @@ class CustomPaginator(Paginator): orphans=2, allow_empty_first_page=allow_empty_first_page) + class AuthorListCustomPaginator(AuthorList): paginate_by = 5 @@ -176,33 +177,42 @@ class BookConfig(object): queryset = Book.objects.all() date_field = 'pubdate' + class BookArchive(BookConfig, generic.ArchiveIndexView): pass + class BookYearArchive(BookConfig, generic.YearArchiveView): pass + class BookMonthArchive(BookConfig, generic.MonthArchiveView): pass + class BookWeekArchive(BookConfig, generic.WeekArchiveView): pass + class BookDayArchive(BookConfig, generic.DayArchiveView): pass + class BookTodayArchive(BookConfig, generic.TodayArchiveView): pass + class BookDetail(BookConfig, generic.DateDetailView): pass + class AuthorGetQuerySetFormView(generic.edit.ModelFormMixin): fields = '__all__' def get_queryset(self): return Author.objects.all() + class BookDetailGetObjectCustomQueryset(BookDetail): def get_object(self, queryset=None): return super(BookDetailGetObjectCustomQueryset, self).get_object( @@ -234,10 +244,12 @@ class CustomContextView(generic.detail.SingleObjectMixin, generic.View): def get_context_object_name(self, obj): return "test_name" + class CustomSingleObjectView(generic.detail.SingleObjectMixin, generic.View): model = Book object = Book(name="dummy") + class BookSigningConfig(object): model = BookSigning date_field = 'event_date' @@ -246,24 +258,31 @@ class BookSigningConfig(object): def get_template_names(self): return ['generic_views/book%s.html' % self.template_name_suffix] + class BookSigningArchive(BookSigningConfig, generic.ArchiveIndexView): pass + class BookSigningYearArchive(BookSigningConfig, generic.YearArchiveView): pass + class BookSigningMonthArchive(BookSigningConfig, generic.MonthArchiveView): pass + class BookSigningWeekArchive(BookSigningConfig, generic.WeekArchiveView): pass + class BookSigningDayArchive(BookSigningConfig, generic.DayArchiveView): pass + class BookSigningTodayArchive(BookSigningConfig, generic.TodayArchiveView): pass + class BookSigningDetail(BookSigningConfig, generic.DateDetailView): context_object_name = 'book' diff --git a/tests/get_object_or_404/models.py b/tests/get_object_or_404/models.py index bb9aa60383..ea6e3e40d5 100644 --- a/tests/get_object_or_404/models.py +++ b/tests/get_object_or_404/models.py @@ -21,10 +21,12 @@ class Author(models.Model): def __str__(self): return self.name + class ArticleManager(models.Manager): def get_queryset(self): return super(ArticleManager, self).get_queryset().filter(authors__name__icontains='sir') + @python_2_unicode_compatible class Article(models.Model): authors = models.ManyToManyField(Author) diff --git a/tests/get_or_create_regress/models.py b/tests/get_or_create_regress/models.py index 637bbf62af..2ffc5c93ac 100644 --- a/tests/get_or_create_regress/models.py +++ b/tests/get_or_create_regress/models.py @@ -4,9 +4,11 @@ from django.db import models class Publisher(models.Model): name = models.CharField(max_length=100) + class Author(models.Model): name = models.CharField(max_length=100) + class Book(models.Model): name = models.CharField(max_length=100) authors = models.ManyToManyField(Author, related_name='books') diff --git a/tests/handlers/views.py b/tests/handlers/views.py index 1b75b27043..84cac97e62 100644 --- a/tests/handlers/views.py +++ b/tests/handlers/views.py @@ -4,18 +4,23 @@ from django.core.exceptions import SuspiciousOperation from django.db import connection, transaction from django.http import HttpResponse, StreamingHttpResponse + def regular(request): return HttpResponse(b"regular content") + def streaming(request): return StreamingHttpResponse([b"streaming", b" ", b"content"]) + def in_transaction(request): return HttpResponse(str(connection.in_atomic_block)) + @transaction.non_atomic_requests def not_in_transaction(request): return HttpResponse(str(connection.in_atomic_block)) + def suspicious(request): raise SuspiciousOperation('dubious') diff --git a/tests/httpwrappers/tests.py b/tests/httpwrappers/tests.py index 820aecf1f7..ccea20f9c5 100644 --- a/tests/httpwrappers/tests.py +++ b/tests/httpwrappers/tests.py @@ -239,6 +239,7 @@ class QueryDictTests(unittest.TestCase): self.assertEqual(copy.copy(q).encoding, 'iso-8859-15') self.assertEqual(copy.deepcopy(q).encoding, 'iso-8859-15') + class HttpResponseTests(unittest.TestCase): def test_headers_type(self): @@ -414,6 +415,7 @@ class HttpResponseTests(unittest.TestCase): self.assertRaises(SuspiciousOperation, HttpResponsePermanentRedirect, url) + class HttpResponseSubclassesTests(TestCase): def test_redirect(self): response = HttpResponseRedirect('/redirected/') @@ -448,6 +450,7 @@ class HttpResponseSubclassesTests(TestCase): content_type='text/html') self.assertContains(response, 'Only the GET method is allowed', status_code=405) + class StreamingHttpResponseTests(TestCase): def test_streaming_response(self): r = StreamingHttpResponse(iter(['hello', 'world'])) @@ -501,6 +504,7 @@ class StreamingHttpResponseTests(TestCase): with self.assertRaises(Exception): r.tell() + class FileCloseTests(TestCase): def setUp(self): @@ -566,6 +570,7 @@ class FileCloseTests(TestCase): self.assertTrue(file1.closed) self.assertTrue(file2.closed) + class CookieTests(unittest.TestCase): def test_encode(self): """ diff --git a/tests/i18n/forms.py b/tests/i18n/forms.py index 07b015d590..e06ed4b18d 100644 --- a/tests/i18n/forms.py +++ b/tests/i18n/forms.py @@ -12,9 +12,11 @@ class I18nForm(forms.Form): time_field = forms.TimeField(localize=True) integer_field = forms.IntegerField(localize=True) + class SelectDateForm(forms.Form): date_field = forms.DateField(widget=SelectDateWidget) + class CompanyForm(forms.ModelForm): cents_paid = forms.DecimalField(max_digits=4, decimal_places=2, localize=True) products_delivered = forms.IntegerField(localize=True) diff --git a/tests/i18n/models.py b/tests/i18n/models.py index 6e3591de24..3afc0841c6 100644 --- a/tests/i18n/models.py +++ b/tests/i18n/models.py @@ -7,6 +7,7 @@ from django.utils.translation import ugettext_lazy as _ class TestModel(models.Model): text = models.CharField(max_length=10, default=_('Anything')) + class Company(models.Model): name = models.CharField(max_length=50) date_added = models.DateTimeField(default=datetime(1799, 1, 31, 23, 59, 59, 0)) diff --git a/tests/i18n/test_extraction.py b/tests/i18n/test_extraction.py index 18088e5e16..633184f7c5 100644 --- a/tests/i18n/test_extraction.py +++ b/tests/i18n/test_extraction.py @@ -21,6 +21,7 @@ from django.utils.translation import TranslatorCommentWarning LOCALE = 'de' has_xgettext = find_command('xgettext') + @skipUnless(has_xgettext, 'xgettext is mandatory for extraction tests') class ExtractorTests(SimpleTestCase): @@ -130,9 +131,10 @@ class BasicExtractorTests(ExtractorTests): self.assertRaises(SyntaxError, management.call_command, 'makemessages', locale=LOCALE, extensions=['tpl'], verbosity=0) with self.assertRaises(SyntaxError) as context_manager: management.call_command('makemessages', locale=LOCALE, extensions=['tpl'], verbosity=0) - six.assertRegex(self, str(context_manager.exception), - r'Translation blocks must not include other block tags: blocktrans \(file templates[/\\]template_with_error\.tpl, line 3\)' - ) + six.assertRegex( + self, str(context_manager.exception), + r'Translation blocks must not include other block tags: blocktrans \(file templates[/\\]template_with_error\.tpl, line 3\)' + ) # Check that the temporary file was cleaned up self.assertFalse(os.path.exists('./templates/template_with_error.tpl.py')) @@ -210,13 +212,16 @@ class BasicExtractorTests(ExtractorTests): self.assertEqual(len(ws), 3) for w in ws: self.assertTrue(issubclass(w.category, TranslatorCommentWarning)) - six.assertRegex(self, str(ws[0].message), + six.assertRegex( + self, str(ws[0].message), r"The translator-targeted comment 'Translators: ignored i18n comment #1' \(file templates[/\\]comments.thtml, line 4\) was ignored, because it wasn't the last item on the line\." ) - six.assertRegex(self, str(ws[1].message), + six.assertRegex( + self, str(ws[1].message), r"The translator-targeted comment 'Translators: ignored i18n comment #3' \(file templates[/\\]comments.thtml, line 6\) was ignored, because it wasn't the last item on the line\." ) - six.assertRegex(self, str(ws[2].message), + six.assertRegex( + self, str(ws[2].message), r"The translator-targeted comment 'Translators: ignored i18n comment #4' \(file templates[/\\]comments.thtml, line 8\) was ignored, because it wasn't the last item on the line\." ) # Now test .po file contents @@ -281,6 +286,7 @@ class JavascriptExtractorTests(ExtractorTests): self.assertMsgId("quz", po_contents) self.assertMsgId("foobar", po_contents) + class IgnoredExtractorTests(ExtractorTests): def test_ignore_option(self): diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index b1f3de0ef9..ac9242241d 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -956,12 +956,14 @@ class ResolutionOrderI18NTests(TransRealMixin, TestCase): self.assertTrue(msgstr in result, ("The string '%s' isn't in the " "translation of '%s'; the actual result is '%s'." % (msgstr, msgid, result))) + @override_settings(INSTALLED_APPS=['i18n.resolution'] + list(settings.INSTALLED_APPS)) class AppResolutionOrderI18NTests(ResolutionOrderI18NTests): def test_app_translation(self): self.assertUgettext('Date/time', 'APP') + @override_settings(LOCALE_PATHS=extended_locale_paths) class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests): @@ -973,6 +975,7 @@ class LocalePathsResolutionOrderI18NTests(ResolutionOrderI18NTests): with self.settings(INSTALLED_APPS=extended_apps): self.assertUgettext('Time', 'LOCALE_PATHS') + class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests): def test_django_fallback(self): diff --git a/tests/inline_formsets/models.py b/tests/inline_formsets/models.py index 40c85fe739..383122dbd7 100644 --- a/tests/inline_formsets/models.py +++ b/tests/inline_formsets/models.py @@ -6,15 +6,18 @@ from django.utils.encoding import python_2_unicode_compatible class School(models.Model): name = models.CharField(max_length=100) + class Parent(models.Model): name = models.CharField(max_length=100) + class Child(models.Model): mother = models.ForeignKey(Parent, related_name='mothers_children') father = models.ForeignKey(Parent, related_name='fathers_children') school = models.ForeignKey(School) name = models.CharField(max_length=100) + @python_2_unicode_compatible class Poet(models.Model): name = models.CharField(max_length=100) @@ -22,6 +25,7 @@ class Poet(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Poem(models.Model): poet = models.ForeignKey(Poet) diff --git a/tests/inspectdb/models.py b/tests/inspectdb/models.py index 83cd906a07..f7c8af73c6 100644 --- a/tests/inspectdb/models.py +++ b/tests/inspectdb/models.py @@ -9,22 +9,27 @@ class People(models.Model): name = models.CharField(max_length=255) parent = models.ForeignKey('self') + class Message(models.Model): from_field = models.ForeignKey(People, db_column='from_id') + class PeopleData(models.Model): people_pk = models.ForeignKey(People, primary_key=True) ssn = models.CharField(max_length=11) + class PeopleMoreData(models.Model): people_unique = models.ForeignKey(People, unique=True) license = models.CharField(max_length=255) + class DigitsInColumnName(models.Model): all_digits = models.CharField(max_length=11, db_column='123') leading_digit = models.CharField(max_length=11, db_column='4extra') leading_digits = models.CharField(max_length=11, db_column='45extra') + class SpecialColumnName(models.Model): field = models.IntegerField(db_column='field') # Underscores @@ -35,6 +40,7 @@ class SpecialColumnName(models.Model): prc_x = models.IntegerField(db_column='prc(%) x') non_ascii = models.IntegerField(db_column='tamaƱo') + class ColumnTypes(models.Model): id = models.AutoField(primary_key=True) big_int_field = models.BigIntegerField() diff --git a/tests/inspectdb/tests.py b/tests/inspectdb/tests.py index 82802843d9..abd43f10e3 100644 --- a/tests/inspectdb/tests.py +++ b/tests/inspectdb/tests.py @@ -14,6 +14,7 @@ if connection.vendor == 'oracle': else: expectedFailureOnOracle = lambda f: f + class InspectDBTestCase(TestCase): def test_stealth_table_name_filter_option(self): @@ -166,7 +167,7 @@ class InspectDBTestCase(TestCase): self.assertIn(" managed = False", output, msg='inspectdb should generate unmanaged models.') @skipUnless(connection.vendor == 'sqlite', - "Only patched sqlite's DatabaseIntrospection.data_types_reverse for this test") + "Only patched sqlite's DatabaseIntrospection.data_types_reverse for this test") def test_custom_fields(self): """ Introspection of columns with a custom field (#21090) diff --git a/tests/known_related_objects/models.py b/tests/known_related_objects/models.py index cfee4650d9..2b5ab6cfe5 100644 --- a/tests/known_related_objects/models.py +++ b/tests/known_related_objects/models.py @@ -6,17 +6,21 @@ Test that queries are not redone when going back through known relations. from django.db import models + class Tournament(models.Model): name = models.CharField(max_length=30) + class Organiser(models.Model): name = models.CharField(max_length=30) + class Pool(models.Model): name = models.CharField(max_length=30) tournament = models.ForeignKey(Tournament) organiser = models.ForeignKey(Organiser) + class PoolStyle(models.Model): name = models.CharField(max_length=30) pool = models.OneToOneField(Pool) diff --git a/tests/known_related_objects/tests.py b/tests/known_related_objects/tests.py index 6fd507cbdc..03307f49ac 100644 --- a/tests/known_related_objects/tests.py +++ b/tests/known_related_objects/tests.py @@ -4,6 +4,7 @@ from django.test import TestCase from .models import Tournament, Organiser, Pool, PoolStyle + class ExistingRelatedInstancesTests(TestCase): fixtures = ['tournament.json'] diff --git a/tests/logging_tests/tests.py b/tests/logging_tests/tests.py index bd1983f74e..1b3a20cc24 100644 --- a/tests/logging_tests/tests.py +++ b/tests/logging_tests/tests.py @@ -62,6 +62,7 @@ class LoggingFiltersTest(TestCase): with self.settings(DEBUG=False): self.assertEqual(filter_.filter("record is not used"), False) + class DefaultLoggingTest(TestCase): def setUp(self): self.logger = logging.getLogger('django') @@ -83,6 +84,7 @@ class DefaultLoggingTest(TestCase): self.logger.error("Hey, this is an error.") self.assertEqual(output.getvalue(), 'Hey, this is an error.\n') + class WarningLoggerTests(TestCase): """ Tests that warnings output for DeprecationWarnings is enabled diff --git a/tests/lookup/models.py b/tests/lookup/models.py index a130d35e8e..df8b26c4e9 100644 --- a/tests/lookup/models.py +++ b/tests/lookup/models.py @@ -17,6 +17,7 @@ class Author(models.Model): class Meta: ordering = ('name', ) + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100) @@ -29,6 +30,7 @@ class Article(models.Model): def __str__(self): return self.headline + class Tag(models.Model): articles = models.ManyToManyField(Article) name = models.CharField(max_length=100) @@ -36,6 +38,7 @@ class Tag(models.Model): class Meta: ordering = ('name', ) + @python_2_unicode_compatible class Season(models.Model): year = models.PositiveSmallIntegerField() @@ -44,6 +47,7 @@ class Season(models.Model): def __str__(self): return six.text_type(self.year) + @python_2_unicode_compatible class Game(models.Model): season = models.ForeignKey(Season, related_name='games') @@ -53,6 +57,7 @@ class Game(models.Model): def __str__(self): return "%s at %s" % (self.away, self.home) + @python_2_unicode_compatible class Player(models.Model): name = models.CharField(max_length=100) diff --git a/tests/m2m_and_m2o/models.py b/tests/m2m_and_m2o/models.py index c303743f04..482ae9a1fa 100644 --- a/tests/m2m_and_m2o/models.py +++ b/tests/m2m_and_m2o/models.py @@ -13,6 +13,7 @@ from django.utils.encoding import python_2_unicode_compatible class User(models.Model): username = models.CharField(max_length=20) + @python_2_unicode_compatible class Issue(models.Model): num = models.IntegerField() @@ -25,5 +26,6 @@ class Issue(models.Model): class Meta: ordering = ('num',) + class UnicodeReferenceModel(models.Model): others = models.ManyToManyField("UnicodeReferenceModel") diff --git a/tests/m2m_and_m2o/tests.py b/tests/m2m_and_m2o/tests.py index 35443e32e4..e950a839d2 100644 --- a/tests/m2m_and_m2o/tests.py +++ b/tests/m2m_and_m2o/tests.py @@ -50,7 +50,7 @@ class RelatedObjectTests(TestCase): # These queries combine results from the m2m and the m2o relationships. # They're three ways of saying the same thing. self.assertQuerysetEqual( - Issue.objects.filter(Q(cc__id__exact = r.id) | Q(client=r.id)), [ + Issue.objects.filter(Q(cc__id__exact=r.id) | Q(client=r.id)), [ 1, 2, 3, @@ -74,6 +74,7 @@ class RelatedObjectTests(TestCase): lambda i: i.num ) + class RelatedObjectUnicodeTests(TestCase): def test_m2m_with_unicode_reference(self): """ diff --git a/tests/m2m_intermediary/models.py b/tests/m2m_intermediary/models.py index 770681f91c..9b194e321b 100644 --- a/tests/m2m_intermediary/models.py +++ b/tests/m2m_intermediary/models.py @@ -23,6 +23,7 @@ class Reporter(models.Model): def __str__(self): return "%s %s" % (self.first_name, self.last_name) + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100) @@ -31,6 +32,7 @@ class Article(models.Model): def __str__(self): return self.headline + @python_2_unicode_compatible class Writer(models.Model): reporter = models.ForeignKey(Reporter) diff --git a/tests/m2m_regress/models.py b/tests/m2m_regress/models.py index abd012b3d0..48fdad9304 100644 --- a/tests/m2m_regress/models.py +++ b/tests/m2m_regress/models.py @@ -2,6 +2,7 @@ from django.contrib.auth import models as auth from django.db import models from django.utils.encoding import python_2_unicode_compatible + # No related name is needed here, since symmetrical relations are not # explicitly reversible. @python_2_unicode_compatible @@ -13,6 +14,7 @@ class SelfRefer(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Tag(models.Model): name = models.CharField(max_length=10) @@ -20,6 +22,7 @@ class Tag(models.Model): def __str__(self): return self.name + # Regression for #11956 -- a many to many to the base class @python_2_unicode_compatible class TagCollection(Tag): @@ -28,6 +31,7 @@ class TagCollection(Tag): def __str__(self): return self.name + # A related_name is required on one of the ManyToManyField entries here because # they are both addressable as reverse relations from Tag. @python_2_unicode_compatible @@ -39,21 +43,26 @@ class Entry(models.Model): def __str__(self): return self.name + # Two models both inheriting from a base model with a self-referential m2m field class SelfReferChild(SelfRefer): pass + class SelfReferChildSibling(SelfRefer): pass + # Many-to-Many relation between models, where one of the PK's isn't an Autofield class Line(models.Model): name = models.CharField(max_length=100) + class Worksheet(models.Model): id = models.CharField(primary_key=True, max_length=100) lines = models.ManyToManyField(Line, blank=True, null=True) + # Regression for #11226 -- A model with the same name that another one to # which it has a m2m relation. This shouldn't cause a name clash between # the automatically created m2m intermediary table FK field names when diff --git a/tests/m2m_signals/models.py b/tests/m2m_signals/models.py index e997d87f21..e4110ccf34 100644 --- a/tests/m2m_signals/models.py +++ b/tests/m2m_signals/models.py @@ -12,6 +12,7 @@ class Part(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Car(models.Model): name = models.CharField(max_length=20) @@ -24,9 +25,11 @@ class Car(models.Model): def __str__(self): return self.name + class SportsCar(Car): price = models.IntegerField() + @python_2_unicode_compatible class Person(models.Model): name = models.CharField(max_length=20) diff --git a/tests/m2m_through/models.py b/tests/m2m_through/models.py index a896f6d9ff..70d6baeca8 100644 --- a/tests/m2m_through/models.py +++ b/tests/m2m_through/models.py @@ -15,6 +15,7 @@ class Person(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Group(models.Model): name = models.CharField(max_length=128) @@ -28,6 +29,7 @@ class Group(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Membership(models.Model): person = models.ForeignKey(Person) @@ -41,6 +43,7 @@ class Membership(models.Model): def __str__(self): return "%s is a member of %s" % (self.person.name, self.group.name) + @python_2_unicode_compatible class CustomMembership(models.Model): person = models.ForeignKey(Person, db_column="custom_person_column", related_name="custom_person_related_name") @@ -54,11 +57,13 @@ class CustomMembership(models.Model): class Meta: db_table = "test_table" + class TestNoDefaultsOrNulls(models.Model): person = models.ForeignKey(Person) group = models.ForeignKey(Group) nodefaultnonull = models.CharField(max_length=5) + @python_2_unicode_compatible class PersonSelfRefM2M(models.Model): name = models.CharField(max_length=5) @@ -67,6 +72,7 @@ class PersonSelfRefM2M(models.Model): def __str__(self): return self.name + class Friendship(models.Model): first = models.ForeignKey(PersonSelfRefM2M, related_name="rel_from_set") second = models.ForeignKey(PersonSelfRefM2M, related_name="rel_to_set") diff --git a/tests/m2m_through_regress/models.py b/tests/m2m_through_regress/models.py index 91e1aa8cc1..c49e5b02eb 100644 --- a/tests/m2m_through_regress/models.py +++ b/tests/m2m_through_regress/models.py @@ -15,6 +15,7 @@ class Membership(models.Model): def __str__(self): return "%s is a member of %s" % (self.person.name, self.group.name) + # using custom id column to test ticket #11107 @python_2_unicode_compatible class UserMembership(models.Model): @@ -26,6 +27,7 @@ class UserMembership(models.Model): def __str__(self): return "%s is a user and member of %s" % (self.user.username, self.group.name) + @python_2_unicode_compatible class Person(models.Model): name = models.CharField(max_length=128) @@ -33,6 +35,7 @@ class Person(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Group(models.Model): name = models.CharField(max_length=128) @@ -43,17 +46,21 @@ class Group(models.Model): def __str__(self): return self.name + # A set of models that use an non-abstract inherited model as the 'through' model. class A(models.Model): a_text = models.CharField(max_length=20) + class ThroughBase(models.Model): a = models.ForeignKey(A) b = models.ForeignKey('B') + class Through(ThroughBase): extra = models.CharField(max_length=20) + class B(models.Model): b_text = models.CharField(max_length=20) a_list = models.ManyToManyField(A, through=Through) @@ -68,6 +75,7 @@ class Car(models.Model): def __str__(self): return "%s" % self.make + @python_2_unicode_compatible class Driver(models.Model): name = models.CharField(max_length=20, unique=True, null=True) @@ -78,6 +86,7 @@ class Driver(models.Model): class Meta: ordering = ('name',) + @python_2_unicode_compatible class CarDriver(models.Model): car = models.ForeignKey('Car', to_field='make') diff --git a/tests/m2o_recursive/models.py b/tests/m2o_recursive/models.py index 2775d713dd..b41e0cb0a3 100644 --- a/tests/m2o_recursive/models.py +++ b/tests/m2o_recursive/models.py @@ -22,6 +22,7 @@ class Category(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Person(models.Model): full_name = models.CharField(max_length=20) diff --git a/tests/m2o_recursive/tests.py b/tests/m2o_recursive/tests.py index f5e8938706..b21aef95d3 100644 --- a/tests/m2o_recursive/tests.py +++ b/tests/m2o_recursive/tests.py @@ -21,6 +21,7 @@ class ManyToOneRecursiveTests(TestCase): self.assertQuerysetEqual(self.c.child_set.all(), []) self.assertEqual(self.c.parent.id, self.r.id) + class MultipleManyToOneRecursiveTests(TestCase): def setUp(self): diff --git a/tests/many_to_many/models.py b/tests/many_to_many/models.py index 31793b3974..eaf98ce565 100644 --- a/tests/many_to_many/models.py +++ b/tests/many_to_many/models.py @@ -22,6 +22,7 @@ class Publication(models.Model): class Meta: ordering = ('title',) + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100) diff --git a/tests/many_to_one/models.py b/tests/many_to_one/models.py index 4e2ed67eea..8c50ffe53b 100644 --- a/tests/many_to_one/models.py +++ b/tests/many_to_one/models.py @@ -18,6 +18,7 @@ class Reporter(models.Model): def __str__(self): return "%s %s" % (self.first_name, self.last_name) + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100) diff --git a/tests/many_to_one_null/models.py b/tests/many_to_one_null/models.py index e00ca85928..16ee56cec6 100644 --- a/tests/many_to_one_null/models.py +++ b/tests/many_to_one_null/models.py @@ -16,6 +16,7 @@ class Reporter(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=100) diff --git a/tests/many_to_one_regress/models.py b/tests/many_to_one_regress/models.py index 0ac0871793..c94bc5e05c 100644 --- a/tests/many_to_one_regress/models.py +++ b/tests/many_to_one_regress/models.py @@ -10,21 +10,26 @@ from django.utils.encoding import python_2_unicode_compatible # created (the field names being lower-cased versions of their opposite # classes is important here). + class First(models.Model): second = models.IntegerField() + class Second(models.Model): - first = models.ForeignKey(First, related_name = 'the_first') + first = models.ForeignKey(First, related_name='the_first') + # Protect against repetition of #1839, #2415 and #2536. class Third(models.Model): name = models.CharField(max_length=20) third = models.ForeignKey('self', null=True, related_name='child_set') + class Parent(models.Model): name = models.CharField(max_length=20) bestchild = models.ForeignKey('Child', null=True, related_name='favored_by') + class Child(models.Model): name = models.CharField(max_length=20) parent = models.ForeignKey(Parent) @@ -38,9 +43,11 @@ class Category(models.Model): def __str__(self): return self.name + class Record(models.Model): category = models.ForeignKey(Category) + @python_2_unicode_compatible class Relation(models.Model): left = models.ForeignKey(Record, related_name='left_set') @@ -49,8 +56,10 @@ class Relation(models.Model): def __str__(self): return "%s - %s" % (self.left.category.name, self.right.category.name) + class Car(models.Model): make = models.CharField(max_length=100, null=True, unique=True) + class Driver(models.Model): car = models.ForeignKey(Car, to_field='make', null=True, related_name='drivers') diff --git a/tests/max_lengths/models.py b/tests/max_lengths/models.py index d66e833e8c..ec4cc8e114 100644 --- a/tests/max_lengths/models.py +++ b/tests/max_lengths/models.py @@ -7,6 +7,7 @@ class PersonWithDefaultMaxLengths(models.Model): homepage = models.URLField() avatar = models.FilePathField() + class PersonWithCustomMaxLengths(models.Model): email = models.EmailField(max_length=250) vcard = models.FileField(upload_to='/tmp', max_length=250) diff --git a/tests/max_lengths/tests.py b/tests/max_lengths/tests.py index 5dd33fc80f..25101cd535 100644 --- a/tests/max_lengths/tests.py +++ b/tests/max_lengths/tests.py @@ -22,6 +22,7 @@ class MaxLengthArgumentsTests(unittest.TestCase): self.verify_max_length(PersonWithCustomMaxLengths, 'homepage', 250) self.verify_max_length(PersonWithCustomMaxLengths, 'avatar', 250) + class MaxLengthORMTests(unittest.TestCase): def test_custom_max_lengths(self): diff --git a/tests/middleware/tests.py b/tests/middleware/tests.py index b474f6b0e3..0124e33c98 100644 --- a/tests/middleware/tests.py +++ b/tests/middleware/tests.py @@ -120,7 +120,7 @@ class CommonMiddlewareTest(TestCase): r = CommonMiddleware().process_request(request) self.assertEqual(r.status_code, 301) self.assertEqual(r.url, - 'http://www.testserver/middleware/slash/') + 'http://www.testserver/middleware/slash/') @override_settings(APPEND_SLASH=True, PREPEND_WWW=True) def test_prepend_www_append_slash_slashless(self): @@ -128,7 +128,7 @@ class CommonMiddlewareTest(TestCase): r = CommonMiddleware().process_request(request) self.assertEqual(r.status_code, 301) self.assertEqual(r.url, - 'http://www.testserver/middleware/slash/') + 'http://www.testserver/middleware/slash/') # The following tests examine expected behavior given a custom urlconf that # overrides the default one through the request object. @@ -228,7 +228,7 @@ class CommonMiddlewareTest(TestCase): r = CommonMiddleware().process_request(request) self.assertEqual(r.status_code, 301) self.assertEqual(r.url, - 'http://www.testserver/middleware/customurlconf/slash/') + 'http://www.testserver/middleware/customurlconf/slash/') @override_settings(APPEND_SLASH=True, PREPEND_WWW=True) def test_prepend_www_append_slash_slashless_custom_urlconf(self): @@ -237,7 +237,7 @@ class CommonMiddlewareTest(TestCase): r = CommonMiddleware().process_request(request) self.assertEqual(r.status_code, 301) self.assertEqual(r.url, - 'http://www.testserver/middleware/customurlconf/slash/') + 'http://www.testserver/middleware/customurlconf/slash/') # Legacy tests for the 404 error reporting via email (to be removed in 1.8) @@ -336,7 +336,7 @@ class BrokenLinkEmailsMiddlewareTest(TestCase): return True user_agent = request.META['HTTP_USER_AGENT'] return any(pattern.search(user_agent) for pattern in - self.ignored_user_agent_patterns) + self.ignored_user_agent_patterns) self.req.META['HTTP_REFERER'] = '/another/url/' self.req.META['HTTP_USER_AGENT'] = 'Spider machine 3.4' @@ -346,6 +346,7 @@ class BrokenLinkEmailsMiddlewareTest(TestCase): SubclassedMiddleware().process_response(self.req, self.resp) self.assertEqual(len(mail.outbox), 1) + class ConditionalGetMiddlewareTest(TestCase): urls = 'middleware.cond_get_urls' @@ -704,6 +705,7 @@ class ETagGZipMiddlewareTest(TestCase): self.assertNotEqual(gzip_etag, nogzip_etag) + class TransactionMiddlewareTest(IgnoreDeprecationWarningsMixin, TransactionTestCase): """ Test the transaction middleware. diff --git a/tests/middleware_exceptions/tests.py b/tests/middleware_exceptions/tests.py index 02e53a00e8..83c6118c9d 100644 --- a/tests/middleware_exceptions/tests.py +++ b/tests/middleware_exceptions/tests.py @@ -778,6 +778,8 @@ class BadMiddlewareTests(BaseMiddlewareExceptionTest): _missing = object() + + class RootUrlconfTests(TestCase): urls = 'middleware_exceptions.urls' diff --git a/tests/middleware_exceptions/views.py b/tests/middleware_exceptions/views.py index ddf28c46a3..59abe26bff 100644 --- a/tests/middleware_exceptions/views.py +++ b/tests/middleware_exceptions/views.py @@ -7,20 +7,26 @@ from django.template.response import TemplateResponse def normal_view(request): return http.HttpResponse('OK') + def template_response(request): return TemplateResponse(request, Template('OK')) + def template_response_error(request): return TemplateResponse(request, Template('{%')) + def not_found(request): raise http.Http404() + def server_error(request): raise Exception('Error in view') + def null_view(request): return None + def permission_denied(request): raise PermissionDenied() diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py index f3ef83a39c..d78f3d7c2d 100644 --- a/tests/model_fields/tests.py +++ b/tests/model_fields/tests.py @@ -133,6 +133,7 @@ class DecimalFieldTests(test.TestCase): # This should not crash. That counts as a win for our purposes. Foo.objects.filter(d__gte=100000000000) + class ForeignKeyTests(test.TestCase): def test_callable_default(self): """Test the use of a lazy callable for ForeignKey.default""" @@ -140,6 +141,7 @@ class ForeignKeyTests(test.TestCase): b = Bar.objects.create(b="bcd") self.assertEqual(b.a, a) + class DateTimeFieldTests(unittest.TestCase): def test_datetimefield_to_python_usecs(self): """DateTimeField.to_python should support usecs""" @@ -157,6 +159,7 @@ class DateTimeFieldTests(unittest.TestCase): self.assertEqual(f.to_python('01:02:03.999999'), datetime.time(1, 2, 3, 999999)) + class BooleanFieldTests(unittest.TestCase): def _test_get_db_prep_lookup(self, f): from django.db import connection @@ -294,6 +297,7 @@ class BooleanFieldTests(unittest.TestCase): self.assertIsNone(nb.nbfield) nb.save() # no error + class ChoicesTests(test.TestCase): def test_choices_and_field_display(self): """ @@ -306,6 +310,7 @@ class ChoicesTests(test.TestCase): self.assertEqual(Whiz(c=None).get_c_display(), None) # Blank value self.assertEqual(Whiz(c='').get_c_display(), '') # Empty value + class SlugFieldTests(test.TestCase): def test_slugfield_max_length(self): """ @@ -409,6 +414,7 @@ class BigIntegerFieldTests(test.TestCase): b = BigInt.objects.get(value='10') self.assertEqual(b.value, 10) + class TypeCoercionTests(test.TestCase): """ Test that database lookups can accept the wrong types and convert @@ -422,6 +428,7 @@ class TypeCoercionTests(test.TestCase): def test_lookup_integer_in_textfield(self): self.assertEqual(Post.objects.filter(body=24).count(), 0) + class FileFieldTests(unittest.TestCase): def test_clearable(self): """ @@ -496,6 +503,7 @@ class BinaryFieldTests(test.TestCase): dm = DataModel(short_data=self.binary_data * 4) self.assertRaises(ValidationError, dm.full_clean) + class GenericIPAddressFieldTests(test.TestCase): def test_genericipaddressfield_formfield_protocol(self): """ diff --git a/tests/model_forms/models.py b/tests/model_forms/models.py index 34644a4bb9..72bf1ff26a 100644 --- a/tests/model_forms/models.py +++ b/tests/model_forms/models.py @@ -34,6 +34,7 @@ ARTICLE_STATUS_CHAR = ( ('l', 'Live'), ) + @python_2_unicode_compatible class Category(models.Model): name = models.CharField(max_length=20) @@ -46,6 +47,7 @@ class Category(models.Model): def __repr__(self): return self.__str__() + @python_2_unicode_compatible class Writer(models.Model): name = models.CharField(max_length=50, help_text='Use both first and last names.') @@ -56,6 +58,7 @@ class Writer(models.Model): def __str__(self): return self.name + @python_2_unicode_compatible class Article(models.Model): headline = models.CharField(max_length=50) @@ -76,15 +79,19 @@ class Article(models.Model): def __str__(self): return self.headline + class ImprovedArticle(models.Model): article = models.OneToOneField(Article) + class ImprovedArticleWithParentLink(models.Model): article = models.OneToOneField(Article, parent_link=True) + class BetterWriter(Writer): score = models.IntegerField() + @python_2_unicode_compatible class WriterProfile(models.Model): writer = models.OneToOneField(Writer, primary_key=True) @@ -93,6 +100,7 @@ class WriterProfile(models.Model): def __str__(self): return "%s is %s" % (self.writer, self.age) + @python_2_unicode_compatible class TextFile(models.Model): description = models.CharField(max_length=20) @@ -144,6 +152,7 @@ try: except ImproperlyConfigured: test_images = False + @python_2_unicode_compatible class CommaSeparatedInteger(models.Model): field = models.CommaSeparatedIntegerField(max_length=20) @@ -151,6 +160,7 @@ class CommaSeparatedInteger(models.Model): def __str__(self): return self.field + @python_2_unicode_compatible class Product(models.Model): slug = models.SlugField(unique=True) @@ -158,6 +168,7 @@ class Product(models.Model): def __str__(self): return self.slug + @python_2_unicode_compatible class Price(models.Model): price = models.DecimalField(max_digits=10, decimal_places=2) @@ -169,9 +180,11 @@ class Price(models.Model): class Meta: unique_together = (('price', 'quantity'),) + class ArticleStatus(models.Model): status = models.CharField(max_length=2, choices=ARTICLE_STATUS_CHAR, blank=True, null=True) + @python_2_unicode_compatible class Inventory(models.Model): barcode = models.PositiveIntegerField(unique=True) @@ -187,6 +200,7 @@ class Inventory(models.Model): def __repr__(self): return self.__str__() + class Book(models.Model): title = models.CharField(max_length=40) author = models.ForeignKey(Writer, blank=True, null=True) @@ -195,6 +209,7 @@ class Book(models.Model): class Meta: unique_together = ('title', 'author') + class BookXtra(models.Model): isbn = models.CharField(max_length=16, unique=True) suffix1 = models.IntegerField(blank=True, default=0) @@ -204,9 +219,11 @@ class BookXtra(models.Model): unique_together = (('suffix1', 'suffix2')) abstract = True + class DerivedBook(Book, BookXtra): pass + @python_2_unicode_compatible class ExplicitPK(models.Model): key = models.CharField(max_length=20, primary_key=True) @@ -218,6 +235,7 @@ class ExplicitPK(models.Model): def __str__(self): return self.key + @python_2_unicode_compatible class Post(models.Model): title = models.CharField(max_length=50, unique_for_date='posted', blank=True) @@ -228,6 +246,7 @@ class Post(models.Model): def __str__(self): return self.title + @python_2_unicode_compatible class DateTimePost(models.Model): title = models.CharField(max_length=50, unique_for_date='posted', blank=True) @@ -238,9 +257,11 @@ class DateTimePost(models.Model): def __str__(self): return self.title + class DerivedPost(Post): pass + @python_2_unicode_compatible class BigInt(models.Model): biggie = models.BigIntegerField() @@ -248,6 +269,7 @@ class BigInt(models.Model): def __str__(self): return six.text_type(self.biggie) + class MarkupField(models.CharField): def __init__(self, *args, **kwargs): kwargs["max_length"] = 20 @@ -260,16 +282,19 @@ class MarkupField(models.CharField): # regressed at r10062 return None + class CustomFieldForExclusionModel(models.Model): name = models.CharField(max_length=10) markup = MarkupField() + class FlexibleDatePost(models.Model): title = models.CharField(max_length=50, unique_for_date='posted', blank=True) slug = models.CharField(max_length=50, unique_for_year='posted', blank=True) subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True) posted = models.DateField(blank=True, null=True) + @python_2_unicode_compatible class Colour(models.Model): name = models.CharField(max_length=50) @@ -281,14 +306,17 @@ class Colour(models.Model): def __str__(self): return self.name + class ColourfulItem(models.Model): name = models.CharField(max_length=50) colours = models.ManyToManyField(Colour) + class ArticleStatusNote(models.Model): name = models.CharField(max_length=20) status = models.ManyToManyField(ArticleStatus) + class CustomErrorMessage(models.Model): name1 = models.CharField(max_length=50, validators=[validators.validate_slug], diff --git a/tests/model_inheritance_same_model_name/models.py b/tests/model_inheritance_same_model_name/models.py index 8b02b08668..a8c051facf 100644 --- a/tests/model_inheritance_same_model_name/models.py +++ b/tests/model_inheritance_same_model_name/models.py @@ -11,6 +11,7 @@ from django.db import models from model_inheritance.models import NamedURL from django.utils.encoding import python_2_unicode_compatible + # # Abstract base classes with related models # diff --git a/tests/multiple_database/tests.py b/tests/multiple_database/tests.py index 8596346c7e..222d236bb0 100644 --- a/tests/multiple_database/tests.py +++ b/tests/multiple_database/tests.py @@ -215,23 +215,23 @@ class QueryTestCase(TestCase): # Remove the second author dive.authors.remove(john) self.assertEqual(list(Book.objects.using('other').filter(authors__name='Mark Pilgrim').values_list('title', flat=True)), - ['Dive into Python']) + ['Dive into Python']) self.assertEqual(list(Book.objects.using('other').filter(authors__name='John Smith').values_list('title', flat=True)), - []) + []) # Clear all authors dive.authors.clear() self.assertEqual(list(Book.objects.using('other').filter(authors__name='Mark Pilgrim').values_list('title', flat=True)), - []) + []) self.assertEqual(list(Book.objects.using('other').filter(authors__name='John Smith').values_list('title', flat=True)), - []) + []) # Create an author through the m2m interface dive.authors.create(name='Jane Brown') self.assertEqual(list(Book.objects.using('other').filter(authors__name='Mark Pilgrim').values_list('title', flat=True)), - []) + []) self.assertEqual(list(Book.objects.using('other').filter(authors__name='Jane Brown').values_list('title', flat=True)), - ['Dive into Python']) + ['Dive into Python']) def test_m2m_reverse_operations(self): "M2M reverse manipulations are all constrained to a single DB" @@ -251,42 +251,42 @@ class QueryTestCase(TestCase): # Add a books to the m2m mark.book_set.add(grease) self.assertEqual(list(Person.objects.using('other').filter(book__title='Dive into Python').values_list('name', flat=True)), - ['Mark Pilgrim']) + ['Mark Pilgrim']) self.assertEqual(list(Person.objects.using('other').filter(book__title='Greasemonkey Hacks').values_list('name', flat=True)), - ['Mark Pilgrim']) + ['Mark Pilgrim']) # Remove a book from the m2m mark.book_set.remove(grease) self.assertEqual(list(Person.objects.using('other').filter(book__title='Dive into Python').values_list('name', flat=True)), - ['Mark Pilgrim']) + ['Mark Pilgrim']) self.assertEqual(list(Person.objects.using('other').filter(book__title='Greasemonkey Hacks').values_list('name', flat=True)), - []) + []) # Clear the books associated with mark mark.book_set.clear() self.assertEqual(list(Person.objects.using('other').filter(book__title='Dive into Python').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('other').filter(book__title='Greasemonkey Hacks').values_list('name', flat=True)), - []) + []) # Create a book through the m2m interface mark.book_set.create(title="Dive into HTML5", published=datetime.date(2020, 1, 1)) self.assertEqual(list(Person.objects.using('other').filter(book__title='Dive into Python').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('other').filter(book__title='Dive into HTML5').values_list('name', flat=True)), - ['Mark Pilgrim']) + ['Mark Pilgrim']) def test_m2m_cross_database_protection(self): "Operations that involve sharing M2M objects across databases raise an error" # Create a book and author on the default database pro = Book.objects.create(title="Pro Django", - published=datetime.date(2008, 12, 16)) + published=datetime.date(2008, 12, 16)) marty = Person.objects.create(name="Marty Alchin") # Create a book and author on the other database dive = Book.objects.using('other').create(title="Dive into Python", - published=datetime.date(2009, 5, 4)) + published=datetime.date(2009, 5, 4)) mark = Person.objects.using('other').create(name="Mark Pilgrim") # Set a foreign key set with an object from a different database @@ -413,14 +413,14 @@ class QueryTestCase(TestCase): # Check that queries work across foreign key joins self.assertEqual(list(Person.objects.using('default').filter(edited__title='Pro Django').values_list('name', flat=True)), - ['George Vilches']) + ['George Vilches']) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Pro Django').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('default').filter(edited__title='Dive into Python').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into Python').values_list('name', flat=True)), - ['Chris Mills']) + ['Chris Mills']) # Reget the objects to clear caches chris = Person.objects.using('other').get(name="Chris Mills") @@ -428,12 +428,12 @@ class QueryTestCase(TestCase): # Retrive related object by descriptor. Related objects should be database-baound self.assertEqual(list(chris.edited.values_list('title', flat=True)), - ['Dive into Python']) + ['Dive into Python']) def test_foreign_key_reverse_operations(self): "FK reverse manipulations are all constrained to a single DB" dive = Book.objects.using('other').create(title="Dive into Python", - published=datetime.date(2009, 5, 4)) + published=datetime.date(2009, 5, 4)) chris = Person.objects.using('other').create(name="Chris Mills") @@ -444,48 +444,48 @@ class QueryTestCase(TestCase): # Add a second book edited by chris html5 = Book.objects.using('other').create(title="Dive into HTML5", published=datetime.date(2010, 3, 15)) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into HTML5').values_list('name', flat=True)), - []) + []) chris.edited.add(html5) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into HTML5').values_list('name', flat=True)), - ['Chris Mills']) + ['Chris Mills']) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into Python').values_list('name', flat=True)), - ['Chris Mills']) + ['Chris Mills']) # Remove the second editor chris.edited.remove(html5) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into HTML5').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into Python').values_list('name', flat=True)), - ['Chris Mills']) + ['Chris Mills']) # Clear all edited books chris.edited.clear() self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into HTML5').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into Python').values_list('name', flat=True)), - []) + []) # Create an author through the m2m interface chris.edited.create(title='Dive into Water', published=datetime.date(2010, 3, 15)) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into HTML5').values_list('name', flat=True)), - []) + []) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into Water').values_list('name', flat=True)), - ['Chris Mills']) + ['Chris Mills']) self.assertEqual(list(Person.objects.using('other').filter(edited__title='Dive into Python').values_list('name', flat=True)), - []) + []) def test_foreign_key_cross_database_protection(self): "Operations that involve sharing FK objects across databases raise an error" # Create a book and author on the default database pro = Book.objects.create(title="Pro Django", - published=datetime.date(2008, 12, 16)) + published=datetime.date(2008, 12, 16)) marty = Person.objects.create(name="Marty Alchin") # Create a book and author on the other database dive = Book.objects.using('other').create(title="Dive into Python", - published=datetime.date(2009, 5, 4)) + published=datetime.date(2009, 5, 4)) mark = Person.objects.using('other').create(name="Mark Pilgrim") @@ -529,37 +529,37 @@ class QueryTestCase(TestCase): self.assertEqual(html5._state.db, 'other') # ... but it isn't saved yet self.assertEqual(list(Person.objects.using('other').values_list('name', flat=True)), - ['Mark Pilgrim']) + ['Mark Pilgrim']) self.assertEqual(list(Book.objects.using('other').values_list('title', flat=True)), - ['Dive into Python']) + ['Dive into Python']) # When saved (no using required), new objects goes to 'other' chris.save() html5.save() self.assertEqual(list(Person.objects.using('default').values_list('name', flat=True)), - ['Marty Alchin']) + ['Marty Alchin']) self.assertEqual(list(Person.objects.using('other').values_list('name', flat=True)), - ['Chris Mills', 'Mark Pilgrim']) + ['Chris Mills', 'Mark Pilgrim']) self.assertEqual(list(Book.objects.using('default').values_list('title', flat=True)), - ['Pro Django']) + ['Pro Django']) self.assertEqual(list(Book.objects.using('other').values_list('title', flat=True)), - ['Dive into HTML5', 'Dive into Python']) + ['Dive into HTML5', 'Dive into Python']) # This also works if you assign the FK in the constructor water = Book(title="Dive into Water", published=datetime.date(2001, 1, 1), editor=mark) self.assertEqual(water._state.db, 'other') # ... but it isn't saved yet self.assertEqual(list(Book.objects.using('default').values_list('title', flat=True)), - ['Pro Django']) + ['Pro Django']) self.assertEqual(list(Book.objects.using('other').values_list('title', flat=True)), - ['Dive into HTML5', 'Dive into Python']) + ['Dive into HTML5', 'Dive into Python']) # When saved, the new book goes to 'other' water.save() self.assertEqual(list(Book.objects.using('default').values_list('title', flat=True)), - ['Pro Django']) + ['Pro Django']) self.assertEqual(list(Book.objects.using('other').values_list('title', flat=True)), - ['Dive into HTML5', 'Dive into Python', 'Dive into Water']) + ['Dive into HTML5', 'Dive into Python', 'Dive into Water']) def test_foreign_key_deletion(self): "Cascaded deletions of Foreign Key relations issue queries on the right database" @@ -608,14 +608,14 @@ class QueryTestCase(TestCase): # Check that queries work across joins self.assertEqual(list(User.objects.using('default').filter(userprofile__flavor='chocolate').values_list('username', flat=True)), - ['alice']) + ['alice']) self.assertEqual(list(User.objects.using('other').filter(userprofile__flavor='chocolate').values_list('username', flat=True)), - []) + []) self.assertEqual(list(User.objects.using('default').filter(userprofile__flavor='crunchy frog').values_list('username', flat=True)), - []) + []) self.assertEqual(list(User.objects.using('other').filter(userprofile__flavor='crunchy frog').values_list('username', flat=True)), - ['bob']) + ['bob']) # Reget the objects to clear caches alice_profile = UserProfile.objects.using('default').get(flavor='chocolate') @@ -664,22 +664,22 @@ class QueryTestCase(TestCase): # ... but it isn't saved yet self.assertEqual(list(User.objects.using('other').values_list('username', flat=True)), - ['bob']) + ['bob']) self.assertEqual(list(UserProfile.objects.using('other').values_list('flavor', flat=True)), - ['crunchy frog']) + ['crunchy frog']) # When saved (no using required), new objects goes to 'other' charlie.save() bob_profile.save() new_bob_profile.save() self.assertEqual(list(User.objects.using('default').values_list('username', flat=True)), - ['alice']) + ['alice']) self.assertEqual(list(User.objects.using('other').values_list('username', flat=True)), - ['bob', 'charlie']) + ['bob', 'charlie']) self.assertEqual(list(UserProfile.objects.using('default').values_list('flavor', flat=True)), - ['chocolate']) + ['chocolate']) self.assertEqual(list(UserProfile.objects.using('other').values_list('flavor', flat=True)), - ['crunchy frog', 'spring surprise']) + ['crunchy frog', 'spring surprise']) # This also works if you assign the O2O relation in the constructor denise = User.objects.db_manager('other').create_user('denise', 'denise@example.com') @@ -688,16 +688,16 @@ class QueryTestCase(TestCase): self.assertEqual(denise_profile._state.db, 'other') # ... but it isn't saved yet self.assertEqual(list(UserProfile.objects.using('default').values_list('flavor', flat=True)), - ['chocolate']) + ['chocolate']) self.assertEqual(list(UserProfile.objects.using('other').values_list('flavor', flat=True)), - ['crunchy frog', 'spring surprise']) + ['crunchy frog', 'spring surprise']) # When saved, the new profile goes to 'other' denise_profile.save() self.assertEqual(list(UserProfile.objects.using('default').values_list('flavor', flat=True)), - ['chocolate']) + ['chocolate']) self.assertEqual(list(UserProfile.objects.using('other').values_list('flavor', flat=True)), - ['crunchy frog', 'spring surprise', 'tofu']) + ['crunchy frog', 'spring surprise', 'tofu']) def test_generic_key_separation(self): "Generic fields are constrained to a single database" @@ -724,7 +724,7 @@ class QueryTestCase(TestCase): # Retrive related object by descriptor. Related objects should be database-bound self.assertEqual(list(dive.reviews.all().values_list('source', flat=True)), - ['Python Weekly']) + ['Python Weekly']) def test_generic_key_reverse_operations(self): "Generic reverse manipulations are all constrained to a single DB" @@ -738,37 +738,37 @@ class QueryTestCase(TestCase): review2 = Review.objects.using('other').create(source="Python Monthly", content_object=temp) self.assertEqual(list(Review.objects.using('default').filter(object_id=dive.pk).values_list('source', flat=True)), - []) + []) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - ['Python Weekly']) + ['Python Weekly']) # Add a second review dive.reviews.add(review2) self.assertEqual(list(Review.objects.using('default').filter(object_id=dive.pk).values_list('source', flat=True)), - []) + []) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - ['Python Monthly', 'Python Weekly']) + ['Python Monthly', 'Python Weekly']) # Remove the second author dive.reviews.remove(review1) self.assertEqual(list(Review.objects.using('default').filter(object_id=dive.pk).values_list('source', flat=True)), - []) + []) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - ['Python Monthly']) + ['Python Monthly']) # Clear all reviews dive.reviews.clear() self.assertEqual(list(Review.objects.using('default').filter(object_id=dive.pk).values_list('source', flat=True)), - []) + []) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - []) + []) # Create an author through the generic interface dive.reviews.create(source='Python Daily') self.assertEqual(list(Review.objects.using('default').filter(object_id=dive.pk).values_list('source', flat=True)), - []) + []) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - ['Python Daily']) + ['Python Daily']) def test_generic_key_cross_database_protection(self): "Operations that involve sharing generic key objects across databases raise an error" @@ -810,16 +810,16 @@ class QueryTestCase(TestCase): self.assertEqual(review3._state.db, 'other') # ... but it isn't saved yet self.assertEqual(list(Review.objects.using('default').filter(object_id=pro.pk).values_list('source', flat=True)), - ['Python Monthly']) + ['Python Monthly']) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - ['Python Weekly']) + ['Python Weekly']) # When saved, John goes to 'other' review3.save() self.assertEqual(list(Review.objects.using('default').filter(object_id=pro.pk).values_list('source', flat=True)), - ['Python Monthly']) + ['Python Monthly']) self.assertEqual(list(Review.objects.using('other').filter(object_id=dive.pk).values_list('source', flat=True)), - ['Python Daily', 'Python Weekly']) + ['Python Daily', 'Python Weekly']) def test_generic_key_deletion(self): "Cascaded deletions of Generic Key relations issue queries on the right database" @@ -1360,18 +1360,18 @@ class RouterTestCase(TestCase): def test_generic_key_cross_database_protection(self): "Generic Key operations can span databases if they share a source" # Create a book and author on the default database - pro = Book.objects.using('default' - ).create(title="Pro Django", published=datetime.date(2008, 12, 16)) + pro = Book.objects.using( + 'default').create(title="Pro Django", published=datetime.date(2008, 12, 16)) - review1 = Review.objects.using('default' - ).create(source="Python Monthly", content_object=pro) + review1 = Review.objects.using( + 'default').create(source="Python Monthly", content_object=pro) # Create a book and author on the other database - dive = Book.objects.using('other' - ).create(title="Dive into Python", published=datetime.date(2009, 5, 4)) + dive = Book.objects.using( + 'other').create(title="Dive into Python", published=datetime.date(2009, 5, 4)) - review2 = Review.objects.using('other' - ).create(source="Python Weekly", content_object=dive) + review2 = Review.objects.using( + 'other').create(source="Python Weekly", content_object=dive) # Set a generic foreign key with an object from a different database try: @@ -1571,6 +1571,7 @@ class AuthTestCase(TestCase): command_output = new_io.getvalue().strip() self.assertTrue('"email": "alice@example.com"' in command_output) + class AntiPetRouter(object): # A router that only expresses an opinion on migrate, # passing pets to the 'other' database @@ -1582,6 +1583,7 @@ class AntiPetRouter(object): else: return model._meta.object_name != 'Pet' + class FixtureTestCase(TestCase): multi_db = True fixtures = ['multidb-common', 'multidb'] @@ -1604,7 +1606,8 @@ class FixtureTestCase(TestCase): except Book.DoesNotExist: self.fail('"Pro Django" should exist on default database') - self.assertRaises(Book.DoesNotExist, + self.assertRaises( + Book.DoesNotExist, Book.objects.using('other').get, title="Pro Django" ) @@ -1615,11 +1618,13 @@ class FixtureTestCase(TestCase): except Book.DoesNotExist: self.fail('"Dive into Python" should exist on other database') - self.assertRaises(Book.DoesNotExist, + self.assertRaises( + Book.DoesNotExist, Book.objects.get, title="Dive into Python" ) - self.assertRaises(Book.DoesNotExist, + self.assertRaises( + Book.DoesNotExist, Book.objects.using('default').get, title="Dive into Python" ) @@ -1640,6 +1645,7 @@ class FixtureTestCase(TestCase): # No objects will actually be loaded self.assertEqual(command_output, "Installed 0 object(s) (of 2) from 1 fixture(s)") + class PickleQuerySetTestCase(TestCase): multi_db = True @@ -1657,6 +1663,7 @@ class DatabaseReceiver(object): def __call__(self, signal, sender, **kwargs): self._database = kwargs['using'] + class WriteToOtherRouter(object): """ A router that sends all writes to the other database. @@ -1664,6 +1671,7 @@ class WriteToOtherRouter(object): def db_for_write(self, model, **hints): return "other" + class SignalTests(TestCase): multi_db = True @@ -1771,6 +1779,7 @@ class SignalTests(TestCase): self._write_to_default() self.assertEqual(receiver._database, "other") + class AttributeErrorRouter(object): "A router to test the exception handling of ConnectionRouter" def db_for_read(self, model, **hints): @@ -1779,6 +1788,7 @@ class AttributeErrorRouter(object): def db_for_write(self, model, **hints): raise AttributeError + class RouterAttributeErrorTestCase(TestCase): multi_db = True @@ -1824,12 +1834,14 @@ class RouterAttributeErrorTestCase(TestCase): router.routers = [AttributeErrorRouter()] # Install our router self.assertRaises(AttributeError, setattr, b, 'authors', [p]) + class ModelMetaRouter(object): "A router to ensure model arguments are real model classes" def db_for_write(self, model, **hints): if not hasattr(model, '_meta'): raise ValueError + class RouterModelArgumentTestCase(TestCase): multi_db = True