summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2012-07-26 18:58:10 +0100
committerAndrew Godwin <andrew@aeracode.org>2012-07-26 18:58:10 +0100
commit4a2e80fff44d0eb1856b593ac5f31ab1492b3e45 (patch)
tree9bc87a682dc488e6555792c1d4bb53f5f3cdc880 /tests
parent959a3f9791d780062c4efe8765404a8ef95e87f0 (diff)
parentab6cd1c839b136cbc94178da433b2e97ab7f6061 (diff)
Merge branch 'master' of github.com:django/django into schema-alteration
Conflicts: django/db/backends/postgresql_psycopg2/base.py
Diffstat (limited to 'tests')
-rw-r--r--tests/modeltests/aggregation/tests.py20
-rw-r--r--tests/modeltests/basic/tests.py22
-rw-r--r--tests/modeltests/custom_columns/tests.py9
-rw-r--r--tests/modeltests/custom_managers/tests.py3
-rw-r--r--tests/modeltests/custom_pk/fields.py5
-rw-r--r--tests/modeltests/custom_pk/tests.py15
-rw-r--r--tests/modeltests/defer/tests.py20
-rw-r--r--tests/modeltests/delete/tests.py1
-rw-r--r--tests/modeltests/expressions/tests.py3
-rw-r--r--tests/modeltests/field_defaults/tests.py3
-rw-r--r--tests/modeltests/field_subclassing/fields.py7
-rw-r--r--tests/modeltests/files/models.py2
-rw-r--r--tests/modeltests/files/tests.py23
-rw-r--r--tests/modeltests/fixtures_model_package/tests.py2
-rw-r--r--tests/modeltests/generic_relations/tests.py2
-rw-r--r--tests/modeltests/lookup/models.py3
-rw-r--r--tests/modeltests/m2m_and_m2o/models.py3
-rw-r--r--tests/modeltests/m2m_intermediary/tests.py5
-rw-r--r--tests/modeltests/many_to_one/tests.py17
-rw-r--r--tests/modeltests/many_to_one_null/tests.py4
-rw-r--r--tests/modeltests/model_forms/models.py3
-rw-r--r--tests/modeltests/model_forms/tests.py33
-rw-r--r--tests/modeltests/model_formsets/models.py3
-rw-r--r--tests/modeltests/model_formsets/tests.py21
-rw-r--r--tests/modeltests/model_inheritance/tests.py5
-rw-r--r--tests/modeltests/order_with_respect_to/models.py3
-rw-r--r--tests/modeltests/pagination/tests.py7
-rw-r--r--tests/modeltests/prefetch_related/tests.py39
-rw-r--r--tests/modeltests/save_delete_hooks/tests.py3
-rw-r--r--tests/modeltests/select_for_update/tests.py7
-rw-r--r--tests/modeltests/serializers/models.py3
-rw-r--r--tests/modeltests/serializers/tests.py5
-rw-r--r--tests/modeltests/signals/tests.py3
-rw-r--r--tests/modeltests/test_client/views.py6
-rw-r--r--tests/modeltests/update/models.py5
-rw-r--r--tests/modeltests/update_only_fields/tests.py8
-rw-r--r--tests/regressiontests/admin_changelist/models.py3
-rw-r--r--tests/regressiontests/admin_changelist/tests.py9
-rw-r--r--tests/regressiontests/admin_scripts/custom_templates/project_template/additional_dir/extra.py1
-rw-r--r--tests/regressiontests/admin_scripts/management/commands/custom_startproject.py11
-rw-r--r--tests/regressiontests/admin_scripts/tests.py18
-rw-r--r--tests/regressiontests/admin_util/models.py3
-rw-r--r--tests/regressiontests/admin_util/tests.py7
-rw-r--r--tests/regressiontests/admin_views/admin.py8
-rw-r--r--tests/regressiontests/admin_views/customadmin.py1
-rw-r--r--tests/regressiontests/admin_views/models.py9
-rw-r--r--tests/regressiontests/admin_views/tests.py44
-rw-r--r--tests/regressiontests/backends/tests.py22
-rw-r--r--tests/regressiontests/bulk_create/models.py6
-rw-r--r--tests/regressiontests/bulk_create/tests.py46
-rw-r--r--tests/regressiontests/conditional_processing/models.py6
-rw-r--r--tests/regressiontests/datatypes/tests.py3
-rw-r--r--tests/regressiontests/defaultfilters/tests.py11
-rw-r--r--tests/regressiontests/defer_regress/models.py4
-rw-r--r--tests/regressiontests/defer_regress/tests.py26
-rw-r--r--tests/regressiontests/dispatch/tests/__init__.py2
-rw-r--r--tests/regressiontests/dispatch/tests/test_dispatcher.py30
-rw-r--r--tests/regressiontests/dispatch/tests/test_saferef.py4
-rw-r--r--tests/regressiontests/file_storage/tests.py6
-rw-r--r--tests/regressiontests/file_uploads/tests.py6
-rw-r--r--tests/regressiontests/file_uploads/views.py3
-rw-r--r--tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json4
-rw-r--r--tests/regressiontests/fixtures_regress/models.py4
-rw-r--r--tests/regressiontests/fixtures_regress/tests.py2
-rw-r--r--tests/regressiontests/forms/tests/extra.py2
-rw-r--r--tests/regressiontests/forms/tests/fields.py5
-rw-r--r--tests/regressiontests/forms/tests/models.py3
-rw-r--r--tests/regressiontests/forms/tests/util.py3
-rw-r--r--tests/regressiontests/forms/tests/widgets.py7
-rw-r--r--tests/regressiontests/httpwrappers/tests.py14
-rw-r--r--tests/regressiontests/i18n/commands/code.sample4
-rw-r--r--tests/regressiontests/i18n/commands/extraction.py8
-rw-r--r--tests/regressiontests/i18n/commands/tests.py4
-rw-r--r--tests/regressiontests/i18n/contenttypes/tests.py7
-rw-r--r--tests/regressiontests/i18n/tests.py12
-rw-r--r--tests/regressiontests/initial_sql_regress/sql/simple.sql4
-rw-r--r--tests/regressiontests/initial_sql_regress/tests.py22
-rw-r--r--tests/regressiontests/inline_formsets/tests.py5
-rw-r--r--tests/regressiontests/localflavor/ar/tests.py9
-rw-r--r--tests/regressiontests/localflavor/fr/tests.py3
-rw-r--r--tests/regressiontests/mail/tests.py20
-rw-r--r--tests/regressiontests/middleware/tests.py1
-rw-r--r--tests/regressiontests/model_fields/imagefield.py686
-rw-r--r--tests/regressiontests/model_fields/tests.py29
-rw-r--r--tests/regressiontests/model_forms_regress/tests.py9
-rw-r--r--tests/regressiontests/model_formsets_regress/tests.py11
-rw-r--r--tests/regressiontests/model_regress/tests.py5
-rw-r--r--tests/regressiontests/queries/models.py3
-rw-r--r--tests/regressiontests/queries/tests.py89
-rw-r--r--tests/regressiontests/queryset_pickle/tests.py10
-rw-r--r--tests/regressiontests/select_related_regress/tests.py7
-rw-r--r--tests/regressiontests/serializers_regress/tests.py18
-rw-r--r--tests/regressiontests/servers/tests.py9
-rw-r--r--tests/regressiontests/staticfiles_tests/apps/test/static/test/nonascii.css5
-rw-r--r--tests/regressiontests/staticfiles_tests/apps/test/static/test/window.pngbin0 -> 207 bytes
-rw-r--r--tests/regressiontests/staticfiles_tests/project/documents/cached/css/ignored.css8
-rw-r--r--tests/regressiontests/staticfiles_tests/project/documents/cached/import.css1
-rw-r--r--tests/regressiontests/staticfiles_tests/tests.py41
-rw-r--r--tests/regressiontests/templates/templatetags/custom.py23
-rw-r--r--tests/regressiontests/templates/tests.py9
-rw-r--r--tests/regressiontests/templates/unicode.py3
-rw-r--r--tests/regressiontests/test_client_regress/views.py2
-rw-r--r--tests/regressiontests/test_runner/tests.py3
-rw-r--r--tests/regressiontests/transactions_regress/tests.py57
-rw-r--r--tests/regressiontests/urlpatterns_reverse/erroneous_urls.py2
-rw-r--r--tests/regressiontests/urlpatterns_reverse/tests.py8
-rw-r--r--tests/regressiontests/utils/datastructures.py104
-rw-r--r--tests/regressiontests/utils/html.py11
-rw-r--r--tests/regressiontests/utils/simplelazyobject.py7
-rw-r--r--tests/regressiontests/utils/tests.py2
-rw-r--r--tests/regressiontests/wsgi/tests.py3
-rwxr-xr-xtests/runtests.py3
112 files changed, 1249 insertions, 674 deletions
diff --git a/tests/modeltests/aggregation/tests.py b/tests/modeltests/aggregation/tests.py
index 433ea1641a..c23b32fc85 100644
--- a/tests/modeltests/aggregation/tests.py
+++ b/tests/modeltests/aggregation/tests.py
@@ -565,3 +565,23 @@ class BaseAggregateTestCase(TestCase):
(Decimal('82.8'), 1),
]
)
+
+ def test_dates_with_aggregation(self):
+ """
+ Test that .dates() returns a distinct set of dates when applied to a
+ QuerySet with aggregation.
+
+ Refs #18056. Previously, .dates() would return distinct (date_kind,
+ aggregation) sets, in this case (year, num_authors), so 2008 would be
+ returned twice because there are books from 2008 with a different
+ number of authors.
+ """
+ dates = Book.objects.annotate(num_authors=Count("authors")).dates('pubdate', 'year')
+ self.assertQuerysetEqual(
+ dates, [
+ "datetime.datetime(1991, 1, 1, 0, 0)",
+ "datetime.datetime(1995, 1, 1, 0, 0)",
+ "datetime.datetime(2007, 1, 1, 0, 0)",
+ "datetime.datetime(2008, 1, 1, 0, 0)"
+ ]
+ )
diff --git a/tests/modeltests/basic/tests.py b/tests/modeltests/basic/tests.py
index 3f00fb25fe..d96c60bbe8 100644
--- a/tests/modeltests/basic/tests.py
+++ b/tests/modeltests/basic/tests.py
@@ -5,6 +5,7 @@ from datetime import datetime
from django.core.exceptions import ObjectDoesNotExist
from django.db.models.fields import Field, FieldDoesNotExist
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
+from django.utils.six import PY3
from django.utils.translation import ugettext_lazy
from .models import Article
@@ -321,17 +322,18 @@ class ModelTest(TestCase):
["<Article: Area man programs in Python>",
"<Article: Third article>"])
- # Slicing works with longs.
- self.assertEqual(Article.objects.all()[0L], a)
- self.assertQuerysetEqual(Article.objects.all()[1L:3L],
- ["<Article: Second article>", "<Article: Third article>"])
- self.assertQuerysetEqual((s1 | s2 | s3)[::2L],
- ["<Article: Area man programs in Python>",
- "<Article: Third article>"])
+ # Slicing works with longs (Python 2 only -- Python 3 doesn't have longs).
+ if not PY3:
+ self.assertEqual(Article.objects.all()[long(0)], a)
+ self.assertQuerysetEqual(Article.objects.all()[long(1):long(3)],
+ ["<Article: Second article>", "<Article: Third article>"])
+ self.assertQuerysetEqual((s1 | s2 | s3)[::long(2)],
+ ["<Article: Area man programs in Python>",
+ "<Article: Third article>"])
- # And can be mixed with ints.
- self.assertQuerysetEqual(Article.objects.all()[1:3L],
- ["<Article: Second article>", "<Article: Third article>"])
+ # And can be mixed with ints.
+ self.assertQuerysetEqual(Article.objects.all()[1:long(3)],
+ ["<Article: Second article>", "<Article: Third article>"])
# Slices (without step) are lazy:
self.assertQuerysetEqual(Article.objects.all()[0:5].filter(),
diff --git a/tests/modeltests/custom_columns/tests.py b/tests/modeltests/custom_columns/tests.py
index c1bb6f0a01..a2e5323a75 100644
--- a/tests/modeltests/custom_columns/tests.py
+++ b/tests/modeltests/custom_columns/tests.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import
from django.core.exceptions import FieldError
from django.test import TestCase
+from django.utils import six
from .models import Author, Article
@@ -22,13 +23,13 @@ class CustomColumnsTests(TestCase):
Author.objects.all(), [
"Peter Jones", "John Smith",
],
- unicode
+ six.text_type
)
self.assertQuerysetEqual(
Author.objects.filter(first_name__exact="John"), [
"John Smith",
],
- unicode
+ six.text_type
)
self.assertEqual(
Author.objects.get(first_name__exact="John"),
@@ -55,7 +56,7 @@ class CustomColumnsTests(TestCase):
"Peter Jones",
"John Smith",
],
- unicode
+ six.text_type
)
# Get the articles for an author
self.assertQuerysetEqual(
@@ -69,5 +70,5 @@ class CustomColumnsTests(TestCase):
art.authors.filter(last_name='Jones'), [
"Peter Jones"
],
- unicode
+ six.text_type
)
diff --git a/tests/modeltests/custom_managers/tests.py b/tests/modeltests/custom_managers/tests.py
index bdba3d0733..294920de2b 100644
--- a/tests/modeltests/custom_managers/tests.py
+++ b/tests/modeltests/custom_managers/tests.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import
from django.test import TestCase
+from django.utils import six
from .models import Person, Book, Car, PersonManager, PublishedBookManager
@@ -14,7 +15,7 @@ class CustomManagerTests(TestCase):
Person.objects.get_fun_people(), [
"Bugs Bunny"
],
- unicode
+ six.text_type
)
# The RelatedManager used on the 'books' descriptor extends the default
# manager
diff --git a/tests/modeltests/custom_pk/fields.py b/tests/modeltests/custom_pk/fields.py
index 40551a363c..68fb9dcd16 100644
--- a/tests/modeltests/custom_pk/fields.py
+++ b/tests/modeltests/custom_pk/fields.py
@@ -2,6 +2,7 @@ import random
import string
from django.db import models
+from django.utils import six
class MyWrapper(object):
@@ -44,12 +45,12 @@ class MyAutoField(models.CharField):
if not value:
return
if isinstance(value, MyWrapper):
- return unicode(value)
+ return six.text_type(value)
return value
def get_db_prep_value(self, value, connection, prepared=False):
if not value:
return
if isinstance(value, MyWrapper):
- return unicode(value)
+ return six.text_type(value)
return value
diff --git a/tests/modeltests/custom_pk/tests.py b/tests/modeltests/custom_pk/tests.py
index b473dcab59..3f562f0bed 100644
--- a/tests/modeltests/custom_pk/tests.py
+++ b/tests/modeltests/custom_pk/tests.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import, unicode_literals
from django.db import transaction, IntegrityError
from django.test import TestCase, skipIfDBFeature
+from django.utils import six
from .models import Employee, Business, Bar, Foo
@@ -16,7 +17,7 @@ class CustomPKTests(TestCase):
Employee.objects.all(), [
"Dan Jones",
],
- unicode
+ six.text_type
)
fran = Employee.objects.create(
@@ -27,7 +28,7 @@ class CustomPKTests(TestCase):
"Fran Bones",
"Dan Jones",
],
- unicode
+ six.text_type
)
self.assertEqual(Employee.objects.get(pk=123), dan)
@@ -45,7 +46,7 @@ class CustomPKTests(TestCase):
"Fran Bones",
"Dan Jones",
],
- unicode
+ six.text_type
)
# The primary key can be accessed via the pk property on the model.
e = Employee.objects.get(pk=123)
@@ -63,7 +64,7 @@ class CustomPKTests(TestCase):
"Dan Jones",
"Fran Jones",
],
- unicode
+ six.text_type
)
emps = Employee.objects.in_bulk([123, 456])
@@ -76,7 +77,7 @@ class CustomPKTests(TestCase):
"Dan Jones",
"Fran Jones",
],
- unicode
+ six.text_type
)
self.assertQuerysetEqual(
fran.business_set.all(), [
@@ -108,14 +109,14 @@ class CustomPKTests(TestCase):
"Dan Jones",
"Fran Jones",
],
- unicode,
+ six.text_type,
)
self.assertQuerysetEqual(
Employee.objects.filter(business__pk="Sears"), [
"Dan Jones",
"Fran Jones",
],
- unicode,
+ six.text_type,
)
self.assertQuerysetEqual(
diff --git a/tests/modeltests/defer/tests.py b/tests/modeltests/defer/tests.py
index eb09162b01..50db5a76b4 100644
--- a/tests/modeltests/defer/tests.py
+++ b/tests/modeltests/defer/tests.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from django.db.models.query_utils import DeferredAttribute
+from django.db.models.query_utils import DeferredAttribute, InvalidQuery
from django.test import TestCase
from .models import Secondary, Primary, Child, BigChild, ChildProxy
@@ -73,9 +73,19 @@ class DeferTests(TestCase):
self.assert_delayed(qs.defer("name").get(pk=p1.pk), 1)
self.assert_delayed(qs.only("name").get(pk=p1.pk), 2)
- # DOES THIS WORK?
- self.assert_delayed(qs.only("name").select_related("related")[0], 1)
- self.assert_delayed(qs.defer("related").select_related("related")[0], 0)
+ # When we defer a field and also select_related it, the query is
+ # invalid and raises an exception.
+ with self.assertRaises(InvalidQuery):
+ qs.only("name").select_related("related")[0]
+ with self.assertRaises(InvalidQuery):
+ qs.defer("related").select_related("related")[0]
+
+ # With a depth-based select_related, all deferred ForeignKeys are
+ # deferred instead of traversed.
+ with self.assertNumQueries(3):
+ obj = qs.defer("related").select_related()[0]
+ self.assert_delayed(obj, 1)
+ self.assertEqual(obj.related.id, s1.pk)
# Saving models with deferred fields is possible (but inefficient,
# since every field has to be retrieved first).
@@ -155,7 +165,7 @@ class DeferTests(TestCase):
children = ChildProxy.objects.all().select_related().only('id', 'name')
self.assertEqual(len(children), 1)
child = children[0]
- self.assert_delayed(child, 1)
+ self.assert_delayed(child, 2)
self.assertEqual(child.name, 'p1')
self.assertEqual(child.value, 'xx')
diff --git a/tests/modeltests/delete/tests.py b/tests/modeltests/delete/tests.py
index d681a76fd2..26f2fd52c1 100644
--- a/tests/modeltests/delete/tests.py
+++ b/tests/modeltests/delete/tests.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import
from django.db import models, IntegrityError
from django.test import TestCase, skipUnlessDBFeature, skipIfDBFeature
+from django.utils.six.moves import xrange
from .models import (R, RChild, S, T, U, A, M, MR, MRNull,
create_a, get_default_r, User, Avatar, HiddenUser, HiddenUserProfile)
diff --git a/tests/modeltests/expressions/tests.py b/tests/modeltests/expressions/tests.py
index c4e2707109..99eb07e370 100644
--- a/tests/modeltests/expressions/tests.py
+++ b/tests/modeltests/expressions/tests.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import, unicode_literals
from django.core.exceptions import FieldError
from django.db.models import F
from django.test import TestCase
+from django.utils import six
from .models import Company, Employee
@@ -156,7 +157,7 @@ class ExpressionsTests(TestCase):
"Frank Meyer",
"Max Mustermann",
],
- lambda c: unicode(c.point_of_contact),
+ lambda c: six.text_type(c.point_of_contact),
)
c = Company.objects.all()[0]
diff --git a/tests/modeltests/field_defaults/tests.py b/tests/modeltests/field_defaults/tests.py
index 206d380e1e..5d9b45610e 100644
--- a/tests/modeltests/field_defaults/tests.py
+++ b/tests/modeltests/field_defaults/tests.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
from datetime import datetime
from django.test import TestCase
+from django.utils import six
from .models import Article
@@ -13,6 +14,6 @@ class DefaultTests(TestCase):
now = datetime.now()
a.save()
- self.assertTrue(isinstance(a.id, (int, long)))
+ self.assertTrue(isinstance(a.id, six.integer_types))
self.assertEqual(a.headline, "Default headline")
self.assertTrue((now - a.pub_date).seconds < 5)
diff --git a/tests/modeltests/field_subclassing/fields.py b/tests/modeltests/field_subclassing/fields.py
index b9987c0fab..a21085de9d 100644
--- a/tests/modeltests/field_subclassing/fields.py
+++ b/tests/modeltests/field_subclassing/fields.py
@@ -4,6 +4,7 @@ import json
from django.db import models
from django.utils.encoding import force_unicode
+from django.utils import six
class Small(object):
@@ -18,7 +19,7 @@ class Small(object):
return '%s%s' % (force_unicode(self.first), force_unicode(self.second))
def __str__(self):
- return unicode(self).encode('utf-8')
+ return six.text_type(self).encode('utf-8')
class SmallField(models.Field):
"""
@@ -41,7 +42,7 @@ class SmallField(models.Field):
return Small(value[0], value[1])
def get_db_prep_save(self, value, connection):
- return unicode(value)
+ return six.text_type(value)
def get_prep_lookup(self, lookup_type, value):
if lookup_type == 'exact':
@@ -66,7 +67,7 @@ class JSONField(models.TextField):
if not value:
return None
- if isinstance(value, basestring):
+ if isinstance(value, six.string_types):
value = json.loads(value)
return value
diff --git a/tests/modeltests/files/models.py b/tests/modeltests/files/models.py
index 4134472748..cefc7c7244 100644
--- a/tests/modeltests/files/models.py
+++ b/tests/modeltests/files/models.py
@@ -26,5 +26,5 @@ class Storage(models.Model):
normal = models.FileField(storage=temp_storage, upload_to='tests')
custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
- random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
+ random = models.FileField(storage=temp_storage, upload_to=random_upload_to, max_length=16)
default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')
diff --git a/tests/modeltests/files/tests.py b/tests/modeltests/files/tests.py
index 3e256f787f..565d4c8942 100644
--- a/tests/modeltests/files/tests.py
+++ b/tests/modeltests/files/tests.py
@@ -5,6 +5,7 @@ import shutil
import tempfile
from django.core.cache import cache
+from django.core.exceptions import ValidationError
from django.core.files import File
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
@@ -102,11 +103,23 @@ class FileStorageTests(TestCase):
obj4.random.save("random_file", ContentFile(b"random content"))
self.assertTrue(obj4.random.name.endswith("/random_file"))
- # Clean up the temporary files and dir.
- obj1.normal.delete()
- obj2.normal.delete()
- obj3.default.delete()
- obj4.random.delete()
+ def test_max_length(self):
+ """
+ Test that FileField validates the length of the generated file name
+ that will be stored in the database. Regression for #9893.
+ """
+ # upload_to = 'unused', so file names are saved as '456/xxxxx'.
+ # max_length = 16, so names longer than 12 characters are rejected.
+ s1 = Storage(random=SimpleUploadedFile(12 * 'x', b"content"))
+ s1.full_clean()
+ with self.assertRaises(ValidationError):
+ Storage(random=SimpleUploadedFile(13 * 'x', b"content")).full_clean()
+
+ # Ticket #18515: validation for an already saved file should not check
+ # against a regenerated file name (and potentially raise a ValidationError
+ # if max_length is exceeded
+ s1.save()
+ s1.full_clean()
class FileTests(unittest.TestCase):
diff --git a/tests/modeltests/fixtures_model_package/tests.py b/tests/modeltests/fixtures_model_package/tests.py
index 17538ed7e8..d147fe68a7 100644
--- a/tests/modeltests/fixtures_model_package/tests.py
+++ b/tests/modeltests/fixtures_model_package/tests.py
@@ -40,7 +40,7 @@ class TestNoInitialDataLoading(TransactionTestCase):
# Test presence of fixture (flush called by TransactionTestCase)
self.assertQuerysetEqual(
Book.objects.all(), [
- u'Achieving self-awareness of Python programs'
+ 'Achieving self-awareness of Python programs'
],
lambda a: a.name
)
diff --git a/tests/modeltests/generic_relations/tests.py b/tests/modeltests/generic_relations/tests.py
index d3de71d917..14871e4e09 100644
--- a/tests/modeltests/generic_relations/tests.py
+++ b/tests/modeltests/generic_relations/tests.py
@@ -231,7 +231,7 @@ class GenericRelationsTests(TestCase):
tag = TaggedItem.objects.create(content_object=tailless, tag="lizard")
self.assertEqual(tag.content_object, tailless)
-class CustomWidget(forms.CharField):
+class CustomWidget(forms.TextInput):
pass
class TaggedItemForm(forms.ModelForm):
diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py
index 3e5d61538a..b685750347 100644
--- a/tests/modeltests/lookup/models.py
+++ b/tests/modeltests/lookup/models.py
@@ -7,6 +7,7 @@ This demonstrates features of the database API.
from __future__ import unicode_literals
from django.db import models
+from django.utils import six
class Author(models.Model):
@@ -35,7 +36,7 @@ class Season(models.Model):
gt = models.IntegerField(null=True, blank=True)
def __unicode__(self):
- return unicode(self.year)
+ return six.text_type(self.year)
class Game(models.Model):
season = models.ForeignKey(Season, related_name='games')
diff --git a/tests/modeltests/m2m_and_m2o/models.py b/tests/modeltests/m2m_and_m2o/models.py
index 6c1f277811..92ed3fbcd9 100644
--- a/tests/modeltests/m2m_and_m2o/models.py
+++ b/tests/modeltests/m2m_and_m2o/models.py
@@ -6,6 +6,7 @@ Make sure to set ``related_name`` if you use relationships to the same table.
from __future__ import unicode_literals
from django.db import models
+from django.utils import six
class User(models.Model):
@@ -17,7 +18,7 @@ class Issue(models.Model):
client = models.ForeignKey(User, related_name='test_issue_client')
def __unicode__(self):
- return unicode(self.num)
+ return six.text_type(self.num)
class Meta:
ordering = ('num',)
diff --git a/tests/modeltests/m2m_intermediary/tests.py b/tests/modeltests/m2m_intermediary/tests.py
index cdc762246a..f261f23546 100644
--- a/tests/modeltests/m2m_intermediary/tests.py
+++ b/tests/modeltests/m2m_intermediary/tests.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
from datetime import datetime
from django.test import TestCase
+from django.utils import six
from .models import Reporter, Article, Writer
@@ -24,7 +25,7 @@ class M2MIntermediaryTests(TestCase):
("John Smith", "Main writer"),
("Jane Doe", "Contributor"),
],
- lambda w: (unicode(w.reporter), w.position)
+ lambda w: (six.text_type(w.reporter), w.position)
)
self.assertEqual(w1.reporter, r1)
self.assertEqual(w2.reporter, r2)
@@ -36,5 +37,5 @@ class M2MIntermediaryTests(TestCase):
r1.writer_set.all(), [
("John Smith", "Main writer")
],
- lambda w: (unicode(w.reporter), w.position)
+ lambda w: (six.text_type(w.reporter), w.position)
)
diff --git a/tests/modeltests/many_to_one/tests.py b/tests/modeltests/many_to_one/tests.py
index 257025583b..20bd1be0df 100644
--- a/tests/modeltests/many_to_one/tests.py
+++ b/tests/modeltests/many_to_one/tests.py
@@ -3,8 +3,9 @@ from __future__ import absolute_import
from copy import deepcopy
from datetime import datetime
-from django.core.exceptions import MultipleObjectsReturned
+from django.core.exceptions import MultipleObjectsReturned, FieldError
from django.test import TestCase
+from django.utils import six
from django.utils.translation import ugettext_lazy
from .models import Article, Reporter
@@ -421,6 +422,18 @@ class ManyToOneTests(TestCase):
lazy = ugettext_lazy('test')
reporter.article_set.create(headline=lazy,
pub_date=datetime(2011, 6, 10))
- notlazy = unicode(lazy)
+ notlazy = six.text_type(lazy)
article = reporter.article_set.get()
self.assertEqual(article.headline, notlazy)
+
+ def test_values_list_exception(self):
+ expected_message = "Cannot resolve keyword 'notafield' into field. Choices are: %s"
+
+ self.assertRaisesMessage(FieldError,
+ expected_message % ', '.join(Reporter._meta.get_all_field_names()),
+ Article.objects.values_list,
+ 'reporter__notafield')
+ self.assertRaisesMessage(FieldError,
+ expected_message % ', '.join(['EXTRA',] + Article._meta.get_all_field_names()),
+ Article.objects.extra(select={'EXTRA': 'EXTRA_SELECT'}).values_list,
+ 'notafield')
diff --git a/tests/modeltests/many_to_one_null/tests.py b/tests/modeltests/many_to_one_null/tests.py
index 1a404bde02..4de44b5e64 100644
--- a/tests/modeltests/many_to_one_null/tests.py
+++ b/tests/modeltests/many_to_one_null/tests.py
@@ -88,8 +88,8 @@ class ManyToOneNullTests(TestCase):
def test_clear_efficiency(self):
r = Reporter.objects.create()
- for _ in xrange(3):
+ for _ in range(3):
r.article_set.create()
with self.assertNumQueries(1):
r.article_set.clear()
- self.assertEqual(r.article_set.count(), 0) \ No newline at end of file
+ self.assertEqual(r.article_set.count(), 0)
diff --git a/tests/modeltests/model_forms/models.py b/tests/modeltests/model_forms/models.py
index a4ce86f184..8942b21f73 100644
--- a/tests/modeltests/model_forms/models.py
+++ b/tests/modeltests/model_forms/models.py
@@ -13,6 +13,7 @@ import tempfile
from django.core.files.storage import FileSystemStorage
from django.db import models
+from django.utils import six
temp_storage_dir = tempfile.mkdtemp(dir=os.environ['DJANGO_TEST_TEMP_DIR'])
@@ -226,7 +227,7 @@ class BigInt(models.Model):
biggie = models.BigIntegerField()
def __unicode__(self):
- return unicode(self.biggie)
+ return six.text_type(self.biggie)
class MarkupField(models.CharField):
def __init__(self, *args, **kwargs):
diff --git a/tests/modeltests/model_forms/tests.py b/tests/modeltests/model_forms/tests.py
index 281316a28e..fc37a25872 100644
--- a/tests/modeltests/model_forms/tests.py
+++ b/tests/modeltests/model_forms/tests.py
@@ -11,6 +11,7 @@ from django.db import connection
from django.forms.models import model_to_dict
from django.utils.unittest import skipUnless
from django.test import TestCase
+from django.utils import six
from .models import (Article, ArticleStatus, BetterWriter, BigInt, Book,
Category, CommaSeparatedInteger, CustomFieldForExclusionModel, DerivedBook,
@@ -653,7 +654,7 @@ class OldFormForXTests(TestCase):
# ManyToManyFields are represented by a MultipleChoiceField, ForeignKeys and any
# fields with the 'choices' attribute are represented by a ChoiceField.
f = ArticleForm(auto_id=False)
- self.assertHTMLEqual(unicode(f), '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
+ self.assertHTMLEqual(six.text_type(f), '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
<tr><th>Slug:</th><td><input type="text" name="slug" maxlength="50" /></td></tr>
<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
<tr><th>Writer:</th><td><select name="writer">
@@ -681,14 +682,14 @@ class OldFormForXTests(TestCase):
# a value of None. If a field isn't specified on a form, the object created
# from the form can't provide a value for that field!
f = PartialArticleForm(auto_id=False)
- self.assertHTMLEqual(unicode(f), '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
+ self.assertHTMLEqual(six.text_type(f), '''<tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
<tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>''')
# When the ModelForm is passed an instance, that instance's current values are
# inserted as 'initial' data in each Field.
w = Writer.objects.get(name='Mike Royko')
f = RoykoForm(auto_id=False, instance=w)
- self.assertHTMLEqual(unicode(f), '''<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br /><span class="helptext">Use both first and last names.</span></td></tr>''')
+ self.assertHTMLEqual(six.text_type(f), '''<tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br /><span class="helptext">Use both first and last names.</span></td></tr>''')
art = Article(
headline='Test article',
@@ -725,7 +726,7 @@ class OldFormForXTests(TestCase):
'headline': 'Test headline',
'slug': 'test-headline',
'pub_date': '1984-02-06',
- 'writer': unicode(w_royko.pk),
+ 'writer': six.text_type(w_royko.pk),
'article': 'Hello.'
}, instance=art)
self.assertEqual(f.errors, {})
@@ -808,9 +809,9 @@ class OldFormForXTests(TestCase):
'headline': 'New headline',
'slug': 'new-headline',
'pub_date': '1988-01-04',
- 'writer': unicode(w_royko.pk),
+ 'writer': six.text_type(w_royko.pk),
'article': 'Hello.',
- 'categories': [unicode(c1.id), unicode(c2.id)]
+ 'categories': [six.text_type(c1.id), six.text_type(c2.id)]
}, instance=new_art)
new_art = f.save()
self.assertEqual(new_art.id == art_id_1, True)
@@ -820,7 +821,7 @@ class OldFormForXTests(TestCase):
# Now, submit form data with no categories. This deletes the existing categories.
f = TestArticleForm({'headline': 'New headline', 'slug': 'new-headline', 'pub_date': '1988-01-04',
- 'writer': unicode(w_royko.pk), 'article': 'Hello.'}, instance=new_art)
+ 'writer': six.text_type(w_royko.pk), 'article': 'Hello.'}, instance=new_art)
new_art = f.save()
self.assertEqual(new_art.id == art_id_1, True)
new_art = Article.objects.get(id=art_id_1)
@@ -828,7 +829,7 @@ class OldFormForXTests(TestCase):
# Create a new article, with categories, via the form.
f = ArticleForm({'headline': 'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': '1967-11-01',
- 'writer': unicode(w_royko.pk), 'article': 'Test.', 'categories': [unicode(c1.id), unicode(c2.id)]})
+ 'writer': six.text_type(w_royko.pk), 'article': 'Test.', 'categories': [six.text_type(c1.id), six.text_type(c2.id)]})
new_art = f.save()
art_id_2 = new_art.id
self.assertEqual(art_id_2 not in (None, art_id_1), True)
@@ -837,7 +838,7 @@ class OldFormForXTests(TestCase):
# Create a new article, with no categories, via the form.
f = ArticleForm({'headline': 'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': '1967-11-01',
- 'writer': unicode(w_royko.pk), 'article': 'Test.'})
+ 'writer': six.text_type(w_royko.pk), 'article': 'Test.'})
new_art = f.save()
art_id_3 = new_art.id
self.assertEqual(art_id_3 not in (None, art_id_1, art_id_2), True)
@@ -847,7 +848,7 @@ class OldFormForXTests(TestCase):
# Create a new article, with categories, via the form, but use commit=False.
# The m2m data won't be saved until save_m2m() is invoked on the form.
f = ArticleForm({'headline': 'The walrus was Paul', 'slug': 'walrus-was-paul', 'pub_date': '1967-11-01',
- 'writer': unicode(w_royko.pk), 'article': 'Test.', 'categories': [unicode(c1.id), unicode(c2.id)]})
+ 'writer': six.text_type(w_royko.pk), 'article': 'Test.', 'categories': [six.text_type(c1.id), six.text_type(c2.id)]})
new_art = f.save(commit=False)
# Manually save the instance
@@ -1091,12 +1092,12 @@ class OldFormForXTests(TestCase):
<p><label for="id_age">Age:</label> <input type="text" name="age" id="id_age" /></p>''' % (w_woodward.pk, w_bernstein.pk, bw.pk, w_royko.pk))
data = {
- 'writer': unicode(w_woodward.pk),
+ 'writer': six.text_type(w_woodward.pk),
'age': '65',
}
form = WriterProfileForm(data)
instance = form.save()
- self.assertEqual(unicode(instance), 'Bob Woodward is 65')
+ self.assertEqual(six.text_type(instance), 'Bob Woodward is 65')
form = WriterProfileForm(instance=instance)
self.assertHTMLEqual(form.as_p(), '''<p><label for="id_writer">Writer:</label> <select name="writer" id="id_writer">
@@ -1376,7 +1377,7 @@ class OldFormForXTests(TestCase):
# Similar to a regular Form class you can define custom media to be used on
# the ModelForm.
f = ModelFormWithMedia()
- self.assertHTMLEqual(unicode(f.media), '''<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
+ self.assertHTMLEqual(six.text_type(f.media), '''<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="/some/form/javascript"></script>''')
f = CommaSeparatedIntegerForm({'field': '1,2,3'})
@@ -1445,7 +1446,7 @@ class OldFormForXTests(TestCase):
(22, 'Pear')))
form = InventoryForm(instance=core)
- self.assertHTMLEqual(unicode(form['parent']), '''<select name="parent" id="id_parent">
+ self.assertHTMLEqual(six.text_type(form['parent']), '''<select name="parent" id="id_parent">
<option value="">---------</option>
<option value="86" selected="selected">Apple</option>
<option value="87">Core</option>
@@ -1466,7 +1467,7 @@ class OldFormForXTests(TestCase):
self.assertEqual(CategoryForm.base_fields.keys(),
['description', 'url'])
- self.assertHTMLEqual(unicode(CategoryForm()), '''<tr><th><label for="id_description">Description:</label></th><td><input type="text" name="description" id="id_description" /></td></tr>
+ self.assertHTMLEqual(six.text_type(CategoryForm()), '''<tr><th><label for="id_description">Description:</label></th><td><input type="text" name="description" id="id_description" /></td></tr>
<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>''')
# to_field_name should also work on ModelMultipleChoiceField ##################
@@ -1481,5 +1482,5 @@ class OldFormForXTests(TestCase):
def test_model_field_that_returns_none_to_exclude_itself_with_explicit_fields(self):
self.assertEqual(CustomFieldForExclusionForm.base_fields.keys(), ['name'])
- self.assertHTMLEqual(unicode(CustomFieldForExclusionForm()),
+ self.assertHTMLEqual(six.text_type(CustomFieldForExclusionForm()),
'''<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="10" /></td></tr>''')
diff --git a/tests/modeltests/model_formsets/models.py b/tests/modeltests/model_formsets/models.py
index 055aa8dff1..a01a2da0fa 100644
--- a/tests/modeltests/model_formsets/models.py
+++ b/tests/modeltests/model_formsets/models.py
@@ -3,6 +3,7 @@ from __future__ import unicode_literals
import datetime
from django.db import models
+from django.utils import six
class Author(models.Model):
@@ -149,7 +150,7 @@ class Revision(models.Model):
unique_together = (("repository", "revision"),)
def __unicode__(self):
- return "%s (%s)" % (self.revision, unicode(self.repository))
+ return "%s (%s)" % (self.revision, six.text_type(self.repository))
# models for testing callable defaults (see bug #7975). If you define a model
# with a callable default value, you cannot rely on the initial value in a
diff --git a/tests/modeltests/model_formsets/tests.py b/tests/modeltests/model_formsets/tests.py
index 309dd3aaa2..e28560b237 100644
--- a/tests/modeltests/model_formsets/tests.py
+++ b/tests/modeltests/model_formsets/tests.py
@@ -10,6 +10,7 @@ from django.db import models
from django.forms.models import (_get_foreign_key, inlineformset_factory,
modelformset_factory)
from django.test import TestCase, skipUnlessDBFeature
+from django.utils import six
from .models import (Author, BetterAuthor, Book, BookWithCustomPK,
BookWithOptionalAltEditor, AlternateBook, AuthorMeeting, CustomPrimaryKey,
@@ -72,7 +73,7 @@ class DeletionTests(TestCase):
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '1',
'form-MAX_NUM_FORMS': '0',
- 'form-0-id': unicode(poet.id),
+ 'form-0-id': six.text_type(poet.id),
'form-0-name': 'x' * 1000,
}
formset = PoetFormSet(data, queryset=Poet.objects.all())
@@ -772,7 +773,7 @@ class ModelFormsetTest(TestCase):
'owner_set-TOTAL_FORMS': '3',
'owner_set-INITIAL_FORMS': '1',
'owner_set-MAX_NUM_FORMS': '',
- 'owner_set-0-auto_id': unicode(owner1.auto_id),
+ 'owner_set-0-auto_id': six.text_type(owner1.auto_id),
'owner_set-0-name': 'Joe Perry',
'owner_set-1-auto_id': '',
'owner_set-1-name': 'Jack Berry',
@@ -835,7 +836,7 @@ class ModelFormsetTest(TestCase):
'ownerprofile-TOTAL_FORMS': '1',
'ownerprofile-INITIAL_FORMS': '1',
'ownerprofile-MAX_NUM_FORMS': '1',
- 'ownerprofile-0-owner': unicode(owner1.auto_id),
+ 'ownerprofile-0-owner': six.text_type(owner1.auto_id),
'ownerprofile-0-age': '55',
}
formset = FormSet(data, instance=owner1)
@@ -993,8 +994,8 @@ class ModelFormsetTest(TestCase):
'membership_set-TOTAL_FORMS': '1',
'membership_set-INITIAL_FORMS': '0',
'membership_set-MAX_NUM_FORMS': '',
- 'membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
- 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
+ 'membership_set-0-date_joined': six.text_type(now.strftime('%Y-%m-%d %H:%M:%S')),
+ 'initial-membership_set-0-date_joined': six.text_type(now.strftime('%Y-%m-%d %H:%M:%S')),
'membership_set-0-karma': '',
}
formset = FormSet(data, instance=person)
@@ -1007,8 +1008,8 @@ class ModelFormsetTest(TestCase):
'membership_set-TOTAL_FORMS': '1',
'membership_set-INITIAL_FORMS': '0',
'membership_set-MAX_NUM_FORMS': '',
- 'membership_set-0-date_joined': unicode(one_day_later.strftime('%Y-%m-%d %H:%M:%S')),
- 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
+ 'membership_set-0-date_joined': six.text_type(one_day_later.strftime('%Y-%m-%d %H:%M:%S')),
+ 'initial-membership_set-0-date_joined': six.text_type(now.strftime('%Y-%m-%d %H:%M:%S')),
'membership_set-0-karma': '',
}
formset = FormSet(filled_data, instance=person)
@@ -1029,9 +1030,9 @@ class ModelFormsetTest(TestCase):
'membership_set-TOTAL_FORMS': '1',
'membership_set-INITIAL_FORMS': '0',
'membership_set-MAX_NUM_FORMS': '',
- 'membership_set-0-date_joined_0': unicode(now.strftime('%Y-%m-%d')),
- 'membership_set-0-date_joined_1': unicode(now.strftime('%H:%M:%S')),
- 'initial-membership_set-0-date_joined': unicode(now.strftime('%Y-%m-%d %H:%M:%S')),
+ 'membership_set-0-date_joined_0': six.text_type(now.strftime('%Y-%m-%d')),
+ 'membership_set-0-date_joined_1': six.text_type(now.strftime('%H:%M:%S')),
+ 'initial-membership_set-0-date_joined': six.text_type(now.strftime('%Y-%m-%d %H:%M:%S')),
'membership_set-0-karma': '',
}
formset = FormSet(data, instance=person)
diff --git a/tests/modeltests/model_inheritance/tests.py b/tests/modeltests/model_inheritance/tests.py
index 695d3f836c..16d2242fbe 100644
--- a/tests/modeltests/model_inheritance/tests.py
+++ b/tests/modeltests/model_inheritance/tests.py
@@ -4,6 +4,7 @@ from operator import attrgetter
from django.core.exceptions import FieldError
from django.test import TestCase
+from django.utils import six
from .models import (Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place,
Post, Restaurant, Student, StudentWorker, Supplier, Worker, MixinModel)
@@ -21,8 +22,8 @@ class ModelInheritanceTests(TestCase):
s = Student.objects.create(name="Pebbles", age=5, school_class="1B")
- self.assertEqual(unicode(w1), "Worker Fred")
- self.assertEqual(unicode(s), "Student Pebbles")
+ self.assertEqual(six.text_type(w1), "Worker Fred")
+ self.assertEqual(six.text_type(s), "Student Pebbles")
# The children inherit the Meta class of their parents (if they don't
# specify their own).
diff --git a/tests/modeltests/order_with_respect_to/models.py b/tests/modeltests/order_with_respect_to/models.py
index 59f01d4cd1..a4e20c2fe0 100644
--- a/tests/modeltests/order_with_respect_to/models.py
+++ b/tests/modeltests/order_with_respect_to/models.py
@@ -3,6 +3,7 @@ Tests for the order_with_respect_to Meta attribute.
"""
from django.db import models
+from django.utils import six
class Question(models.Model):
@@ -16,7 +17,7 @@ class Answer(models.Model):
order_with_respect_to = 'question'
def __unicode__(self):
- return unicode(self.text)
+ return six.text_type(self.text)
class Post(models.Model):
title = models.CharField(max_length=200)
diff --git a/tests/modeltests/pagination/tests.py b/tests/modeltests/pagination/tests.py
index 4d5d8680e4..cba8825ec4 100644
--- a/tests/modeltests/pagination/tests.py
+++ b/tests/modeltests/pagination/tests.py
@@ -4,6 +4,7 @@ from datetime import datetime
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.test import TestCase
+from django.utils import six
from .models import Article
@@ -32,7 +33,7 @@ class PaginationTests(TestCase):
def test_first_page(self):
paginator = Paginator(Article.objects.all(), 5)
p = paginator.page(1)
- self.assertEqual("<Page 1 of 2>", unicode(p))
+ self.assertEqual("<Page 1 of 2>", six.text_type(p))
self.assertQuerysetEqual(p.object_list, [
"<Article: Article 1>",
"<Article: Article 2>",
@@ -52,7 +53,7 @@ class PaginationTests(TestCase):
def test_last_page(self):
paginator = Paginator(Article.objects.all(), 5)
p = paginator.page(2)
- self.assertEqual("<Page 2 of 2>", unicode(p))
+ self.assertEqual("<Page 2 of 2>", six.text_type(p))
self.assertQuerysetEqual(p.object_list, [
"<Article: Article 6>",
"<Article: Article 7>",
@@ -109,7 +110,7 @@ class PaginationTests(TestCase):
self.assertEqual(3, paginator.num_pages)
self.assertEqual([1, 2, 3], paginator.page_range)
p = paginator.page(2)
- self.assertEqual("<Page 2 of 3>", unicode(p))
+ self.assertEqual("<Page 2 of 3>", six.text_type(p))
self.assertEqual([4, 5, 6], p.object_list)
self.assertTrue(p.has_next())
self.assertTrue(p.has_previous())
diff --git a/tests/modeltests/prefetch_related/tests.py b/tests/modeltests/prefetch_related/tests.py
index 43f195d357..8ae0a1e298 100644
--- a/tests/modeltests/prefetch_related/tests.py
+++ b/tests/modeltests/prefetch_related/tests.py
@@ -4,6 +4,7 @@ from django.contrib.contenttypes.models import ContentType
from django.db import connection
from django.test import TestCase
from django.test.utils import override_settings
+from django.utils import six
from .models import (Author, Book, Reader, Qualification, Teacher, Department,
TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge,
@@ -120,7 +121,7 @@ class PrefetchRelatedTests(TestCase):
"""
with self.assertNumQueries(3):
qs = Author.objects.prefetch_related('books__read_by')
- lists = [[[unicode(r) for r in b.read_by.all()]
+ lists = [[[six.text_type(r) for r in b.read_by.all()]
for b in a.books.all()]
for a in qs]
self.assertEqual(lists,
@@ -134,7 +135,7 @@ class PrefetchRelatedTests(TestCase):
def test_overriding_prefetch(self):
with self.assertNumQueries(3):
qs = Author.objects.prefetch_related('books', 'books__read_by')
- lists = [[[unicode(r) for r in b.read_by.all()]
+ lists = [[[six.text_type(r) for r in b.read_by.all()]
for b in a.books.all()]
for a in qs]
self.assertEqual(lists,
@@ -146,7 +147,7 @@ class PrefetchRelatedTests(TestCase):
])
with self.assertNumQueries(3):
qs = Author.objects.prefetch_related('books__read_by', 'books')
- lists = [[[unicode(r) for r in b.read_by.all()]
+ lists = [[[six.text_type(r) for r in b.read_by.all()]
for b in a.books.all()]
for a in qs]
self.assertEqual(lists,
@@ -164,7 +165,7 @@ class PrefetchRelatedTests(TestCase):
# Need a double
with self.assertNumQueries(3):
author = Author.objects.prefetch_related('books__read_by').get(name="Charlotte")
- lists = [[unicode(r) for r in b.read_by.all()]
+ lists = [[six.text_type(r) for r in b.read_by.all()]
for b in author.books.all()]
self.assertEqual(lists, [["Amy"], ["Belinda"]]) # Poems, Jane Eyre
@@ -175,7 +176,7 @@ class PrefetchRelatedTests(TestCase):
"""
with self.assertNumQueries(2):
qs = Author.objects.select_related('first_book').prefetch_related('first_book__read_by')
- lists = [[unicode(r) for r in a.first_book.read_by.all()]
+ lists = [[six.text_type(r) for r in a.first_book.read_by.all()]
for a in qs]
self.assertEqual(lists, [["Amy"],
["Amy"],
@@ -227,7 +228,7 @@ class DefaultManagerTests(TestCase):
# qualifications, since this will do one query per teacher.
qs = Department.objects.prefetch_related('teachers')
depts = "".join(["%s department: %s\n" %
- (dept.name, ", ".join(unicode(t) for t in dept.teachers.all()))
+ (dept.name, ", ".join(six.text_type(t) for t in dept.teachers.all()))
for dept in qs])
self.assertEqual(depts,
@@ -343,9 +344,9 @@ class MultiTableInheritanceTest(TestCase):
def test_foreignkey(self):
with self.assertNumQueries(2):
qs = AuthorWithAge.objects.prefetch_related('addresses')
- addresses = [[unicode(address) for address in obj.addresses.all()]
+ addresses = [[six.text_type(address) for address in obj.addresses.all()]
for obj in qs]
- self.assertEqual(addresses, [[unicode(self.authorAddress)], [], []])
+ self.assertEqual(addresses, [[six.text_type(self.authorAddress)], [], []])
def test_foreignkey_to_inherited(self):
with self.assertNumQueries(2):
@@ -356,19 +357,19 @@ class MultiTableInheritanceTest(TestCase):
def test_m2m_to_inheriting_model(self):
qs = AuthorWithAge.objects.prefetch_related('books_with_year')
with self.assertNumQueries(2):
- lst = [[unicode(book) for book in author.books_with_year.all()]
+ lst = [[six.text_type(book) for book in author.books_with_year.all()]
for author in qs]
qs = AuthorWithAge.objects.all()
- lst2 = [[unicode(book) for book in author.books_with_year.all()]
+ lst2 = [[six.text_type(book) for book in author.books_with_year.all()]
for author in qs]
self.assertEqual(lst, lst2)
qs = BookWithYear.objects.prefetch_related('aged_authors')
with self.assertNumQueries(2):
- lst = [[unicode(author) for author in book.aged_authors.all()]
+ lst = [[six.text_type(author) for author in book.aged_authors.all()]
for book in qs]
qs = BookWithYear.objects.all()
- lst2 = [[unicode(author) for author in book.aged_authors.all()]
+ lst2 = [[six.text_type(author) for author in book.aged_authors.all()]
for book in qs]
self.assertEqual(lst, lst2)
@@ -410,23 +411,23 @@ class ForeignKeyToFieldTest(TestCase):
def test_foreignkey(self):
with self.assertNumQueries(2):
qs = Author.objects.prefetch_related('addresses')
- addresses = [[unicode(address) for address in obj.addresses.all()]
+ addresses = [[six.text_type(address) for address in obj.addresses.all()]
for obj in qs]
- self.assertEqual(addresses, [[unicode(self.authorAddress)], [], []])
+ self.assertEqual(addresses, [[six.text_type(self.authorAddress)], [], []])
def test_m2m(self):
with self.assertNumQueries(3):
qs = Author.objects.all().prefetch_related('favorite_authors', 'favors_me')
favorites = [(
- [unicode(i_like) for i_like in author.favorite_authors.all()],
- [unicode(likes_me) for likes_me in author.favors_me.all()]
+ [six.text_type(i_like) for i_like in author.favorite_authors.all()],
+ [six.text_type(likes_me) for likes_me in author.favors_me.all()]
) for author in qs]
self.assertEqual(
favorites,
[
- ([unicode(self.author2)],[unicode(self.author3)]),
- ([unicode(self.author3)],[unicode(self.author1)]),
- ([unicode(self.author1)],[unicode(self.author2)])
+ ([six.text_type(self.author2)],[six.text_type(self.author3)]),
+ ([six.text_type(self.author3)],[six.text_type(self.author1)]),
+ ([six.text_type(self.author1)],[six.text_type(self.author2)])
]
)
diff --git a/tests/modeltests/save_delete_hooks/tests.py b/tests/modeltests/save_delete_hooks/tests.py
index 377d9eec03..42e0d4a80e 100644
--- a/tests/modeltests/save_delete_hooks/tests.py
+++ b/tests/modeltests/save_delete_hooks/tests.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import
from django.test import TestCase
+from django.utils import six
from .models import Person
@@ -19,7 +20,7 @@ class SaveDeleteHookTests(TestCase):
Person.objects.all(), [
"John Smith",
],
- unicode
+ six.text_type
)
p.delete()
diff --git a/tests/modeltests/select_for_update/tests.py b/tests/modeltests/select_for_update/tests.py
index 243f6b50e7..e3e4d9e7e2 100644
--- a/tests/modeltests/select_for_update/tests.py
+++ b/tests/modeltests/select_for_update/tests.py
@@ -36,6 +36,8 @@ class SelectForUpdateTests(TransactionTestCase):
# issuing a SELECT ... FOR UPDATE will block.
new_connections = ConnectionHandler(settings.DATABASES)
self.new_connection = new_connections[DEFAULT_DB_ALIAS]
+ self.new_connection.enter_transaction_management()
+ self.new_connection.managed(True)
# We need to set settings.DEBUG to True so we can capture
# the output SQL to examine.
@@ -48,6 +50,7 @@ class SelectForUpdateTests(TransactionTestCase):
# this in the course of their run.
transaction.managed(False)
transaction.leave_transaction_management()
+ self.new_connection.leave_transaction_management()
except transaction.TransactionManagementError:
pass
self.new_connection.close()
@@ -66,7 +69,7 @@ class SelectForUpdateTests(TransactionTestCase):
'for_update': self.new_connection.ops.for_update_sql(),
}
self.cursor.execute(sql, ())
- result = self.cursor.fetchone()
+ self.cursor.fetchone()
def end_blocking_transaction(self):
# Roll back the blocking transaction.
@@ -203,7 +206,7 @@ class SelectForUpdateTests(TransactionTestCase):
sanity_count += 1
time.sleep(1)
if sanity_count >= 10:
- raise ValueError, 'Thread did not run and block'
+ raise ValueError('Thread did not run and block')
# Check the person hasn't been updated. Since this isn't
# using FOR UPDATE, it won't block.
diff --git a/tests/modeltests/serializers/models.py b/tests/modeltests/serializers/models.py
index 3549be1b4f..9da099c027 100644
--- a/tests/modeltests/serializers/models.py
+++ b/tests/modeltests/serializers/models.py
@@ -10,6 +10,7 @@ from __future__ import unicode_literals
from decimal import Decimal
from django.db import models
+from django.utils import six
class Category(models.Model):
@@ -100,7 +101,7 @@ class TeamField(models.CharField):
super(TeamField, self).__init__(max_length=100)
def get_db_prep_save(self, value, connection):
- return unicode(value.title)
+ return six.text_type(value.title)
def to_python(self, value):
if isinstance(value, Team):
diff --git a/tests/modeltests/serializers/tests.py b/tests/modeltests/serializers/tests.py
index 13cf1e7e17..9177227539 100644
--- a/tests/modeltests/serializers/tests.py
+++ b/tests/modeltests/serializers/tests.py
@@ -10,6 +10,7 @@ from django.conf import settings
from django.core import serializers
from django.db import transaction, connection
from django.test import TestCase, TransactionTestCase, Approximate
+from django.utils import six
from django.utils import unittest
from .models import (Category, Author, Article, AuthorProfile, Actor, Movie,
@@ -295,7 +296,7 @@ class XmlSerializerTestCase(SerializersTestBase, TestCase):
def _comparison_value(value):
# The XML serializer handles everything as strings, so comparisons
# need to be performed on the stringified value
- return unicode(value)
+ return six.text_type(value)
@staticmethod
def _validate_output(serial_str):
@@ -461,7 +462,7 @@ else:
# yaml.safe_load will return non-string objects for some
# of the fields we are interested in, this ensures that
# everything comes back as a string
- if isinstance(field_value, basestring):
+ if isinstance(field_value, six.string_types):
ret_list.append(field_value)
else:
ret_list.append(str(field_value))
diff --git a/tests/modeltests/signals/tests.py b/tests/modeltests/signals/tests.py
index 29563dc363..58f25c2868 100644
--- a/tests/modeltests/signals/tests.py
+++ b/tests/modeltests/signals/tests.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
from django.db.models import signals
from django.dispatch import receiver
from django.test import TestCase
+from django.utils import six
from .models import Person, Car
@@ -144,7 +145,7 @@ class SignalTests(TestCase):
Person.objects.all(), [
"James Jones",
],
- unicode
+ six.text_type
)
signals.post_delete.disconnect(post_delete_test)
diff --git a/tests/modeltests/test_client/views.py b/tests/modeltests/test_client/views.py
index 6ea7213a02..477a27b178 100644
--- a/tests/modeltests/test_client/views.py
+++ b/tests/modeltests/test_client/views.py
@@ -1,3 +1,7 @@
+try:
+ from urllib.parse import urlencode
+except ImportError: # Python 2
+ from urllib import urlencode
from xml.dom.minidom import parseString
from django.contrib.auth.decorators import login_required, permission_required
@@ -9,7 +13,6 @@ from django.shortcuts import render_to_response
from django.template import Context, Template
from django.utils.decorators import method_decorator
-
def get_view(request):
"A simple view that expects a GET request, and returns a rendered template"
t = Template('This is a test. {{ var }} is the value.', name='GET Template')
@@ -58,7 +61,6 @@ def raw_post_view(request):
def redirect_view(request):
"A view that redirects all requests to the GET view"
if request.GET:
- from urllib import urlencode
query = '?' + urlencode(request.GET, True)
else:
query = ''
diff --git a/tests/modeltests/update/models.py b/tests/modeltests/update/models.py
index 92156a5553..b93e4a7aae 100644
--- a/tests/modeltests/update/models.py
+++ b/tests/modeltests/update/models.py
@@ -4,6 +4,7 @@ updates.
"""
from django.db import models
+from django.utils import six
class DataPoint(models.Model):
@@ -12,14 +13,14 @@ class DataPoint(models.Model):
another_value = models.CharField(max_length=20, blank=True)
def __unicode__(self):
- return unicode(self.name)
+ return six.text_type(self.name)
class RelatedPoint(models.Model):
name = models.CharField(max_length=20)
data = models.ForeignKey(DataPoint)
def __unicode__(self):
- return unicode(self.name)
+ return six.text_type(self.name)
class A(models.Model):
diff --git a/tests/modeltests/update_only_fields/tests.py b/tests/modeltests/update_only_fields/tests.py
index e843bd7ab9..bce53ca621 100644
--- a/tests/modeltests/update_only_fields/tests.py
+++ b/tests/modeltests/update_only_fields/tests.py
@@ -55,6 +55,14 @@ class UpdateOnlyFieldsTests(TestCase):
self.assertEqual(e3.name, 'Ian')
self.assertEqual(e3.profile, profile_receptionist)
+ with self.assertNumQueries(1):
+ e3.profile = profile_boss
+ e3.save(update_fields=['profile_id'])
+
+ e4 = Employee.objects.get(pk=e3.pk)
+ self.assertEqual(e4.profile, profile_boss)
+ self.assertEqual(e4.profile_id, profile_boss.pk)
+
def test_update_fields_inheritance_with_proxy_model(self):
profile_boss = Profile.objects.create(name='Boss', salary=3000)
profile_receptionist = Profile.objects.create(name='Receptionist', salary=1000)
diff --git a/tests/regressiontests/admin_changelist/models.py b/tests/regressiontests/admin_changelist/models.py
index dcc343bb6a..487db50689 100644
--- a/tests/regressiontests/admin_changelist/models.py
+++ b/tests/regressiontests/admin_changelist/models.py
@@ -1,7 +1,8 @@
from django.db import models
class Event(models.Model):
- date = models.DateField()
+ # 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)
diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
index 62166ce174..1ed963aaf2 100644
--- a/tests/regressiontests/admin_changelist/tests.py
+++ b/tests/regressiontests/admin_changelist/tests.py
@@ -10,6 +10,7 @@ from django.template import Context, Template
from django.test import TestCase
from django.test.client import RequestFactory
from django.utils import formats
+from django.utils import six
from .admin import (ChildAdmin, QuartetAdmin, BandAdmin, ChordsBandAdmin,
GroupAdmin, ParentAdmin, DynamicListDisplayChildAdmin,
@@ -339,7 +340,7 @@ class ChangeListTests(TestCase):
event = Event.objects.create(date=datetime.date.today())
response = self.client.get('/admin/admin_changelist/event/')
self.assertContains(response, formats.localize(event.date))
- self.assertNotContains(response, unicode(event.date))
+ self.assertNotContains(response, six.text_type(event.date))
def test_dynamic_list_display(self):
"""
@@ -443,9 +444,9 @@ class ChangeListTests(TestCase):
request = self._mocked_authenticated_request('/swallow/', superuser)
response = model_admin.changelist_view(request)
# just want to ensure it doesn't blow up during rendering
- self.assertContains(response, unicode(swallow.origin))
- self.assertContains(response, unicode(swallow.load))
- self.assertContains(response, unicode(swallow.speed))
+ self.assertContains(response, six.text_type(swallow.origin))
+ self.assertContains(response, six.text_type(swallow.load))
+ self.assertContains(response, six.text_type(swallow.speed))
def test_deterministic_order_for_unordered_model(self):
"""
diff --git a/tests/regressiontests/admin_scripts/custom_templates/project_template/additional_dir/extra.py b/tests/regressiontests/admin_scripts/custom_templates/project_template/additional_dir/extra.py
new file mode 100644
index 0000000000..6b553f190f
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/custom_templates/project_template/additional_dir/extra.py
@@ -0,0 +1 @@
+# this file uses the {{ extra }} variable
diff --git a/tests/regressiontests/admin_scripts/management/commands/custom_startproject.py b/tests/regressiontests/admin_scripts/management/commands/custom_startproject.py
new file mode 100644
index 0000000000..80c6d6b805
--- /dev/null
+++ b/tests/regressiontests/admin_scripts/management/commands/custom_startproject.py
@@ -0,0 +1,11 @@
+from optparse import make_option
+
+from django.core.management.commands.startproject import Command as BaseCommand
+
+
+class Command(BaseCommand):
+ option_list = BaseCommand.option_list + (
+ make_option('--extra',
+ action='store', dest='extra',
+ help='An arbitrary extra value passed to the context'),
+ )
diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py
index ecb16df53a..546fa7d79c 100644
--- a/tests/regressiontests/admin_scripts/tests.py
+++ b/tests/regressiontests/admin_scripts/tests.py
@@ -1541,6 +1541,24 @@ class StartProject(LiveServerTestCase, AdminScriptTestCase):
self.assertIn("project_name = 'another_project'", content)
self.assertIn("project_directory = '%s'" % testproject_dir, content)
+ def test_no_escaping_of_project_variables(self):
+ "Make sure template context variables are not html escaped"
+ # We're using a custom command so we need the alternate settings
+ self.write_settings('alternate_settings.py')
+ template_path = os.path.join(test_dir, 'admin_scripts', 'custom_templates', 'project_template')
+ args = ['custom_startproject', '--template', template_path, 'another_project', 'project_dir', '--extra', '<&>', '--settings=alternate_settings']
+ testproject_dir = os.path.join(test_dir, 'project_dir')
+ os.mkdir(testproject_dir)
+ out, err = self.run_manage(args)
+ self.addCleanup(shutil.rmtree, testproject_dir)
+ self.assertNoOutput(err)
+ test_manage_py = os.path.join(testproject_dir, 'additional_dir', 'extra.py')
+ with open(test_manage_py, 'r') as fp:
+ content = fp.read()
+ self.assertIn("<&>", content)
+ # tidy up alternate settings
+ self.remove_settings('alternate_settings.py')
+
def test_custom_project_destination_missing(self):
"""
Make sure an exception is raised when the provided
diff --git a/tests/regressiontests/admin_util/models.py b/tests/regressiontests/admin_util/models.py
index 0e81df3817..5541097022 100644
--- a/tests/regressiontests/admin_util/models.py
+++ b/tests/regressiontests/admin_util/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django.utils import six
class Article(models.Model):
@@ -22,7 +23,7 @@ class Count(models.Model):
parent = models.ForeignKey('self', null=True)
def __unicode__(self):
- return unicode(self.num)
+ return six.text_type(self.num)
class Event(models.Model):
date = models.DateTimeField(auto_now_add=True)
diff --git a/tests/regressiontests/admin_util/tests.py b/tests/regressiontests/admin_util/tests.py
index ba2be363ca..6b6dad4336 100644
--- a/tests/regressiontests/admin_util/tests.py
+++ b/tests/regressiontests/admin_util/tests.py
@@ -15,6 +15,7 @@ from django.test import TestCase
from django.utils import unittest
from django.utils.formats import localize
from django.utils.safestring import mark_safe
+from django.utils import six
from .models import Article, Count, Event, Location
@@ -249,17 +250,17 @@ class UtilTests(unittest.TestCase):
log_entry.action_flag = admin.models.ADDITION
self.assertTrue(
- unicode(log_entry).startswith('Added ')
+ six.text_type(log_entry).startswith('Added ')
)
log_entry.action_flag = admin.models.CHANGE
self.assertTrue(
- unicode(log_entry).startswith('Changed ')
+ six.text_type(log_entry).startswith('Changed ')
)
log_entry.action_flag = admin.models.DELETION
self.assertTrue(
- unicode(log_entry).startswith('Deleted ')
+ six.text_type(log_entry).startswith('Deleted ')
)
def test_safestring_in_field_label(self):
diff --git a/tests/regressiontests/admin_views/admin.py b/tests/regressiontests/admin_views/admin.py
index 01a19e6373..6ec933f89b 100644
--- a/tests/regressiontests/admin_views/admin.py
+++ b/tests/regressiontests/admin_views/admin.py
@@ -27,7 +27,7 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
Album, Question, Answer, ComplexSortedPerson, PrePopulatedPostLargeSlug,
AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated,
- RelatedPrepopulated)
+ RelatedPrepopulated, UndeletableObject)
def callable_year(dt_value):
@@ -569,6 +569,11 @@ class UnorderedObjectAdmin(admin.ModelAdmin):
list_per_page = 2
+class UndeletableObjectAdmin(admin.ModelAdmin):
+ def change_view(self, *args, **kwargs):
+ kwargs['extra_context'] = {'show_delete': False}
+ return super(UndeletableObjectAdmin, self).change_view(*args, **kwargs)
+
site = admin.AdminSite(name="admin")
site.register(Article, ArticleAdmin)
@@ -616,6 +621,7 @@ site.register(OtherStory, OtherStoryAdmin)
site.register(Report, ReportAdmin)
site.register(MainPrepopulated, MainPrepopulatedAdmin)
site.register(UnorderedObject, UnorderedObjectAdmin)
+site.register(UndeletableObject, UndeletableObjectAdmin)
# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
# That way we cover all four cases:
diff --git a/tests/regressiontests/admin_views/customadmin.py b/tests/regressiontests/admin_views/customadmin.py
index d205e0e290..142527b022 100644
--- a/tests/regressiontests/admin_views/customadmin.py
+++ b/tests/regressiontests/admin_views/customadmin.py
@@ -48,3 +48,4 @@ site.register(models.Thing, base_admin.ThingAdmin)
site.register(models.Fabric, base_admin.FabricAdmin)
site.register(models.ChapterXtra1, base_admin.ChapterXtra1Admin)
site.register(User, UserLimitedAdmin)
+site.register(models.UndeletableObject, base_admin.UndeletableObjectAdmin)
diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
index ebb637ac6b..aee193b572 100644
--- a/tests/regressiontests/admin_views/models.py
+++ b/tests/regressiontests/admin_views/models.py
@@ -101,7 +101,7 @@ class ModelWithStringPrimaryKey(models.Model):
return self.string_pk
def get_absolute_url(self):
- return u'/dummy/%s/' % self.string_pk
+ return '/dummy/%s/' % self.string_pk
class Color(models.Model):
@@ -611,3 +611,10 @@ 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
+ Refs #10057.
+ """
+ name = models.CharField(max_length=255)
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
index f074d77b11..09be55baba 100644
--- a/tests/regressiontests/admin_views/tests.py
+++ b/tests/regressiontests/admin_views/tests.py
@@ -4,7 +4,10 @@ from __future__ import absolute_import, unicode_literals
import os
import re
import datetime
-import urlparse
+try:
+ from urllib.parse import urljoin
+except ImportError: # Python 2
+ from urlparse import urljoin
from django.conf import settings, global_settings
from django.core import mail
@@ -30,6 +33,7 @@ from django.utils.cache import get_max_age
from django.utils.encoding import iri_to_uri
from django.utils.html import escape
from django.utils.http import urlencode
+from django.utils import six
from django.test.utils import override_settings
# local test models
@@ -41,7 +45,8 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount,
FoodDelivery, RowLevelChangePermissionModel, Paper, CoverLetter, Story,
OtherStory, ComplexSortedPerson, Parent, Child, AdminOrderedField,
AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable,
- Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject)
+ Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject,
+ UndeletableObject)
ERROR_MESSAGE = "Please enter the correct username and password \
@@ -588,6 +593,16 @@ class AdminViewBasicTest(TestCase):
self.assertFalse(reverse('admin:password_change') in response.content,
msg='The "change password" link should not be displayed if a user does not have a usable password.')
+ def test_change_view_with_show_delete_extra_context(self):
+ """
+ Ensured that the 'show_delete' context variable in the admin's change
+ view actually controls the display of the delete button.
+ Refs #10057.
+ """
+ instance = UndeletableObject.objects.create(name='foo')
+ response = self.client.get('/test_admin/%s/admin_views/undeletableobject/%d/' %
+ (self.urlbit, instance.pk))
+ self.assertNotContains(response, 'deletelink')
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
class AdminViewFormUrlTest(TestCase):
@@ -1344,15 +1359,20 @@ class AdminViewStringPrimaryKeyTest(TestCase):
def setUp(self):
self.client.login(username='super', password='secret')
content_type_pk = ContentType.objects.get_for_model(ModelWithStringPrimaryKey).pk
- LogEntry.objects.log_action(100, content_type_pk, self.pk, self.pk, 2, change_message='')
+ LogEntry.objects.log_action(100, content_type_pk, self.pk, self.pk, 2, change_message='Changed something')
def tearDown(self):
self.client.logout()
def test_get_history_view(self):
- "Retrieving the history for the object using urlencoded form of primary key should work"
+ """
+ Retrieving the history for an object using urlencoded form of primary
+ key should work.
+ Refs #12349, #18550.
+ """
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/history/' % quote(self.pk))
self.assertContains(response, escape(self.pk))
+ self.assertContains(response, 'Changed something')
self.assertEqual(response.status_code, 200)
def test_get_change_view(self):
@@ -1364,19 +1384,19 @@ class AdminViewStringPrimaryKeyTest(TestCase):
def test_changelist_to_changeform_link(self):
"The link from the changelist referring to the changeform of the object should be quoted"
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/')
- should_contain = """<th><a href="%s/">%s</a></th></tr>""" % (quote(self.pk), escape(self.pk))
+ should_contain = """<th><a href="%s/">%s</a></th></tr>""" % (escape(quote(self.pk)), escape(self.pk))
self.assertContains(response, should_contain)
def test_recentactions_link(self):
"The link from the recent actions list referring to the changeform of the object should be quoted"
response = self.client.get('/test_admin/admin/')
- should_contain = """<a href="admin_views/modelwithstringprimarykey/%s/">%s</a>""" % (quote(self.pk), escape(self.pk))
+ should_contain = """<a href="admin_views/modelwithstringprimarykey/%s/">%s</a>""" % (escape(quote(self.pk)), escape(self.pk))
self.assertContains(response, should_contain)
def test_recentactions_without_content_type(self):
"If a LogEntry is missing content_type it will not display it in span tag under the hyperlink."
response = self.client.get('/test_admin/admin/')
- should_contain = """<a href="admin_views/modelwithstringprimarykey/%s/">%s</a>""" % (quote(self.pk), escape(self.pk))
+ should_contain = """<a href="admin_views/modelwithstringprimarykey/%s/">%s</a>""" % (escape(quote(self.pk)), escape(self.pk))
self.assertContains(response, should_contain)
should_contain = "Model with string primary key" # capitalized in Recent Actions
self.assertContains(response, should_contain)
@@ -1397,7 +1417,7 @@ class AdminViewStringPrimaryKeyTest(TestCase):
"The link from the delete confirmation page referring back to the changeform of the object should be quoted"
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/delete/' % quote(self.pk))
# this URL now comes through reverse(), thus iri_to_uri encoding
- should_contain = """/%s/">%s</a>""" % (iri_to_uri(quote(self.pk)), escape(self.pk))
+ should_contain = """/%s/">%s</a>""" % (escape(iri_to_uri(quote(self.pk))), escape(self.pk))
self.assertContains(response, should_contain)
def test_url_conflicts_with_add(self):
@@ -2462,7 +2482,7 @@ class AdminCustomQuerysetTest(TestCase):
response = self.client.post('/test_admin/admin/admin_views/paper/%s/' % p.pk,
post_data, follow=True)
self.assertEqual(response.status_code, 200)
- # Message should contain non-ugly model name. Instance representation is set by unicode() (ugly)
+ # Message should contain non-ugly model name. Instance representation is set by six.text_type() (ugly)
self.assertContains(response, '<li class="info">The paper &quot;Paper_Deferred_author object&quot; was changed successfully.</li>', html=True)
# defer() is used in ModelAdmin.queryset()
@@ -2514,8 +2534,8 @@ class AdminInlineFileUploadTest(TestCase):
"pictures-TOTAL_FORMS": "2",
"pictures-INITIAL_FORMS": "1",
"pictures-MAX_NUM_FORMS": "0",
- "pictures-0-id": unicode(self.picture.id),
- "pictures-0-gallery": unicode(self.gallery.id),
+ "pictures-0-id": six.text_type(self.picture.id),
+ "pictures-0-gallery": six.text_type(self.gallery.id),
"pictures-0-name": "Test Picture",
"pictures-0-image": "",
"pictures-1-id": "",
@@ -3182,7 +3202,7 @@ class RawIdFieldsTest(TestCase):
popup_url = m.groups()[0].replace("&amp;", "&")
# Handle relative links
- popup_url = urlparse.urljoin(response.request['PATH_INFO'], popup_url)
+ popup_url = urljoin(response.request['PATH_INFO'], popup_url)
# Get the popup
response2 = self.client.get(popup_url)
self.assertContains(response2, "Spain")
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index c6d28ab135..a6425c5591 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -16,6 +16,8 @@ from django.db.utils import ConnectionHandler, DatabaseError, load_backend
from django.test import (TestCase, skipUnlessDBFeature, skipIfDBFeature,
TransactionTestCase)
from django.test.utils import override_settings
+from django.utils import six
+from django.utils.six.moves import xrange
from django.utils import unittest
from . import models
@@ -50,7 +52,7 @@ class OracleChecks(unittest.TestCase):
# than 4000 chars and read it properly
c = connection.cursor()
c.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
- long_str = ''.join([unicode(x) for x in xrange(4000)])
+ long_str = ''.join([six.text_type(x) for x in xrange(4000)])
c.execute('INSERT INTO ltext VALUES (%s)',[long_str])
c.execute('SELECT text FROM ltext')
row = c.fetchone()
@@ -66,6 +68,18 @@ class OracleChecks(unittest.TestCase):
self.assertEqual(connection.connection.encoding, "UTF-8")
self.assertEqual(connection.connection.nencoding, "UTF-8")
+ @unittest.skipUnless(connection.vendor == 'oracle',
+ "No need to check Oracle connection semantics")
+ def test_order_of_nls_parameters(self):
+ # an 'almost right' datetime should work with configured
+ # NLS parameters as per #18465.
+ c = connection.cursor()
+ query = "select 1 from dual where '1936-12-29 00:00' < sysdate"
+ # Test that the query succeeds without errors - pre #18465 this
+ # wasn't the case.
+ c.execute(query)
+ self.assertEqual(c.fetchone()[0], 1)
+
class MySQLTests(TestCase):
@unittest.skipUnless(connection.vendor == 'mysql',
"Test valid only for MySQL")
@@ -142,7 +156,7 @@ class LastExecutedQueryTest(TestCase):
sql, params = tags.query.sql_with_params()
cursor = tags.query.get_compiler('default').execute_sql(None)
last_sql = cursor.db.ops.last_executed_query(cursor, sql, params)
- self.assertTrue(isinstance(last_sql, unicode))
+ self.assertTrue(isinstance(last_sql, six.text_type))
class ParameterHandlingTest(TestCase):
@@ -518,7 +532,7 @@ class ThreadTests(TestCase):
from django.db import connection
connection.cursor()
connections_set.add(connection.connection)
- for x in xrange(2):
+ for x in range(2):
t = threading.Thread(target=runner)
t.start()
t.join()
@@ -545,7 +559,7 @@ class ThreadTests(TestCase):
# main thread.
conn.allow_thread_sharing = True
connections_set.add(conn)
- for x in xrange(2):
+ for x in range(2):
t = threading.Thread(target=runner)
t.start()
t.join()
diff --git a/tests/regressiontests/bulk_create/models.py b/tests/regressiontests/bulk_create/models.py
index a4c611d537..bc685bbbe4 100644
--- a/tests/regressiontests/bulk_create/models.py
+++ b/tests/regressiontests/bulk_create/models.py
@@ -18,4 +18,8 @@ class Pizzeria(Restaurant):
pass
class State(models.Model):
- two_letter_code = models.CharField(max_length=2, primary_key=True) \ No newline at end of file
+ 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/regressiontests/bulk_create/tests.py b/tests/regressiontests/bulk_create/tests.py
index 0b55f637a4..33108ea9b0 100644
--- a/tests/regressiontests/bulk_create/tests.py
+++ b/tests/regressiontests/bulk_create/tests.py
@@ -2,9 +2,11 @@ from __future__ import absolute_import
from operator import attrgetter
-from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
+from django.db import connection
+from django.test import TestCase, skipIfDBFeature
+from django.test.utils import override_settings
-from .models import Country, Restaurant, Pizzeria, State
+from .models import Country, Restaurant, Pizzeria, State, TwoFields
class BulkCreateTests(TestCase):
@@ -27,7 +29,6 @@ class BulkCreateTests(TestCase):
self.assertEqual(created, [])
self.assertEqual(Country.objects.count(), 4)
- @skipUnlessDBFeature("has_bulk_insert")
def test_efficiency(self):
with self.assertNumQueries(1):
Country.objects.bulk_create(self.data)
@@ -69,3 +70,42 @@ class BulkCreateTests(TestCase):
invalid_country = Country(id=0, name='Poland', iso_two_letter='PL')
with self.assertRaises(ValueError):
Country.objects.bulk_create([valid_country, invalid_country])
+
+ def test_large_batch(self):
+ with override_settings(DEBUG=True):
+ connection.queries = []
+ TwoFields.objects.bulk_create([
+ TwoFields(f1=i, f2=i+1) for i in range(0, 1001)
+ ])
+ self.assertTrue(len(connection.queries) < 10)
+ self.assertEqual(TwoFields.objects.count(), 1001)
+ self.assertEqual(
+ TwoFields.objects.filter(f1__gte=450, f1__lte=550).count(),
+ 101)
+ self.assertEqual(TwoFields.objects.filter(f2__gte=901).count(), 101)
+
+ def test_large_batch_mixed(self):
+ """
+ Test inserting a large batch with objects having primary key set
+ mixed together with objects without PK set.
+ """
+ with override_settings(DEBUG=True):
+ connection.queries = []
+ TwoFields.objects.bulk_create([
+ TwoFields(id=i if i % 2 == 0 else None, f1=i, f2=i+1)
+ for i in range(100000, 101000)])
+ self.assertTrue(len(connection.queries) < 10)
+ self.assertEqual(TwoFields.objects.count(), 1000)
+ # We can't assume much about the ID's created, except that the above
+ # created IDs must exist.
+ id_range = range(100000, 101000, 2)
+ self.assertEqual(TwoFields.objects.filter(id__in=id_range).count(), 500)
+ self.assertEqual(TwoFields.objects.exclude(id__in=id_range).count(), 500)
+
+ def test_explicit_batch_size(self):
+ objs = [TwoFields(f1=i, f2=i) for i in range(0, 100)]
+ with self.assertNumQueries(2):
+ TwoFields.objects.bulk_create(objs, 50)
+ TwoFields.objects.all().delete()
+ with self.assertNumQueries(1):
+ TwoFields.objects.bulk_create(objs, len(objs))
diff --git a/tests/regressiontests/conditional_processing/models.py b/tests/regressiontests/conditional_processing/models.py
index 97aeff5eaa..d1a8ac605b 100644
--- a/tests/regressiontests/conditional_processing/models.py
+++ b/tests/regressiontests/conditional_processing/models.py
@@ -143,14 +143,14 @@ class HttpDateProcessing(unittest.TestCase):
def testParsingRfc1123(self):
parsed = parse_http_date('Sun, 06 Nov 1994 08:49:37 GMT')
self.assertEqual(datetime.utcfromtimestamp(parsed),
- datetime(1994, 11, 06, 8, 49, 37))
+ datetime(1994, 11, 6, 8, 49, 37))
def testParsingRfc850(self):
parsed = parse_http_date('Sunday, 06-Nov-94 08:49:37 GMT')
self.assertEqual(datetime.utcfromtimestamp(parsed),
- datetime(1994, 11, 06, 8, 49, 37))
+ datetime(1994, 11, 6, 8, 49, 37))
def testParsingAsctime(self):
parsed = parse_http_date('Sun Nov 6 08:49:37 1994')
self.assertEqual(datetime.utcfromtimestamp(parsed),
- datetime(1994, 11, 06, 8, 49, 37))
+ datetime(1994, 11, 6, 8, 49, 37))
diff --git a/tests/regressiontests/datatypes/tests.py b/tests/regressiontests/datatypes/tests.py
index f8f6802041..f0ec5f3c0a 100644
--- a/tests/regressiontests/datatypes/tests.py
+++ b/tests/regressiontests/datatypes/tests.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import, unicode_literals
import datetime
from django.test import TestCase, skipIfDBFeature
+from django.utils import six
from django.utils.timezone import utc
from .models import Donut, RumBaba
@@ -73,7 +74,7 @@ class DataTypesTestCase(TestCase):
database should be unicode."""
d = Donut.objects.create(name='Jelly Donut', review='Outstanding')
newd = Donut.objects.get(id=d.id)
- self.assertTrue(isinstance(newd.review, unicode))
+ self.assertTrue(isinstance(newd.review, six.text_type))
@skipIfDBFeature('supports_timezones')
def test_error_on_timezone(self):
diff --git a/tests/regressiontests/defaultfilters/tests.py b/tests/regressiontests/defaultfilters/tests.py
index ffa0a01132..2852572d32 100644
--- a/tests/regressiontests/defaultfilters/tests.py
+++ b/tests/regressiontests/defaultfilters/tests.py
@@ -6,6 +6,7 @@ import decimal
from django.template.defaultfilters import *
from django.test import TestCase
+from django.utils import six
from django.utils import unittest, translation
from django.utils.safestring import SafeData
@@ -48,13 +49,13 @@ class DefaultFiltersTests(TestCase):
'0.00000000000000000002')
pos_inf = float(1e30000)
- self.assertEqual(floatformat(pos_inf), unicode(pos_inf))
+ self.assertEqual(floatformat(pos_inf), six.text_type(pos_inf))
neg_inf = float(-1e30000)
- self.assertEqual(floatformat(neg_inf), unicode(neg_inf))
+ self.assertEqual(floatformat(neg_inf), six.text_type(neg_inf))
nan = pos_inf / pos_inf
- self.assertEqual(floatformat(nan), unicode(nan))
+ self.assertEqual(floatformat(nan), six.text_type(nan))
class FloatWrapper(object):
def __init__(self, value):
@@ -297,6 +298,10 @@ class DefaultFiltersTests(TestCase):
self.assertEqual(urlize('HTTPS://github.com/'),
'<a href="https://github.com/" rel="nofollow">HTTPS://github.com/</a>')
+ # Check urlize trims trailing period when followed by parenthesis - see #18644
+ self.assertEqual(urlize('(Go to http://www.example.com/foo.)'),
+ '(Go to <a href="http://www.example.com/foo" rel="nofollow">http://www.example.com/foo</a>.)')
+
def test_wordcount(self):
self.assertEqual(wordcount(''), 0)
self.assertEqual(wordcount('oneword'), 1)
diff --git a/tests/regressiontests/defer_regress/models.py b/tests/regressiontests/defer_regress/models.py
index 812d2da206..bd4f845f27 100644
--- a/tests/regressiontests/defer_regress/models.py
+++ b/tests/regressiontests/defer_regress/models.py
@@ -47,3 +47,7 @@ class SimpleItem(models.Model):
class Feature(models.Model):
item = models.ForeignKey(SimpleItem)
+
+class ItemAndSimpleItem(models.Model):
+ item = models.ForeignKey(Item)
+ simple = models.ForeignKey(SimpleItem)
diff --git a/tests/regressiontests/defer_regress/tests.py b/tests/regressiontests/defer_regress/tests.py
index 1f07d4c9a8..53bb59f5b3 100644
--- a/tests/regressiontests/defer_regress/tests.py
+++ b/tests/regressiontests/defer_regress/tests.py
@@ -9,7 +9,7 @@ from django.db.models.loading import cache
from django.test import TestCase
from .models import (ResolveThis, Item, RelatedItem, Child, Leaf, Proxy,
- SimpleItem, Feature)
+ SimpleItem, Feature, ItemAndSimpleItem)
class DeferRegressionTest(TestCase):
@@ -109,6 +109,7 @@ class DeferRegressionTest(TestCase):
Child,
Feature,
Item,
+ ItemAndSimpleItem,
Leaf,
Proxy,
RelatedItem,
@@ -125,12 +126,16 @@ class DeferRegressionTest(TestCase):
),
)
)
+ # FIXME: This is dependent on the order in which tests are run --
+ # this test case has to be the first, otherwise a LOT more classes
+ # appear.
self.assertEqual(
klasses, [
"Child",
"Child_Deferred_value",
"Feature",
"Item",
+ "ItemAndSimpleItem",
"Item_Deferred_name",
"Item_Deferred_name_other_value_text",
"Item_Deferred_name_other_value_value",
@@ -139,7 +144,7 @@ class DeferRegressionTest(TestCase):
"Leaf",
"Leaf_Deferred_child_id_second_child_id_value",
"Leaf_Deferred_name_value",
- "Leaf_Deferred_second_child_value",
+ "Leaf_Deferred_second_child_id_value",
"Leaf_Deferred_value",
"Proxy",
"RelatedItem",
@@ -175,6 +180,23 @@ class DeferRegressionTest(TestCase):
self.assertEqual(1, qs.count())
self.assertEqual('Foobar', qs[0].name)
+ def test_defer_with_select_related(self):
+ item1 = Item.objects.create(name="first", value=47)
+ item2 = Item.objects.create(name="second", value=42)
+ simple = SimpleItem.objects.create(name="simple", value="23")
+ related = ItemAndSimpleItem.objects.create(item=item1, simple=simple)
+
+ obj = ItemAndSimpleItem.objects.defer('item').select_related('simple').get()
+ self.assertEqual(obj.item, item1)
+ self.assertEqual(obj.item_id, item1.id)
+
+ obj.item = item2
+ obj.save()
+
+ obj = ItemAndSimpleItem.objects.defer('item').select_related('simple').get()
+ self.assertEqual(obj.item, item2)
+ self.assertEqual(obj.item_id, item2.id)
+
def test_deferred_class_factory(self):
from django.db.models.query_utils import deferred_class_factory
new_class = deferred_class_factory(Item,
diff --git a/tests/regressiontests/dispatch/tests/__init__.py b/tests/regressiontests/dispatch/tests/__init__.py
index 447975ab85..b6d26217e1 100644
--- a/tests/regressiontests/dispatch/tests/__init__.py
+++ b/tests/regressiontests/dispatch/tests/__init__.py
@@ -4,5 +4,5 @@ Unit-tests for the dispatch project
from __future__ import absolute_import
-from .test_dispatcher import DispatcherTests
+from .test_dispatcher import DispatcherTests, ReceiverTestCase
from .test_saferef import SaferefTests
diff --git a/tests/regressiontests/dispatch/tests/test_dispatcher.py b/tests/regressiontests/dispatch/tests/test_dispatcher.py
index 319d6553a0..5f7094d5fa 100644
--- a/tests/regressiontests/dispatch/tests/test_dispatcher.py
+++ b/tests/regressiontests/dispatch/tests/test_dispatcher.py
@@ -2,7 +2,7 @@ import gc
import sys
import time
-from django.dispatch import Signal
+from django.dispatch import Signal, receiver
from django.utils import unittest
@@ -33,6 +33,8 @@ class Callable(object):
return val
a_signal = Signal(providing_args=["val"])
+b_signal = Signal(providing_args=["val"])
+c_signal = Signal(providing_args=["val"])
class DispatcherTests(unittest.TestCase):
"""Test suite for dispatcher (barely started)"""
@@ -123,3 +125,29 @@ class DispatcherTests(unittest.TestCase):
garbage_collect()
a_signal.disconnect(receiver_3)
self._testIsClean(a_signal)
+
+
+class ReceiverTestCase(unittest.TestCase):
+ """
+ Test suite for receiver.
+
+ """
+ def testReceiverSingleSignal(self):
+ @receiver(a_signal)
+ def f(val, **kwargs):
+ self.state = val
+ self.state = False
+ a_signal.send(sender=self, val=True)
+ self.assertTrue(self.state)
+
+ def testReceiverSignalList(self):
+ @receiver([a_signal, b_signal, c_signal])
+ def f(val, **kwargs):
+ self.state.append(val)
+ self.state = []
+ a_signal.send(sender=self, val='a')
+ c_signal.send(sender=self, val='c')
+ b_signal.send(sender=self, val='b')
+ self.assertIn('a', self.state)
+ self.assertIn('b', self.state)
+ self.assertIn('c', self.state)
diff --git a/tests/regressiontests/dispatch/tests/test_saferef.py b/tests/regressiontests/dispatch/tests/test_saferef.py
index 99251c5127..cfe6c5df85 100644
--- a/tests/regressiontests/dispatch/tests/test_saferef.py
+++ b/tests/regressiontests/dispatch/tests/test_saferef.py
@@ -1,7 +1,7 @@
from django.dispatch.saferef import safeRef
+from django.utils.six.moves import xrange
from django.utils import unittest
-
class Test1(object):
def x(self):
pass
@@ -70,4 +70,4 @@ class SaferefTests(unittest.TestCase):
def _closure(self, ref):
"""Dumb utility mechanism to increment deletion counter"""
- self.closureCount +=1 \ No newline at end of file
+ self.closureCount +=1
diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py
index 51b2207867..31e33d915c 100644
--- a/tests/regressiontests/file_storage/tests.py
+++ b/tests/regressiontests/file_storage/tests.py
@@ -424,7 +424,7 @@ class FileSaveRaceConditionTest(unittest.TestCase):
class FileStoragePermissions(unittest.TestCase):
def setUp(self):
self.old_perms = settings.FILE_UPLOAD_PERMISSIONS
- settings.FILE_UPLOAD_PERMISSIONS = 0666
+ settings.FILE_UPLOAD_PERMISSIONS = 0o666
self.storage_dir = tempfile.mkdtemp()
self.storage = FileSystemStorage(self.storage_dir)
@@ -434,8 +434,8 @@ class FileStoragePermissions(unittest.TestCase):
def test_file_upload_permissions(self):
name = self.storage.save("the_file", ContentFile(b"data"))
- actual_mode = os.stat(self.storage.path(name))[0] & 0777
- self.assertEqual(actual_mode, 0666)
+ actual_mode = os.stat(self.storage.path(name))[0] & 0o777
+ self.assertEqual(actual_mode, 0o666)
class FileStoragePathParsing(unittest.TestCase):
diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py
index a7424639b4..9fe3ca15a7 100644
--- a/tests/regressiontests/file_uploads/tests.py
+++ b/tests/regressiontests/file_uploads/tests.py
@@ -362,16 +362,16 @@ class DirectoryCreationTests(unittest.TestCase):
if not os.path.isdir(temp_storage.location):
os.makedirs(temp_storage.location)
if os.path.isdir(UPLOAD_TO):
- os.chmod(UPLOAD_TO, 0700)
+ os.chmod(UPLOAD_TO, 0o700)
shutil.rmtree(UPLOAD_TO)
def tearDown(self):
- os.chmod(temp_storage.location, 0700)
+ os.chmod(temp_storage.location, 0o700)
shutil.rmtree(temp_storage.location)
def test_readonly_root(self):
"""Permission errors are not swallowed"""
- os.chmod(temp_storage.location, 0500)
+ os.chmod(temp_storage.location, 0o500)
try:
self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', b'x'))
except OSError as err:
diff --git a/tests/regressiontests/file_uploads/views.py b/tests/regressiontests/file_uploads/views.py
index 73b09cbcff..c5d2720e1a 100644
--- a/tests/regressiontests/file_uploads/views.py
+++ b/tests/regressiontests/file_uploads/views.py
@@ -6,6 +6,7 @@ import os
from django.core.files.uploadedfile import UploadedFile
from django.http import HttpResponse, HttpResponseServerError
+from django.utils import six
from .models import FileModel, UPLOAD_TO
from .tests import UNICODE_FILENAME
@@ -19,7 +20,7 @@ def file_upload_view(request):
"""
form_data = request.POST.copy()
form_data.update(request.FILES)
- if isinstance(form_data.get('file_field'), UploadedFile) and isinstance(form_data['name'], unicode):
+ if isinstance(form_data.get('file_field'), UploadedFile) and isinstance(form_data['name'], six.text_type):
# If a file is posted, the dummy client should only post the file name,
# not the full path.
if os.path.dirname(form_data['file_field'].name) != '':
diff --git a/tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json b/tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json
index fe50c653cc..42e8ec0877 100644
--- a/tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json
+++ b/tests/regressiontests/fixtures_regress/fixtures/forward_ref_lookup.json
@@ -10,6 +10,7 @@
"pk": "2",
"model": "fixtures_regress.store",
"fields": {
+ "main": null,
"name": "Amazon"
}
},
@@ -17,6 +18,7 @@
"pk": "3",
"model": "fixtures_regress.store",
"fields": {
+ "main": null,
"name": "Borders"
}
},
@@ -29,4 +31,4 @@
"stores": [["Amazon"], ["Borders"]]
}
}
-] \ No newline at end of file
+]
diff --git a/tests/regressiontests/fixtures_regress/models.py b/tests/regressiontests/fixtures_regress/models.py
index 5d23a21dcd..7151cb0ed9 100644
--- a/tests/regressiontests/fixtures_regress/models.py
+++ b/tests/regressiontests/fixtures_regress/models.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
from django.contrib.auth.models import User
from django.db import models
+from django.utils import six
class Animal(models.Model):
@@ -29,7 +30,7 @@ class Stuff(models.Model):
owner = models.ForeignKey(User, null=True)
def __unicode__(self):
- return unicode(self.name) + ' is owned by ' + unicode(self.owner)
+ return six.text_type(self.name) + ' is owned by ' + six.text_type(self.owner)
class Absolute(models.Model):
@@ -91,6 +92,7 @@ class TestManager(models.Manager):
class Store(models.Model):
objects = TestManager()
name = models.CharField(max_length=255)
+ main = models.ForeignKey('self', null=True)
class Meta:
ordering = ('name',)
diff --git a/tests/regressiontests/fixtures_regress/tests.py b/tests/regressiontests/fixtures_regress/tests.py
index 405c566826..ab93341699 100644
--- a/tests/regressiontests/fixtures_regress/tests.py
+++ b/tests/regressiontests/fixtures_regress/tests.py
@@ -478,7 +478,7 @@ class NaturalKeyFixtureTests(TestCase):
)
self.assertEqual(
stdout.getvalue(),
- """[{"pk": 2, "model": "fixtures_regress.store", "fields": {"name": "Amazon"}}, {"pk": 3, "model": "fixtures_regress.store", "fields": {"name": "Borders"}}, {"pk": 4, "model": "fixtures_regress.person", "fields": {"name": "Neal Stephenson"}}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]"""
+ """[{"pk": 2, "model": "fixtures_regress.store", "fields": {"main": null, "name": "Amazon"}}, {"pk": 3, "model": "fixtures_regress.store", "fields": {"main": null, "name": "Borders"}}, {"pk": 4, "model": "fixtures_regress.person", "fields": {"name": "Neal Stephenson"}}, {"pk": 1, "model": "fixtures_regress.book", "fields": {"stores": [["Amazon"], ["Borders"]], "name": "Cryptonomicon", "author": ["Neal Stephenson"]}}]"""
)
def test_dependency_sorting(self):
diff --git a/tests/regressiontests/forms/tests/extra.py b/tests/regressiontests/forms/tests/extra.py
index 25b21123c4..28b6c12453 100644
--- a/tests/regressiontests/forms/tests/extra.py
+++ b/tests/regressiontests/forms/tests/extra.py
@@ -554,7 +554,7 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
def test_smart_unicode(self):
class Test:
def __str__(self):
- return b'ŠĐĆŽćžšđ'
+ return 'ŠĐĆŽćžšđ'.encode('utf-8')
class TestU:
def __str__(self):
diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
index ebeb19c8fc..feb2ade458 100644
--- a/tests/regressiontests/forms/tests/fields.py
+++ b/tests/regressiontests/forms/tests/fields.py
@@ -35,10 +35,11 @@ from decimal import Decimal
from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms import *
from django.test import SimpleTestCase
+from django.utils import six
def fix_os_paths(x):
- if isinstance(x, basestring):
+ if isinstance(x, six.string_types):
return x.replace('\\', '/')
elif isinstance(x, tuple):
return tuple(fix_os_paths(list(x)))
@@ -486,7 +487,7 @@ class FieldsTests(SimpleTestCase):
Refs #.
"""
f = RegexField('^\w+$')
- self.assertEqual(u'éèøçÎÎ你好', f.clean(u'éèøçÎÎ你好'))
+ self.assertEqual('éèøçÎÎ你好', f.clean('éèøçÎÎ你好'))
def test_change_regex_after_init(self):
f = RegexField('^[a-z]+$')
diff --git a/tests/regressiontests/forms/tests/models.py b/tests/regressiontests/forms/tests/models.py
index 5bea49b840..7687335b48 100644
--- a/tests/regressiontests/forms/tests/models.py
+++ b/tests/regressiontests/forms/tests/models.py
@@ -8,6 +8,7 @@ from django.db import models
from django.forms import Form, ModelForm, FileField, ModelChoiceField
from django.forms.models import ModelFormMetaclass
from django.test import TestCase
+from django.utils import six
from ..models import (ChoiceOptionModel, ChoiceFieldModel, FileModel, Group,
BoundaryModel, Defaults)
@@ -40,7 +41,7 @@ class ModelFormCallableModelDefault(TestCase):
choices = list(ChoiceFieldForm().fields['choice'].choices)
self.assertEqual(len(choices), 1)
- self.assertEqual(choices[0], (option.pk, unicode(option)))
+ self.assertEqual(choices[0], (option.pk, six.text_type(option)))
def test_callable_initial_value(self):
"The initial value for a callable default returning a queryset is the pk (refs #13769)"
diff --git a/tests/regressiontests/forms/tests/util.py b/tests/regressiontests/forms/tests/util.py
index 280049c97b..b7cc4ec809 100644
--- a/tests/regressiontests/forms/tests/util.py
+++ b/tests/regressiontests/forms/tests/util.py
@@ -5,6 +5,7 @@ from django.core.exceptions import ValidationError
from django.forms.util import flatatt, ErrorDict, ErrorList
from django.test import TestCase
from django.utils.safestring import mark_safe
+from django.utils import six
from django.utils.translation import ugettext_lazy
@@ -30,7 +31,7 @@ class FormsUtilTestCase(TestCase):
'<ul class="errorlist"><li>There was an error.</li></ul>')
# Can take a unicode string.
- self.assertHTMLEqual(unicode(ErrorList(ValidationError("Not \u03C0.").messages)),
+ self.assertHTMLEqual(six.text_type(ErrorList(ValidationError("Not \u03C0.").messages)),
'<ul class="errorlist"><li>Not π.</li></ul>')
# Can take a lazy string.
diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py
index d5f6334fe9..3ea42cf549 100644
--- a/tests/regressiontests/forms/tests/widgets.py
+++ b/tests/regressiontests/forms/tests/widgets.py
@@ -10,6 +10,7 @@ from django.forms import *
from django.forms.widgets import RadioFieldRenderer
from django.utils import formats
from django.utils.safestring import mark_safe
+from django.utils import six
from django.utils.translation import activate, deactivate
from django.test import TestCase
@@ -676,7 +677,7 @@ beatle J R Ringo False""")
# You can create your own custom renderers for RadioSelect to use.
class MyRenderer(RadioFieldRenderer):
def render(self):
- return '<br />\n'.join([unicode(choice) for choice in self])
+ return '<br />\n'.join([six.text_type(choice) for choice in self])
w = RadioSelect(renderer=MyRenderer)
self.assertHTMLEqual(w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))), """<label><input type="radio" name="beatle" value="J" /> John</label><br />
<label><input type="radio" name="beatle" value="P" /> Paul</label><br />
@@ -716,7 +717,7 @@ beatle J R Ringo False""")
# Unicode choices are correctly rendered as HTML
w = RadioSelect()
- self.assertHTMLEqual(unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])), '<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>')
+ self.assertHTMLEqual(six.text_type(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])), '<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>')
# Attributes provided at instantiation are passed to the constituent inputs
w = RadioSelect(attrs={'id':'foo'})
@@ -1135,7 +1136,7 @@ class ClearableFileInputTests(TestCase):
output = widget.render('my<div>file', field)
self.assertFalse(field.url in output)
self.assertTrue('href="something?chapter=1&amp;sect=2&amp;copy=3&amp;lang=en"' in output)
- self.assertFalse(unicode(field) in output)
+ self.assertFalse(six.text_type(field) in output)
self.assertTrue('something&lt;div onclick=&quot;alert(&#39;oops&#39;)&quot;&gt;.jpg' in output)
self.assertTrue('my&lt;div&gt;file' in output)
self.assertFalse('my<div>file' in output)
diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py
index 870324bffb..9b599db6d0 100644
--- a/tests/regressiontests/httpwrappers/tests.py
+++ b/tests/regressiontests/httpwrappers/tests.py
@@ -1,3 +1,4 @@
+# -*- encoding: utf-8 -*-
from __future__ import unicode_literals
import copy
@@ -189,7 +190,7 @@ class QueryDictTests(unittest.TestCase):
self.assertEqual(q == q1, True)
q = QueryDict('a=b&c=d&a=1')
q1 = pickle.loads(pickle.dumps(q, 2))
- self.assertEqual(q == q1 , True)
+ self.assertEqual(q == q1, True)
def test_update_from_querydict(self):
"""Regression test for #8278: QueryDict.update(QueryDict)"""
@@ -298,6 +299,17 @@ class HttpResponseTests(unittest.TestCase):
self.assertRaises(UnicodeEncodeError,
getattr, r, 'content')
+ def test_file_interface(self):
+ r = HttpResponse()
+ r.write(b"hello")
+ self.assertEqual(r.tell(), 5)
+ r.write("привет")
+ self.assertEqual(r.tell(), 17)
+
+ r = HttpResponse(['abc'])
+ self.assertRaises(Exception, r.write, 'def')
+
+
class CookieTests(unittest.TestCase):
def test_encode(self):
"""
diff --git a/tests/regressiontests/i18n/commands/code.sample b/tests/regressiontests/i18n/commands/code.sample
new file mode 100644
index 0000000000..bbcb83164b
--- /dev/null
+++ b/tests/regressiontests/i18n/commands/code.sample
@@ -0,0 +1,4 @@
+from django.utils.translation import ugettext
+
+# This will generate an xgettext warning
+my_string = ugettext("This string contain two placeholders: %s and %s" % ('a', 'b'))
diff --git a/tests/regressiontests/i18n/commands/extraction.py b/tests/regressiontests/i18n/commands/extraction.py
index fb9ca4ed08..cd6d50893a 100644
--- a/tests/regressiontests/i18n/commands/extraction.py
+++ b/tests/regressiontests/i18n/commands/extraction.py
@@ -117,6 +117,14 @@ class BasicExtractorTests(ExtractorTests):
# Check that the temporary file was cleaned up
self.assertFalse(os.path.exists('./templates/template_with_error.html.py'))
+ def test_extraction_warning(self):
+ os.chdir(self.test_dir)
+ shutil.copyfile('./code.sample', './code_sample.py')
+ stdout = StringIO()
+ management.call_command('makemessages', locale=LOCALE, stdout=stdout)
+ os.remove('./code_sample.py')
+ self.assertIn("code_sample.py:4", stdout.getvalue())
+
def test_template_message_context_extractor(self):
"""
Ensure that message contexts are correctly extracted for the
diff --git a/tests/regressiontests/i18n/commands/tests.py b/tests/regressiontests/i18n/commands/tests.py
index 38e8af1d0d..e00ef72d59 100644
--- a/tests/regressiontests/i18n/commands/tests.py
+++ b/tests/regressiontests/i18n/commands/tests.py
@@ -2,13 +2,15 @@ import os
import re
from subprocess import Popen, PIPE
+from django.utils import six
+
can_run_extraction_tests = False
can_run_compilation_tests = False
def find_command(cmd, path=None, pathext=None):
if path is None:
path = os.environ.get('PATH', []).split(os.pathsep)
- if isinstance(path, basestring):
+ if isinstance(path, six.string_types):
path = [path]
# check if there are funny path extensions for executables, e.g. Windows
if pathext is None:
diff --git a/tests/regressiontests/i18n/contenttypes/tests.py b/tests/regressiontests/i18n/contenttypes/tests.py
index bed94da8b8..178232f543 100644
--- a/tests/regressiontests/i18n/contenttypes/tests.py
+++ b/tests/regressiontests/i18n/contenttypes/tests.py
@@ -6,6 +6,7 @@ import os
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from django.test.utils import override_settings
+from django.utils import six
from django.utils import translation
@@ -24,11 +25,11 @@ class ContentTypeTests(TestCase):
def test_verbose_name(self):
company_type = ContentType.objects.get(app_label='i18n', model='company')
with translation.override('en'):
- self.assertEqual(unicode(company_type), 'Company')
+ self.assertEqual(six.text_type(company_type), 'Company')
with translation.override('fr'):
- self.assertEqual(unicode(company_type), 'Société')
+ self.assertEqual(six.text_type(company_type), 'Société')
def test_field_override(self):
company_type = ContentType.objects.get(app_label='i18n', model='company')
company_type.name = 'Other'
- self.assertEqual(unicode(company_type), 'Other')
+ self.assertEqual(six.text_type(company_type), 'Other')
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index f91d7c042b..9ca66bdb9b 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -19,6 +19,8 @@ from django.utils.formats import (get_format, date_format, time_format,
from django.utils.importlib import import_module
from django.utils.numberformat import format as nformat
from django.utils.safestring import mark_safe, SafeString, SafeUnicode
+from django.utils import six
+from django.utils.six import PY3
from django.utils.translation import (ugettext, ugettext_lazy, activate,
deactivate, gettext_lazy, pgettext, npgettext, to_locale,
get_language_info, get_language, get_language_from_request)
@@ -80,9 +82,9 @@ class TranslationTests(TestCase):
def test_lazy_pickle(self):
s1 = ugettext_lazy("test")
- self.assertEqual(unicode(s1), "test")
+ self.assertEqual(six.text_type(s1), "test")
s2 = pickle.loads(pickle.dumps(s1))
- self.assertEqual(unicode(s2), "test")
+ self.assertEqual(six.text_type(s2), "test")
def test_pgettext(self):
# Reset translation catalog to include other/locale/de
@@ -221,10 +223,10 @@ class TranslationTests(TestCase):
def test_string_concat(self):
"""
- unicode(string_concat(...)) should not raise a TypeError - #4796
+ six.text_type(string_concat(...)) should not raise a TypeError - #4796
"""
import django.utils.translation
- self.assertEqual('django', unicode(django.utils.translation.string_concat("dja", "ngo")))
+ self.assertEqual('django', six.text_type(django.utils.translation.string_concat("dja", "ngo")))
def test_safe_status(self):
"""
@@ -309,7 +311,7 @@ class FormattingTests(TestCase):
self.d = datetime.date(2009, 12, 31)
self.dt = datetime.datetime(2009, 12, 31, 20, 50)
self.t = datetime.time(10, 15, 48)
- self.l = 10000L
+ self.l = 10000 if PY3 else long(10000)
self.ctxt = Context({
'n': self.n,
't': self.t,
diff --git a/tests/regressiontests/initial_sql_regress/sql/simple.sql b/tests/regressiontests/initial_sql_regress/sql/simple.sql
index ca9bd40dab..39363baa9a 100644
--- a/tests/regressiontests/initial_sql_regress/sql/simple.sql
+++ b/tests/regressiontests/initial_sql_regress/sql/simple.sql
@@ -1,4 +1,6 @@
-INSERT INTO initial_sql_regress_simple (name) VALUES ('John');
+-- a comment
+INSERT INTO initial_sql_regress_simple (name) VALUES ('John'); -- another comment
+INSERT INTO initial_sql_regress_simple (name) VALUES ('-- Comment Man');
INSERT INTO initial_sql_regress_simple (name) VALUES ('Paul');
INSERT INTO initial_sql_regress_simple (name) VALUES ('Ringo');
INSERT INTO initial_sql_regress_simple (name) VALUES ('George');
diff --git a/tests/regressiontests/initial_sql_regress/tests.py b/tests/regressiontests/initial_sql_regress/tests.py
index 815b75a9bb..03a91cb807 100644
--- a/tests/regressiontests/initial_sql_regress/tests.py
+++ b/tests/regressiontests/initial_sql_regress/tests.py
@@ -4,12 +4,26 @@ from .models import Simple
class InitialSQLTests(TestCase):
- def test_initial_sql(self):
- # The format of the included SQL file for this test suite is important.
- # It must end with a trailing newline in order to test the fix for #2161.
+ # The format of the included SQL file for this test suite is important.
+ # It must end with a trailing newline in order to test the fix for #2161.
- # However, as pointed out by #14661, test data loaded by custom SQL
+ def test_initial_sql(self):
+ # As pointed out by #14661, test data loaded by custom SQL
# can't be relied upon; as a result, the test framework flushes the
# data contents before every test. This test validates that this has
# occurred.
self.assertEqual(Simple.objects.count(), 0)
+
+ def test_custom_sql(self):
+ from django.core.management.sql import custom_sql_for_model
+ from django.core.management.color import no_style
+ from django.db import connections, DEFAULT_DB_ALIAS
+
+ # Simulate the custom SQL loading by syncdb
+ connection = connections[DEFAULT_DB_ALIAS]
+ custom_sql = custom_sql_for_model(Simple, no_style(), connection)
+ self.assertEqual(len(custom_sql), 8)
+ cursor = connection.cursor()
+ for sql in custom_sql:
+ cursor.execute(sql)
+ self.assertEqual(Simple.objects.count(), 8)
diff --git a/tests/regressiontests/inline_formsets/tests.py b/tests/regressiontests/inline_formsets/tests.py
index 8ad84f221f..6e63f34ed0 100644
--- a/tests/regressiontests/inline_formsets/tests.py
+++ b/tests/regressiontests/inline_formsets/tests.py
@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
from django.forms.models import inlineformset_factory
from django.test import TestCase
+from django.utils import six
from .models import Poet, Poem, School, Parent, Child
@@ -66,8 +67,8 @@ class DeletionTests(TestCase):
'poem_set-TOTAL_FORMS': '1',
'poem_set-INITIAL_FORMS': '1',
'poem_set-MAX_NUM_FORMS': '0',
- 'poem_set-0-id': unicode(poem.id),
- 'poem_set-0-poem': unicode(poem.id),
+ 'poem_set-0-id': six.text_type(poem.id),
+ 'poem_set-0-poem': six.text_type(poem.id),
'poem_set-0-name': 'x' * 1000,
}
formset = PoemFormSet(data, instance=poet)
diff --git a/tests/regressiontests/localflavor/ar/tests.py b/tests/regressiontests/localflavor/ar/tests.py
index 0731c3ce9b..0bc228eae9 100644
--- a/tests/regressiontests/localflavor/ar/tests.py
+++ b/tests/regressiontests/localflavor/ar/tests.py
@@ -81,20 +81,23 @@ class ARLocalFlavorTests(SimpleTestCase):
def test_ARCUITField(self):
error_format = ['Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.']
error_invalid = ['Invalid CUIT.']
+ error_legal_type = ['Invalid legal type. Type must be 27, 20, 23 or 30.']
valid = {
'20-10123456-9': '20-10123456-9',
'20-10123456-9': '20-10123456-9',
'27-10345678-4': '27-10345678-4',
'20101234569': '20-10123456-9',
'27103456784': '27-10345678-4',
+ '30011111110': '30-01111111-0',
}
invalid = {
'2-10123456-9': error_format,
'210123456-9': error_format,
'20-10123456': error_format,
'20-10123456-': error_format,
- '20-10123456-5': error_invalid,
- '27-10345678-1': error_invalid,
- '27-10345678-1': error_invalid,
+ '20-10123456-5': error_invalid,
+ '27-10345678-1': error_invalid,
+ '27-10345678-1': error_invalid,
+ '11211111110': error_legal_type,
}
self.assertFieldOutput(ARCUITField, valid, invalid)
diff --git a/tests/regressiontests/localflavor/fr/tests.py b/tests/regressiontests/localflavor/fr/tests.py
index 55f8a68b3b..8e99ef462b 100644
--- a/tests/regressiontests/localflavor/fr/tests.py
+++ b/tests/regressiontests/localflavor/fr/tests.py
@@ -16,7 +16,8 @@ class FRLocalFlavorTests(SimpleTestCase):
}
invalid = {
'2A200': error_format,
- '980001': error_format,
+ '980001': ['Ensure this value has at most 5 characters (it has 6).'
+ ] + error_format,
}
self.assertFieldOutput(FRZipCodeField, valid, invalid)
diff --git a/tests/regressiontests/mail/tests.py b/tests/regressiontests/mail/tests.py
index cdd6dd1b9e..2215f56523 100644
--- a/tests/regressiontests/mail/tests.py
+++ b/tests/regressiontests/mail/tests.py
@@ -603,21 +603,16 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
maddr = email.Utils.parseaddr(m.get('from'))[1]
if mailfrom != maddr:
return "553 '%s' != '%s'" % (mailfrom, maddr)
- self.sink_lock.acquire()
- self._sink.append(m)
- self.sink_lock.release()
+ with self.sink_lock:
+ self._sink.append(m)
def get_sink(self):
- self.sink_lock.acquire()
- try:
+ with self.sink_lock:
return self._sink[:]
- finally:
- self.sink_lock.release()
def flush_sink(self):
- self.sink_lock.acquire()
- self._sink[:] = []
- self.sink_lock.release()
+ with self.sink_lock:
+ self._sink[:] = []
def start(self):
assert not self.active
@@ -629,9 +624,8 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
self.active = True
self.__flag.set()
while self.active and asyncore.socket_map:
- self.active_lock.acquire()
- asyncore.loop(timeout=0.1, count=1)
- self.active_lock.release()
+ with self.active_lock:
+ asyncore.loop(timeout=0.1, count=1)
asyncore.close_all()
def stop(self):
diff --git a/tests/regressiontests/middleware/tests.py b/tests/regressiontests/middleware/tests.py
index 47fca03ba3..ead34f46db 100644
--- a/tests/regressiontests/middleware/tests.py
+++ b/tests/regressiontests/middleware/tests.py
@@ -15,6 +15,7 @@ from django.middleware.http import ConditionalGetMiddleware
from django.middleware.gzip import GZipMiddleware
from django.test import TestCase, RequestFactory
from django.test.utils import override_settings
+from django.utils.six.moves import xrange
class CommonMiddlewareTest(TestCase):
def setUp(self):
diff --git a/tests/regressiontests/model_fields/imagefield.py b/tests/regressiontests/model_fields/imagefield.py
index 09c1bd76d3..7446f222ff 100644
--- a/tests/regressiontests/model_fields/imagefield.py
+++ b/tests/regressiontests/model_fields/imagefield.py
@@ -6,416 +6,428 @@ import shutil
from django.core.files import File
from django.core.files.images import ImageFile
from django.test import TestCase
+from django.utils.unittest import skipIf
-from .models import (Image, Person, PersonWithHeight, PersonWithHeightAndWidth,
- PersonDimensionsFirst, PersonTwoImages, TestImageFieldFile)
+from .models import Image
-
-# If PIL available, do these tests.
if Image:
-
+ from .models import (Person, PersonWithHeight, PersonWithHeightAndWidth,
+ PersonDimensionsFirst, PersonTwoImages, TestImageFieldFile)
from .models import temp_storage_dir
+else:
+ # PIL not available, create dummy classes (tests will be skipped anyway)
+ class Person():
+ pass
+ PersonWithHeight = PersonWithHeightAndWidth = PersonDimensionsFirst = Person
+ PersonTwoImages = Person
- class ImageFieldTestMixin(object):
- """
- Mixin class to provide common functionality to ImageField test classes.
- """
+class ImageFieldTestMixin(object):
+ """
+ Mixin class to provide common functionality to ImageField test classes.
+ """
- # Person model to use for tests.
- PersonModel = PersonWithHeightAndWidth
- # File class to use for file instances.
- File = ImageFile
+ # Person model to use for tests.
+ PersonModel = PersonWithHeightAndWidth
+ # File class to use for file instances.
+ File = ImageFile
- def setUp(self):
- """
- Creates a pristine temp directory (or deletes and recreates if it
- already exists) that the model uses as its storage directory.
+ def setUp(self):
+ """
+ Creates a pristine temp directory (or deletes and recreates if it
+ already exists) that the model uses as its storage directory.
- Sets up two ImageFile instances for use in tests.
- """
- if os.path.exists(temp_storage_dir):
- shutil.rmtree(temp_storage_dir)
- os.mkdir(temp_storage_dir)
+ Sets up two ImageFile instances for use in tests.
+ """
+ if os.path.exists(temp_storage_dir):
+ shutil.rmtree(temp_storage_dir)
+ os.mkdir(temp_storage_dir)
- file_path1 = os.path.join(os.path.dirname(__file__), "4x8.png")
- self.file1 = self.File(open(file_path1, 'rb'))
+ file_path1 = os.path.join(os.path.dirname(__file__), "4x8.png")
+ self.file1 = self.File(open(file_path1, 'rb'))
- file_path2 = os.path.join(os.path.dirname(__file__), "8x4.png")
- self.file2 = self.File(open(file_path2, 'rb'))
+ file_path2 = os.path.join(os.path.dirname(__file__), "8x4.png")
+ self.file2 = self.File(open(file_path2, 'rb'))
- def tearDown(self):
- """
- Removes temp directory and all its contents.
- """
- shutil.rmtree(temp_storage_dir)
+ def tearDown(self):
+ """
+ Removes temp directory and all its contents.
+ """
+ shutil.rmtree(temp_storage_dir)
- def check_dimensions(self, instance, width, height,
- field_name='mugshot'):
- """
- Asserts that the given width and height values match both the
- field's height and width attributes and the height and width fields
- (if defined) the image field is caching to.
+ def check_dimensions(self, instance, width, height,
+ field_name='mugshot'):
+ """
+ Asserts that the given width and height values match both the
+ field's height and width attributes and the height and width fields
+ (if defined) the image field is caching to.
- Note, this method will check for dimension fields named by adding
- "_width" or "_height" to the name of the ImageField. So, the
- models used in these tests must have their fields named
- accordingly.
+ Note, this method will check for dimension fields named by adding
+ "_width" or "_height" to the name of the ImageField. So, the
+ models used in these tests must have their fields named
+ accordingly.
- By default, we check the field named "mugshot", but this can be
- specified by passing the field_name parameter.
- """
- field = getattr(instance, field_name)
- # Check height/width attributes of field.
- if width is None and height is None:
- self.assertRaises(ValueError, getattr, field, 'width')
- self.assertRaises(ValueError, getattr, field, 'height')
- else:
- self.assertEqual(field.width, width)
- self.assertEqual(field.height, height)
+ By default, we check the field named "mugshot", but this can be
+ specified by passing the field_name parameter.
+ """
+ field = getattr(instance, field_name)
+ # Check height/width attributes of field.
+ if width is None and height is None:
+ self.assertRaises(ValueError, getattr, field, 'width')
+ self.assertRaises(ValueError, getattr, field, 'height')
+ else:
+ self.assertEqual(field.width, width)
+ self.assertEqual(field.height, height)
- # Check height/width fields of model, if defined.
- width_field_name = field_name + '_width'
- if hasattr(instance, width_field_name):
- self.assertEqual(getattr(instance, width_field_name), width)
- height_field_name = field_name + '_height'
- if hasattr(instance, height_field_name):
- self.assertEqual(getattr(instance, height_field_name), height)
+ # Check height/width fields of model, if defined.
+ width_field_name = field_name + '_width'
+ if hasattr(instance, width_field_name):
+ self.assertEqual(getattr(instance, width_field_name), width)
+ height_field_name = field_name + '_height'
+ if hasattr(instance, height_field_name):
+ self.assertEqual(getattr(instance, height_field_name), height)
- class ImageFieldTests(ImageFieldTestMixin, TestCase):
+@skipIf(Image is None, "PIL is required to test ImageField")
+class ImageFieldTests(ImageFieldTestMixin, TestCase):
+ """
+ Tests for ImageField that don't need to be run with each of the
+ different test model classes.
+ """
+
+ def test_equal_notequal_hash(self):
"""
- Tests for ImageField that don't need to be run with each of the
- different test model classes.
+ Bug #9786: Ensure '==' and '!=' work correctly.
+ Bug #9508: make sure hash() works as expected (equal items must
+ hash to the same value).
"""
+ # Create two Persons with different mugshots.
+ p1 = self.PersonModel(name="Joe")
+ p1.mugshot.save("mug", self.file1)
+ p2 = self.PersonModel(name="Bob")
+ p2.mugshot.save("mug", self.file2)
+ self.assertEqual(p1.mugshot == p2.mugshot, False)
+ self.assertEqual(p1.mugshot != p2.mugshot, True)
- def test_equal_notequal_hash(self):
- """
- Bug #9786: Ensure '==' and '!=' work correctly.
- Bug #9508: make sure hash() works as expected (equal items must
- hash to the same value).
- """
- # Create two Persons with different mugshots.
- p1 = self.PersonModel(name="Joe")
- p1.mugshot.save("mug", self.file1)
- p2 = self.PersonModel(name="Bob")
- p2.mugshot.save("mug", self.file2)
- self.assertEqual(p1.mugshot == p2.mugshot, False)
- self.assertEqual(p1.mugshot != p2.mugshot, True)
+ # Test again with an instance fetched from the db.
+ p1_db = self.PersonModel.objects.get(name="Joe")
+ self.assertEqual(p1_db.mugshot == p2.mugshot, False)
+ self.assertEqual(p1_db.mugshot != p2.mugshot, True)
- # Test again with an instance fetched from the db.
- p1_db = self.PersonModel.objects.get(name="Joe")
- self.assertEqual(p1_db.mugshot == p2.mugshot, False)
- self.assertEqual(p1_db.mugshot != p2.mugshot, True)
+ # Instance from db should match the local instance.
+ self.assertEqual(p1_db.mugshot == p1.mugshot, True)
+ self.assertEqual(hash(p1_db.mugshot), hash(p1.mugshot))
+ self.assertEqual(p1_db.mugshot != p1.mugshot, False)
- # Instance from db should match the local instance.
- self.assertEqual(p1_db.mugshot == p1.mugshot, True)
- self.assertEqual(hash(p1_db.mugshot), hash(p1.mugshot))
- self.assertEqual(p1_db.mugshot != p1.mugshot, False)
+ def test_instantiate_missing(self):
+ """
+ If the underlying file is unavailable, still create instantiate the
+ object without error.
+ """
+ p = self.PersonModel(name="Joan")
+ p.mugshot.save("shot", self.file1)
+ p = self.PersonModel.objects.get(name="Joan")
+ path = p.mugshot.path
+ shutil.move(path, path + '.moved')
+ p2 = self.PersonModel.objects.get(name="Joan")
- def test_instantiate_missing(self):
- """
- If the underlying file is unavailable, still create instantiate the
- object without error.
- """
- p = self.PersonModel(name="Joan")
- p.mugshot.save("shot", self.file1)
- p = self.PersonModel.objects.get(name="Joan")
- path = p.mugshot.path
- shutil.move(path, path + '.moved')
- p2 = self.PersonModel.objects.get(name="Joan")
+ def test_delete_when_missing(self):
+ """
+ Bug #8175: correctly delete an object where the file no longer
+ exists on the file system.
+ """
+ p = self.PersonModel(name="Fred")
+ p.mugshot.save("shot", self.file1)
+ os.remove(p.mugshot.path)
+ p.delete()
- def test_delete_when_missing(self):
- """
- Bug #8175: correctly delete an object where the file no longer
- exists on the file system.
- """
- p = self.PersonModel(name="Fred")
- p.mugshot.save("shot", self.file1)
- os.remove(p.mugshot.path)
- p.delete()
+ def test_size_method(self):
+ """
+ Bug #8534: FileField.size should not leave the file open.
+ """
+ p = self.PersonModel(name="Joan")
+ p.mugshot.save("shot", self.file1)
- def test_size_method(self):
- """
- Bug #8534: FileField.size should not leave the file open.
- """
- p = self.PersonModel(name="Joan")
- p.mugshot.save("shot", self.file1)
+ # Get a "clean" model instance
+ p = self.PersonModel.objects.get(name="Joan")
+ # It won't have an opened file.
+ self.assertEqual(p.mugshot.closed, True)
- # Get a "clean" model instance
- p = self.PersonModel.objects.get(name="Joan")
- # It won't have an opened file.
- self.assertEqual(p.mugshot.closed, True)
+ # After asking for the size, the file should still be closed.
+ _ = p.mugshot.size
+ self.assertEqual(p.mugshot.closed, True)
- # After asking for the size, the file should still be closed.
- _ = p.mugshot.size
- self.assertEqual(p.mugshot.closed, True)
+ def test_pickle(self):
+ """
+ Tests that ImageField can be pickled, unpickled, and that the
+ image of the unpickled version is the same as the original.
+ """
+ import pickle
- def test_pickle(self):
- """
- Tests that ImageField can be pickled, unpickled, and that the
- image of the unpickled version is the same as the original.
- """
- import pickle
+ p = Person(name="Joe")
+ p.mugshot.save("mug", self.file1)
+ dump = pickle.dumps(p)
- p = Person(name="Joe")
- p.mugshot.save("mug", self.file1)
- dump = pickle.dumps(p)
+ p2 = Person(name="Bob")
+ p2.mugshot = self.file1
- p2 = Person(name="Bob")
- p2.mugshot = self.file1
+ loaded_p = pickle.loads(dump)
+ self.assertEqual(p.mugshot, loaded_p.mugshot)
- loaded_p = pickle.loads(dump)
- self.assertEqual(p.mugshot, loaded_p.mugshot)
+@skipIf(Image is None, "PIL is required to test ImageField")
+class ImageFieldTwoDimensionsTests(ImageFieldTestMixin, TestCase):
+ """
+ Tests behavior of an ImageField and its dimensions fields.
+ """
- class ImageFieldTwoDimensionsTests(ImageFieldTestMixin, TestCase):
+ def test_constructor(self):
"""
- Tests behavior of an ImageField and its dimensions fields.
+ Tests assigning an image field through the model's constructor.
"""
+ p = self.PersonModel(name='Joe', mugshot=self.file1)
+ self.check_dimensions(p, 4, 8)
+ p.save()
+ self.check_dimensions(p, 4, 8)
- def test_constructor(self):
- """
- Tests assigning an image field through the model's constructor.
- """
- p = self.PersonModel(name='Joe', mugshot=self.file1)
- self.check_dimensions(p, 4, 8)
- p.save()
- self.check_dimensions(p, 4, 8)
-
- def test_image_after_constructor(self):
- """
- Tests behavior when image is not passed in constructor.
- """
- p = self.PersonModel(name='Joe')
- # TestImageField value will default to being an instance of its
- # attr_class, a TestImageFieldFile, with name == None, which will
- # cause it to evaluate as False.
- self.assertEqual(isinstance(p.mugshot, TestImageFieldFile), True)
- self.assertEqual(bool(p.mugshot), False)
+ def test_image_after_constructor(self):
+ """
+ Tests behavior when image is not passed in constructor.
+ """
+ p = self.PersonModel(name='Joe')
+ # TestImageField value will default to being an instance of its
+ # attr_class, a TestImageFieldFile, with name == None, which will
+ # cause it to evaluate as False.
+ self.assertEqual(isinstance(p.mugshot, TestImageFieldFile), True)
+ self.assertEqual(bool(p.mugshot), False)
- # Test setting a fresh created model instance.
- p = self.PersonModel(name='Joe')
- p.mugshot = self.file1
- self.check_dimensions(p, 4, 8)
+ # Test setting a fresh created model instance.
+ p = self.PersonModel(name='Joe')
+ p.mugshot = self.file1
+ self.check_dimensions(p, 4, 8)
- def test_create(self):
- """
- Tests assigning an image in Manager.create().
- """
- p = self.PersonModel.objects.create(name='Joe', mugshot=self.file1)
- self.check_dimensions(p, 4, 8)
+ def test_create(self):
+ """
+ Tests assigning an image in Manager.create().
+ """
+ p = self.PersonModel.objects.create(name='Joe', mugshot=self.file1)
+ self.check_dimensions(p, 4, 8)
- def test_default_value(self):
- """
- Tests that the default value for an ImageField is an instance of
- the field's attr_class (TestImageFieldFile in this case) with no
- name (name set to None).
- """
- p = self.PersonModel()
- self.assertEqual(isinstance(p.mugshot, TestImageFieldFile), True)
- self.assertEqual(bool(p.mugshot), False)
+ def test_default_value(self):
+ """
+ Tests that the default value for an ImageField is an instance of
+ the field's attr_class (TestImageFieldFile in this case) with no
+ name (name set to None).
+ """
+ p = self.PersonModel()
+ self.assertEqual(isinstance(p.mugshot, TestImageFieldFile), True)
+ self.assertEqual(bool(p.mugshot), False)
- def test_assignment_to_None(self):
- """
- Tests that assigning ImageField to None clears dimensions.
- """
- p = self.PersonModel(name='Joe', mugshot=self.file1)
- self.check_dimensions(p, 4, 8)
+ def test_assignment_to_None(self):
+ """
+ Tests that assigning ImageField to None clears dimensions.
+ """
+ p = self.PersonModel(name='Joe', mugshot=self.file1)
+ self.check_dimensions(p, 4, 8)
- # If image assigned to None, dimension fields should be cleared.
- p.mugshot = None
- self.check_dimensions(p, None, None)
+ # If image assigned to None, dimension fields should be cleared.
+ p.mugshot = None
+ self.check_dimensions(p, None, None)
- p.mugshot = self.file2
- self.check_dimensions(p, 8, 4)
+ p.mugshot = self.file2
+ self.check_dimensions(p, 8, 4)
- def test_field_save_and_delete_methods(self):
- """
- Tests assignment using the field's save method and deletion using
- the field's delete method.
- """
- p = self.PersonModel(name='Joe')
- p.mugshot.save("mug", self.file1)
- self.check_dimensions(p, 4, 8)
+ def test_field_save_and_delete_methods(self):
+ """
+ Tests assignment using the field's save method and deletion using
+ the field's delete method.
+ """
+ p = self.PersonModel(name='Joe')
+ p.mugshot.save("mug", self.file1)
+ self.check_dimensions(p, 4, 8)
- # A new file should update dimensions.
- p.mugshot.save("mug", self.file2)
- self.check_dimensions(p, 8, 4)
+ # A new file should update dimensions.
+ p.mugshot.save("mug", self.file2)
+ self.check_dimensions(p, 8, 4)
- # Field and dimensions should be cleared after a delete.
- p.mugshot.delete(save=False)
- self.assertEqual(p.mugshot, None)
- self.check_dimensions(p, None, None)
+ # Field and dimensions should be cleared after a delete.
+ p.mugshot.delete(save=False)
+ self.assertEqual(p.mugshot, None)
+ self.check_dimensions(p, None, None)
- def test_dimensions(self):
- """
- Checks that dimensions are updated correctly in various situations.
- """
- p = self.PersonModel(name='Joe')
+ def test_dimensions(self):
+ """
+ Checks that dimensions are updated correctly in various situations.
+ """
+ p = self.PersonModel(name='Joe')
- # Dimensions should get set if file is saved.
- p.mugshot.save("mug", self.file1)
- self.check_dimensions(p, 4, 8)
+ # Dimensions should get set if file is saved.
+ p.mugshot.save("mug", self.file1)
+ self.check_dimensions(p, 4, 8)
- # Test dimensions after fetching from database.
- p = self.PersonModel.objects.get(name='Joe')
- # Bug 11084: Dimensions should not get recalculated if file is
- # coming from the database. We test this by checking if the file
- # was opened.
- self.assertEqual(p.mugshot.was_opened, False)
- self.check_dimensions(p, 4, 8)
- # After checking dimensions on the image field, the file will have
- # opened.
- self.assertEqual(p.mugshot.was_opened, True)
- # Dimensions should now be cached, and if we reset was_opened and
- # check dimensions again, the file should not have opened.
- p.mugshot.was_opened = False
- self.check_dimensions(p, 4, 8)
- self.assertEqual(p.mugshot.was_opened, False)
+ # Test dimensions after fetching from database.
+ p = self.PersonModel.objects.get(name='Joe')
+ # Bug 11084: Dimensions should not get recalculated if file is
+ # coming from the database. We test this by checking if the file
+ # was opened.
+ self.assertEqual(p.mugshot.was_opened, False)
+ self.check_dimensions(p, 4, 8)
+ # After checking dimensions on the image field, the file will have
+ # opened.
+ self.assertEqual(p.mugshot.was_opened, True)
+ # Dimensions should now be cached, and if we reset was_opened and
+ # check dimensions again, the file should not have opened.
+ p.mugshot.was_opened = False
+ self.check_dimensions(p, 4, 8)
+ self.assertEqual(p.mugshot.was_opened, False)
- # If we assign a new image to the instance, the dimensions should
- # update.
- p.mugshot = self.file2
- self.check_dimensions(p, 8, 4)
- # Dimensions were recalculated, and hence file should have opened.
- self.assertEqual(p.mugshot.was_opened, True)
+ # If we assign a new image to the instance, the dimensions should
+ # update.
+ p.mugshot = self.file2
+ self.check_dimensions(p, 8, 4)
+ # Dimensions were recalculated, and hence file should have opened.
+ self.assertEqual(p.mugshot.was_opened, True)
- class ImageFieldNoDimensionsTests(ImageFieldTwoDimensionsTests):
- """
- Tests behavior of an ImageField with no dimension fields.
- """
+@skipIf(Image is None, "PIL is required to test ImageField")
+class ImageFieldNoDimensionsTests(ImageFieldTwoDimensionsTests):
+ """
+ Tests behavior of an ImageField with no dimension fields.
+ """
- PersonModel = Person
+ PersonModel = Person
- class ImageFieldOneDimensionTests(ImageFieldTwoDimensionsTests):
- """
- Tests behavior of an ImageField with one dimensions field.
- """
+@skipIf(Image is None, "PIL is required to test ImageField")
+class ImageFieldOneDimensionTests(ImageFieldTwoDimensionsTests):
+ """
+ Tests behavior of an ImageField with one dimensions field.
+ """
- PersonModel = PersonWithHeight
+ PersonModel = PersonWithHeight
- class ImageFieldDimensionsFirstTests(ImageFieldTwoDimensionsTests):
- """
- Tests behavior of an ImageField where the dimensions fields are
- defined before the ImageField.
- """
+@skipIf(Image is None, "PIL is required to test ImageField")
+class ImageFieldDimensionsFirstTests(ImageFieldTwoDimensionsTests):
+ """
+ Tests behavior of an ImageField where the dimensions fields are
+ defined before the ImageField.
+ """
- PersonModel = PersonDimensionsFirst
+ PersonModel = PersonDimensionsFirst
- class ImageFieldUsingFileTests(ImageFieldTwoDimensionsTests):
- """
- Tests behavior of an ImageField when assigning it a File instance
- rather than an ImageFile instance.
- """
+@skipIf(Image is None, "PIL is required to test ImageField")
+class ImageFieldUsingFileTests(ImageFieldTwoDimensionsTests):
+ """
+ Tests behavior of an ImageField when assigning it a File instance
+ rather than an ImageFile instance.
+ """
- PersonModel = PersonDimensionsFirst
- File = File
+ PersonModel = PersonDimensionsFirst
+ File = File
- class TwoImageFieldTests(ImageFieldTestMixin, TestCase):
- """
- Tests a model with two ImageFields.
- """
+@skipIf(Image is None, "PIL is required to test ImageField")
+class TwoImageFieldTests(ImageFieldTestMixin, TestCase):
+ """
+ Tests a model with two ImageFields.
+ """
- PersonModel = PersonTwoImages
+ PersonModel = PersonTwoImages
- def test_constructor(self):
- p = self.PersonModel(mugshot=self.file1, headshot=self.file2)
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
- p.save()
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
+ def test_constructor(self):
+ p = self.PersonModel(mugshot=self.file1, headshot=self.file2)
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
+ p.save()
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
- def test_create(self):
- p = self.PersonModel.objects.create(mugshot=self.file1,
- headshot=self.file2)
- self.check_dimensions(p, 4, 8)
- self.check_dimensions(p, 8, 4, 'headshot')
+ def test_create(self):
+ p = self.PersonModel.objects.create(mugshot=self.file1,
+ headshot=self.file2)
+ self.check_dimensions(p, 4, 8)
+ self.check_dimensions(p, 8, 4, 'headshot')
- def test_assignment(self):
- p = self.PersonModel()
- self.check_dimensions(p, None, None, 'mugshot')
- self.check_dimensions(p, None, None, 'headshot')
+ def test_assignment(self):
+ p = self.PersonModel()
+ self.check_dimensions(p, None, None, 'mugshot')
+ self.check_dimensions(p, None, None, 'headshot')
- p.mugshot = self.file1
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, None, None, 'headshot')
- p.headshot = self.file2
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
+ p.mugshot = self.file1
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, None, None, 'headshot')
+ p.headshot = self.file2
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
- # Clear the ImageFields one at a time.
- p.mugshot = None
- self.check_dimensions(p, None, None, 'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
- p.headshot = None
- self.check_dimensions(p, None, None, 'mugshot')
- self.check_dimensions(p, None, None, 'headshot')
+ # Clear the ImageFields one at a time.
+ p.mugshot = None
+ self.check_dimensions(p, None, None, 'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
+ p.headshot = None
+ self.check_dimensions(p, None, None, 'mugshot')
+ self.check_dimensions(p, None, None, 'headshot')
- def test_field_save_and_delete_methods(self):
- p = self.PersonModel(name='Joe')
- p.mugshot.save("mug", self.file1)
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, None, None, 'headshot')
- p.headshot.save("head", self.file2)
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
+ def test_field_save_and_delete_methods(self):
+ p = self.PersonModel(name='Joe')
+ p.mugshot.save("mug", self.file1)
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, None, None, 'headshot')
+ p.headshot.save("head", self.file2)
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
- # We can use save=True when deleting the image field with null=True
- # dimension fields and the other field has an image.
- p.headshot.delete(save=True)
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, None, None, 'headshot')
- p.mugshot.delete(save=False)
- self.check_dimensions(p, None, None, 'mugshot')
- self.check_dimensions(p, None, None, 'headshot')
+ # We can use save=True when deleting the image field with null=True
+ # dimension fields and the other field has an image.
+ p.headshot.delete(save=True)
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, None, None, 'headshot')
+ p.mugshot.delete(save=False)
+ self.check_dimensions(p, None, None, 'mugshot')
+ self.check_dimensions(p, None, None, 'headshot')
- def test_dimensions(self):
- """
- Checks that dimensions are updated correctly in various situations.
- """
- p = self.PersonModel(name='Joe')
+ def test_dimensions(self):
+ """
+ Checks that dimensions are updated correctly in various situations.
+ """
+ p = self.PersonModel(name='Joe')
- # Dimensions should get set for the saved file.
- p.mugshot.save("mug", self.file1)
- p.headshot.save("head", self.file2)
- self.check_dimensions(p, 4, 8, 'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
+ # Dimensions should get set for the saved file.
+ p.mugshot.save("mug", self.file1)
+ p.headshot.save("head", self.file2)
+ self.check_dimensions(p, 4, 8, 'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
- # Test dimensions after fetching from database.
- p = self.PersonModel.objects.get(name='Joe')
- # Bug 11084: Dimensions should not get recalculated if file is
- # coming from the database. We test this by checking if the file
- # was opened.
- self.assertEqual(p.mugshot.was_opened, False)
- self.assertEqual(p.headshot.was_opened, False)
- self.check_dimensions(p, 4, 8,'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
- # After checking dimensions on the image fields, the files will
- # have been opened.
- self.assertEqual(p.mugshot.was_opened, True)
- self.assertEqual(p.headshot.was_opened, True)
- # Dimensions should now be cached, and if we reset was_opened and
- # check dimensions again, the file should not have opened.
- p.mugshot.was_opened = False
- p.headshot.was_opened = False
- self.check_dimensions(p, 4, 8,'mugshot')
- self.check_dimensions(p, 8, 4, 'headshot')
- self.assertEqual(p.mugshot.was_opened, False)
- self.assertEqual(p.headshot.was_opened, False)
+ # Test dimensions after fetching from database.
+ p = self.PersonModel.objects.get(name='Joe')
+ # Bug 11084: Dimensions should not get recalculated if file is
+ # coming from the database. We test this by checking if the file
+ # was opened.
+ self.assertEqual(p.mugshot.was_opened, False)
+ self.assertEqual(p.headshot.was_opened, False)
+ self.check_dimensions(p, 4, 8,'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
+ # After checking dimensions on the image fields, the files will
+ # have been opened.
+ self.assertEqual(p.mugshot.was_opened, True)
+ self.assertEqual(p.headshot.was_opened, True)
+ # Dimensions should now be cached, and if we reset was_opened and
+ # check dimensions again, the file should not have opened.
+ p.mugshot.was_opened = False
+ p.headshot.was_opened = False
+ self.check_dimensions(p, 4, 8,'mugshot')
+ self.check_dimensions(p, 8, 4, 'headshot')
+ self.assertEqual(p.mugshot.was_opened, False)
+ self.assertEqual(p.headshot.was_opened, False)
- # If we assign a new image to the instance, the dimensions should
- # update.
- p.mugshot = self.file2
- p.headshot = self.file1
- self.check_dimensions(p, 8, 4, 'mugshot')
- self.check_dimensions(p, 4, 8, 'headshot')
- # Dimensions were recalculated, and hence file should have opened.
- self.assertEqual(p.mugshot.was_opened, True)
- self.assertEqual(p.headshot.was_opened, True)
+ # If we assign a new image to the instance, the dimensions should
+ # update.
+ p.mugshot = self.file2
+ p.headshot = self.file1
+ self.check_dimensions(p, 8, 4, 'mugshot')
+ self.check_dimensions(p, 4, 8, 'headshot')
+ # Dimensions were recalculated, and hence file should have opened.
+ self.assertEqual(p.mugshot.was_opened, True)
+ self.assertEqual(p.headshot.was_opened, True)
diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py
index 5d3d42ef2a..e86159463d 100644
--- a/tests/regressiontests/model_fields/tests.py
+++ b/tests/regressiontests/model_fields/tests.py
@@ -8,17 +8,16 @@ from django import forms
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models.fields.files import FieldFile
+from django.utils import six
from django.utils import unittest
from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post,
NullBooleanModel, BooleanModel, Document, RenamedField)
-# If PIL available, do these tests.
-if Image:
- from .imagefield import (ImageFieldTests, ImageFieldTwoDimensionsTests,
- TwoImageFieldTests, ImageFieldNoDimensionsTests,
- ImageFieldOneDimensionTests, ImageFieldDimensionsFirstTests,
- ImageFieldUsingFileTests)
+from .imagefield import (ImageFieldTests, ImageFieldTwoDimensionsTests,
+ TwoImageFieldTests, ImageFieldNoDimensionsTests,
+ ImageFieldOneDimensionTests, ImageFieldDimensionsFirstTests,
+ ImageFieldUsingFileTests)
class BasicFieldTests(test.TestCase):
@@ -305,11 +304,11 @@ class BigIntegerFieldTests(test.TestCase):
def test_types(self):
b = BigInt(value = 0)
- self.assertTrue(isinstance(b.value, (int, long)))
+ self.assertTrue(isinstance(b.value, six.integer_types))
b.save()
- self.assertTrue(isinstance(b.value, (int, long)))
+ self.assertTrue(isinstance(b.value, six.integer_types))
b = BigInt.objects.all()[0]
- self.assertTrue(isinstance(b.value, (int, long)))
+ self.assertTrue(isinstance(b.value, six.integer_types))
def test_coercing(self):
BigInt.objects.create(value ='10')
@@ -365,15 +364,3 @@ class FileFieldTests(unittest.TestCase):
field = d._meta.get_field('myfile')
field.save_form_data(d, 'else.txt')
self.assertEqual(d.myfile, 'else.txt')
-
- def test_max_length(self):
- """
- Test that FileField validates the length of the generated file name
- that will be stored in the database. Regression for #9893.
-
- """
- # upload_to = 'unused', so file names are saved as 'unused/xxxxx'.
- # max_length = 100, so names longer than 93 characters are rejected.
- Document(myfile=93 * 'x').full_clean()
- with self.assertRaises(ValidationError):
- Document(myfile=94 * 'x').full_clean()
diff --git a/tests/regressiontests/model_forms_regress/tests.py b/tests/regressiontests/model_forms_regress/tests.py
index a0f9bba170..3cb129f84e 100644
--- a/tests/regressiontests/model_forms_regress/tests.py
+++ b/tests/regressiontests/model_forms_regress/tests.py
@@ -7,6 +7,7 @@ from django.core.exceptions import FieldError, ValidationError
from django.core.files.uploadedfile import SimpleUploadedFile
from django.forms.models import (modelform_factory, ModelChoiceField,
fields_for_model, construct_instance, ModelFormMetaclass)
+from django.utils import six
from django.utils import unittest
from django.test import TestCase
@@ -392,14 +393,14 @@ class FileFieldTests(unittest.TestCase):
"""
form = DocumentForm()
- self.assertTrue('name="myfile"' in unicode(form))
- self.assertTrue('myfile-clear' not in unicode(form))
+ self.assertTrue('name="myfile"' in six.text_type(form))
+ self.assertTrue('myfile-clear' not in six.text_type(form))
form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', b'content')})
self.assertTrue(form.is_valid())
doc = form.save(commit=False)
self.assertEqual(doc.myfile.name, 'something.txt')
form = DocumentForm(instance=doc)
- self.assertTrue('myfile-clear' in unicode(form))
+ self.assertTrue('myfile-clear' in six.text_type(form))
form = DocumentForm(instance=doc, data={'myfile-clear': 'true'})
doc = form.save(commit=False)
self.assertEqual(bool(doc.myfile), False)
@@ -420,7 +421,7 @@ class FileFieldTests(unittest.TestCase):
self.assertTrue(not form.is_valid())
self.assertEqual(form.errors['myfile'],
['Please either submit a file or check the clear checkbox, not both.'])
- rendered = unicode(form)
+ rendered = six.text_type(form)
self.assertTrue('something.txt' in rendered)
self.assertTrue('myfile-clear' in rendered)
diff --git a/tests/regressiontests/model_formsets_regress/tests.py b/tests/regressiontests/model_formsets_regress/tests.py
index 68ebe48bde..1fbdb9744f 100644
--- a/tests/regressiontests/model_formsets_regress/tests.py
+++ b/tests/regressiontests/model_formsets_regress/tests.py
@@ -5,6 +5,7 @@ from django.forms.formsets import BaseFormSet, DELETION_FIELD_NAME
from django.forms.util import ErrorDict, ErrorList
from django.forms.models import modelform_factory, inlineformset_factory, modelformset_factory, BaseModelFormSet
from django.test import TestCase
+from django.utils import six
from .models import User, UserSite, Restaurant, Manager, Network, Host
@@ -51,7 +52,7 @@ class InlineFormsetTests(TestCase):
'usersite_set-TOTAL_FORMS': '1',
'usersite_set-INITIAL_FORMS': '1',
'usersite_set-MAX_NUM_FORMS': '0',
- 'usersite_set-0-id': unicode(usersite[0]['id']),
+ 'usersite_set-0-id': six.text_type(usersite[0]['id']),
'usersite_set-0-data': '11',
'usersite_set-0-user': 'apollo13'
}
@@ -69,7 +70,7 @@ class InlineFormsetTests(TestCase):
'usersite_set-TOTAL_FORMS': '2',
'usersite_set-INITIAL_FORMS': '1',
'usersite_set-MAX_NUM_FORMS': '0',
- 'usersite_set-0-id': unicode(usersite[0]['id']),
+ 'usersite_set-0-id': six.text_type(usersite[0]['id']),
'usersite_set-0-data': '11',
'usersite_set-0-user': 'apollo13',
'usersite_set-1-data': '42',
@@ -124,7 +125,7 @@ class InlineFormsetTests(TestCase):
'manager_set-TOTAL_FORMS': '1',
'manager_set-INITIAL_FORMS': '1',
'manager_set-MAX_NUM_FORMS': '0',
- 'manager_set-0-id': unicode(manager[0]['id']),
+ 'manager_set-0-id': six.text_type(manager[0]['id']),
'manager_set-0-name': 'Terry Gilliam'
}
form_set = FormSet(data, instance=restaurant)
@@ -140,7 +141,7 @@ class InlineFormsetTests(TestCase):
'manager_set-TOTAL_FORMS': '2',
'manager_set-INITIAL_FORMS': '1',
'manager_set-MAX_NUM_FORMS': '0',
- 'manager_set-0-id': unicode(manager[0]['id']),
+ 'manager_set-0-id': six.text_type(manager[0]['id']),
'manager_set-0-name': 'Terry Gilliam',
'manager_set-1-name': 'John Cleese'
}
@@ -188,7 +189,7 @@ class InlineFormsetTests(TestCase):
'host_set-TOTAL_FORMS': '2',
'host_set-INITIAL_FORMS': '1',
'host_set-MAX_NUM_FORMS': '0',
- 'host_set-0-id': unicode(host1.id),
+ 'host_set-0-id': six.text_type(host1.id),
'host_set-0-hostname': 'tranquility.hub.dal.net',
'host_set-1-hostname': 'matrix.de.eu.dal.net'
}
diff --git a/tests/regressiontests/model_regress/tests.py b/tests/regressiontests/model_regress/tests.py
index 7f9f514c7a..6a45a83052 100644
--- a/tests/regressiontests/model_regress/tests.py
+++ b/tests/regressiontests/model_regress/tests.py
@@ -5,6 +5,7 @@ from operator import attrgetter
from django.core.exceptions import ValidationError
from django.test import TestCase, skipUnlessDBFeature
+from django.utils import six
from django.utils import tzinfo
from .models import (Worker, Article, Party, Event, Department,
@@ -38,7 +39,7 @@ class ModelTests(TestCase):
# Empty strings should be returned as Unicode
a = Article.objects.get(pk=a.pk)
self.assertEqual(a.misc_data, '')
- self.assertIs(type(a.misc_data), unicode)
+ self.assertIs(type(a.misc_data), six.text_type)
def test_long_textfield(self):
# TextFields can hold more than 4000 characters (this was broken in
@@ -138,7 +139,7 @@ class ModelTests(TestCase):
# Check Department and Worker (non-default PK type)
d = Department.objects.create(id=10, name="IT")
w = Worker.objects.create(department=d, name="Full-time")
- self.assertEqual(unicode(w), "Full-time")
+ self.assertEqual(six.text_type(w), "Full-time")
def test_broken_unicode(self):
# Models with broken unicode methods should still have a printable repr
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
index 8c34b50e93..6328776e91 100644
--- a/tests/regressiontests/queries/models.py
+++ b/tests/regressiontests/queries/models.py
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import threading
from django.db import models
+from django.utils import six
class DumbCategory(models.Model):
@@ -122,7 +123,7 @@ class Number(models.Model):
num = models.IntegerField()
def __unicode__(self):
- return unicode(self.num)
+ return six.text_type(self.num)
# Symmetrical m2m field with a normal field using the reverse accesor name
# ("valid").
diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
index 4cc7208a96..1582993dfc 100644
--- a/tests/regressiontests/queries/tests.py
+++ b/tests/regressiontests/queries/tests.py
@@ -10,6 +10,8 @@ from django.core.exceptions import FieldError
from django.db import DatabaseError, connection, connections, DEFAULT_DB_ALIAS
from django.db.models import Count
from django.db.models.query import Q, ITER_CHUNK_SIZE, EmptyQuerySet
+from django.db.models.sql.where import WhereNode, EverythingNode, NothingNode
+from django.db.models.sql.datastructures import EmptyResultSet
from django.test import TestCase, skipUnlessDBFeature
from django.test.utils import str_prefix
from django.utils import unittest
@@ -1316,10 +1318,23 @@ class Queries5Tests(TestCase):
)
def test_ticket5261(self):
+ # Test different empty excludes.
self.assertQuerysetEqual(
Note.objects.exclude(Q()),
['<Note: n1>', '<Note: n2>']
)
+ self.assertQuerysetEqual(
+ Note.objects.filter(~Q()),
+ ['<Note: n1>', '<Note: n2>']
+ )
+ self.assertQuerysetEqual(
+ Note.objects.filter(~Q()|~Q()),
+ ['<Note: n1>', '<Note: n2>']
+ )
+ self.assertQuerysetEqual(
+ Note.objects.exclude(~Q()&~Q()),
+ ['<Note: n1>', '<Note: n2>']
+ )
class SelectRelatedTests(TestCase):
@@ -1864,8 +1879,7 @@ class ConditionalTests(BaseQuerysetTest):
# Test that the "in" lookup works with lists of 1000 items or more.
Number.objects.all().delete()
numbers = range(2500)
- for num in numbers:
- _ = Number.objects.create(num=num)
+ Number.objects.bulk_create(Number(num=num) for num in numbers)
self.assertEqual(
Number.objects.filter(num__in=numbers[:1000]).count(),
1000
@@ -2020,3 +2034,74 @@ class ProxyQueryCleanupTest(TestCase):
self.assertEqual(qs.count(), 1)
str(qs.query)
self.assertEqual(qs.count(), 1)
+
+class WhereNodeTest(TestCase):
+ class DummyNode(object):
+ def as_sql(self, qn, connection):
+ return 'dummy', []
+
+ def test_empty_full_handling_conjunction(self):
+ qn = connection.ops.quote_name
+ w = WhereNode(children=[EverythingNode()])
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w.negate()
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w = WhereNode(children=[NothingNode()])
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w = WhereNode(children=[EverythingNode(), EverythingNode()])
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w.negate()
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w = WhereNode(children=[EverythingNode(), self.DummyNode()])
+ self.assertEquals(w.as_sql(qn, connection), ('dummy', []))
+ w = WhereNode(children=[self.DummyNode(), self.DummyNode()])
+ self.assertEquals(w.as_sql(qn, connection), ('(dummy AND dummy)', []))
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), ('NOT (dummy AND dummy)', []))
+ w = WhereNode(children=[NothingNode(), self.DummyNode()])
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+
+ def test_empty_full_handling_disjunction(self):
+ qn = connection.ops.quote_name
+ w = WhereNode(children=[EverythingNode()], connector='OR')
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w.negate()
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w = WhereNode(children=[NothingNode()], connector='OR')
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w = WhereNode(children=[EverythingNode(), EverythingNode()], connector='OR')
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w.negate()
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w = WhereNode(children=[EverythingNode(), self.DummyNode()], connector='OR')
+ self.assertEquals(w.as_sql(qn, connection), ('', []))
+ w.negate()
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
+ w = WhereNode(children=[self.DummyNode(), self.DummyNode()], connector='OR')
+ self.assertEquals(w.as_sql(qn, connection), ('(dummy OR dummy)', []))
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), ('NOT (dummy OR dummy)', []))
+ w = WhereNode(children=[NothingNode(), self.DummyNode()], connector='OR')
+ self.assertEquals(w.as_sql(qn, connection), ('dummy', []))
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), ('NOT (dummy)', []))
+
+ def test_empty_nodes(self):
+ qn = connection.ops.quote_name
+ empty_w = WhereNode()
+ w = WhereNode(children=[empty_w, empty_w])
+ self.assertEquals(w.as_sql(qn, connection), (None, []))
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), (None, []))
+ w.connector = 'OR'
+ self.assertEquals(w.as_sql(qn, connection), (None, []))
+ w.negate()
+ self.assertEquals(w.as_sql(qn, connection), (None, []))
+ w = WhereNode(children=[empty_w, NothingNode()], connector='OR')
+ self.assertRaises(EmptyResultSet, w.as_sql, qn, connection)
diff --git a/tests/regressiontests/queryset_pickle/tests.py b/tests/regressiontests/queryset_pickle/tests.py
index f73e61a900..ab32e8f647 100644
--- a/tests/regressiontests/queryset_pickle/tests.py
+++ b/tests/regressiontests/queryset_pickle/tests.py
@@ -36,3 +36,13 @@ class PickleabilityTestCase(TestCase):
def test_membermethod_as_default(self):
self.assert_pickles(Happening.objects.filter(number4=1))
+
+ def test_doesnotexist_exception(self):
+ # Ticket #17776
+ original = Event.DoesNotExist("Doesn't exist")
+ unpickled = pickle.loads(pickle.dumps(original))
+
+ # Exceptions are not equal to equivalent instances of themselves, so
+ # can't just use assertEqual(original, unpickled)
+ self.assertEqual(original.__class__, unpickled.__class__)
+ self.assertEqual(original.args, unpickled.args)
diff --git a/tests/regressiontests/select_related_regress/tests.py b/tests/regressiontests/select_related_regress/tests.py
index e35157dbaf..7f93a1c33c 100644
--- a/tests/regressiontests/select_related_regress/tests.py
+++ b/tests/regressiontests/select_related_regress/tests.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import, unicode_literals
from django.test import TestCase
+from django.utils import six
from .models import (Building, Child, Device, Port, Item, Country, Connection,
ClientStatus, State, Client, SpecialClient, TUser, Person, Student,
@@ -33,11 +34,11 @@ class SelectRelatedRegressTests(TestCase):
c2=Connection.objects.create(start=port2, end=port3)
connections=Connection.objects.filter(start__device__building=b, end__device__building=b).order_by('id')
- self.assertEqual([(c.id, unicode(c.start), unicode(c.end)) for c in connections],
+ self.assertEqual([(c.id, six.text_type(c.start), six.text_type(c.end)) for c in connections],
[(c1.id, 'router/4', 'switch/7'), (c2.id, 'switch/7', 'server/1')])
connections=Connection.objects.filter(start__device__building=b, end__device__building=b).select_related().order_by('id')
- self.assertEqual([(c.id, unicode(c.start), unicode(c.end)) for c in connections],
+ self.assertEqual([(c.id, six.text_type(c.start), six.text_type(c.end)) for c in connections],
[(c1.id, 'router/4', 'switch/7'), (c2.id, 'switch/7', 'server/1')])
# This final query should only have seven tables (port, device and building
@@ -133,7 +134,7 @@ class SelectRelatedRegressTests(TestCase):
self.assertEqual(troy.state.name, 'Western Australia')
# Also works if you use only, rather than defer
- troy = SpecialClient.objects.select_related('state').only('name').get(name='Troy Buswell')
+ troy = SpecialClient.objects.select_related('state').only('name', 'state').get(name='Troy Buswell')
self.assertEqual(troy.name, 'Troy Buswell')
self.assertEqual(troy.value, 42)
diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py
index f1b70a1d2e..4e73be015c 100644
--- a/tests/regressiontests/serializers_regress/tests.py
+++ b/tests/regressiontests/serializers_regress/tests.py
@@ -21,6 +21,7 @@ from django.core import serializers
from django.core.serializers import SerializerDoesNotExist
from django.core.serializers.base import DeserializationError
from django.db import connection, models
+from django.http import HttpResponse
from django.test import TestCase
from django.utils.functional import curry
from django.utils.unittest import skipUnless
@@ -501,15 +502,18 @@ def streamTest(format, self):
obj.save_base(raw=True)
# Serialize the test database to a stream
- stream = BytesIO()
- serializers.serialize(format, [obj], indent=2, stream=stream)
+ for stream in (BytesIO(), HttpResponse()):
+ serializers.serialize(format, [obj], indent=2, stream=stream)
- # Serialize normally for a comparison
- string_data = serializers.serialize(format, [obj], indent=2)
+ # Serialize normally for a comparison
+ string_data = serializers.serialize(format, [obj], indent=2)
- # Check that the two are the same
- self.assertEqual(string_data, stream.getvalue())
- stream.close()
+ # Check that the two are the same
+ if isinstance(stream, BytesIO):
+ self.assertEqual(string_data, stream.getvalue())
+ else:
+ self.assertEqual(string_data, stream.content)
+ stream.close()
for format in serializers.get_serializer_formats():
setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format))
diff --git a/tests/regressiontests/servers/tests.py b/tests/regressiontests/servers/tests.py
index 9537e1feb3..b98b4b73c2 100644
--- a/tests/regressiontests/servers/tests.py
+++ b/tests/regressiontests/servers/tests.py
@@ -2,7 +2,10 @@
Tests for django.core.servers.
"""
import os
-import urllib2
+try:
+ from urllib.request import urlopen, HTTPError
+except ImportError: # Python 2
+ from urllib2 import urlopen, HTTPError
from django.core.exceptions import ImproperlyConfigured
from django.test import LiveServerTestCase
@@ -39,7 +42,7 @@ class LiveServerBase(LiveServerTestCase):
super(LiveServerBase, cls).tearDownClass()
def urlopen(self, url):
- return urllib2.urlopen(self.live_server_url + url)
+ return urlopen(self.live_server_url + url)
class LiveServerAddress(LiveServerBase):
@@ -102,7 +105,7 @@ class LiveServerViews(LiveServerBase):
"""
try:
self.urlopen('/')
- except urllib2.HTTPError as err:
+ except HTTPError as err:
self.assertEqual(err.code, 404, 'Expected 404 response')
else:
self.fail('Expected 404 response')
diff --git a/tests/regressiontests/staticfiles_tests/apps/test/static/test/nonascii.css b/tests/regressiontests/staticfiles_tests/apps/test/static/test/nonascii.css
new file mode 100644
index 0000000000..a5358f6ede
--- /dev/null
+++ b/tests/regressiontests/staticfiles_tests/apps/test/static/test/nonascii.css
@@ -0,0 +1,5 @@
+body {
+ background: url('window.png');
+}
+
+.snowman:before { content: "☃"; }
diff --git a/tests/regressiontests/staticfiles_tests/apps/test/static/test/window.png b/tests/regressiontests/staticfiles_tests/apps/test/static/test/window.png
new file mode 100644
index 0000000000..ba48325c0a
--- /dev/null
+++ b/tests/regressiontests/staticfiles_tests/apps/test/static/test/window.png
Binary files differ
diff --git a/tests/regressiontests/staticfiles_tests/project/documents/cached/css/ignored.css b/tests/regressiontests/staticfiles_tests/project/documents/cached/css/ignored.css
new file mode 100644
index 0000000000..fe7b022215
--- /dev/null
+++ b/tests/regressiontests/staticfiles_tests/project/documents/cached/css/ignored.css
@@ -0,0 +1,8 @@
+body {
+ background: url("#foobar");
+ background: url("http:foobar");
+ background: url("https:foobar");
+ background: url("data:foobar");
+ background: url("//foobar");
+}
+
diff --git a/tests/regressiontests/staticfiles_tests/project/documents/cached/import.css b/tests/regressiontests/staticfiles_tests/project/documents/cached/import.css
new file mode 100644
index 0000000000..6bc7ce04c4
--- /dev/null
+++ b/tests/regressiontests/staticfiles_tests/project/documents/cached/import.css
@@ -0,0 +1 @@
+@import 'styles.css';
diff --git a/tests/regressiontests/staticfiles_tests/tests.py b/tests/regressiontests/staticfiles_tests/tests.py
index 8321fc2365..2c038e1713 100644
--- a/tests/regressiontests/staticfiles_tests/tests.py
+++ b/tests/regressiontests/staticfiles_tests/tests.py
@@ -20,6 +20,7 @@ from django.test.utils import override_settings
from django.utils.encoding import smart_unicode
from django.utils.functional import empty
from django.utils._os import rmtree_errorhandler
+from django.utils import six
from django.contrib.staticfiles import finders, storage
@@ -53,6 +54,9 @@ class BaseStaticFilesTestCase(object):
# since we're planning on changing that we need to clear out the cache.
default_storage._wrapped = empty
storage.staticfiles_storage._wrapped = empty
+ # Clear the cached staticfile finders, so they are reinitialized every
+ # run and pick up changes in settings.STATICFILES_DIRS.
+ finders._finders.clear()
testfiles_path = os.path.join(TEST_ROOT, 'apps', 'test', 'static', 'test')
# To make sure SVN doesn't hangs itself with the non-ASCII characters
@@ -83,18 +87,20 @@ class BaseStaticFilesTestCase(object):
self.assertRaises(IOError, self._get_file, filepath)
def render_template(self, template, **kwargs):
- if isinstance(template, basestring):
+ if isinstance(template, six.string_types):
template = loader.get_template_from_string(template)
return template.render(Context(kwargs)).strip()
- def static_template_snippet(self, path):
+ def static_template_snippet(self, path, asvar=False):
+ if asvar:
+ return "{%% load static from staticfiles %%}{%% static '%s' as var %%}{{ var }}" % path
return "{%% load static from staticfiles %%}{%% static '%s' %%}" % path
- def assertStaticRenders(self, path, result, **kwargs):
- template = self.static_template_snippet(path)
+ def assertStaticRenders(self, path, result, asvar=False, **kwargs):
+ template = self.static_template_snippet(path, asvar)
self.assertEqual(self.render_template(template, **kwargs), result)
- def assertStaticRaises(self, exc, path, result, **kwargs):
+ def assertStaticRaises(self, exc, path, result, asvar=False, **kwargs):
self.assertRaises(exc, self.assertStaticRenders, path, result, **kwargs)
@@ -368,6 +374,8 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
"/static/does/not/exist.png")
self.assertStaticRenders("test/file.txt",
"/static/test/file.dad0999e4f8f.txt")
+ self.assertStaticRenders("test/file.txt",
+ "/static/test/file.dad0999e4f8f.txt", asvar=True)
self.assertStaticRenders("cached/styles.css",
"/static/cached/styles.93b1147e8552.css")
self.assertStaticRenders("path/",
@@ -383,6 +391,17 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
self.assertNotIn(b"cached/other.css", content)
self.assertIn(b"other.d41d8cd98f00.css", content)
+ def test_path_ignored_completely(self):
+ relpath = self.cached_file_path("cached/css/ignored.css")
+ self.assertEqual(relpath, "cached/css/ignored.6c77f2643390.css")
+ with storage.staticfiles_storage.open(relpath) as relfile:
+ content = relfile.read()
+ self.assertIn(b'#foobar', content)
+ self.assertIn(b'http:foobar', content)
+ self.assertIn(b'https:foobar', content)
+ self.assertIn(b'data:foobar', content)
+ self.assertIn(b'//foobar', content)
+
def test_path_with_querystring(self):
relpath = self.cached_file_path("cached/styles.css?spam=eggs")
self.assertEqual(relpath,
@@ -442,6 +461,13 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
self.assertIn(b'url("img/relative.acae32e4532b.png")', content)
self.assertIn(b"../cached/styles.93b1147e8552.css", content)
+ def test_import_replacement(self):
+ "See #18050"
+ relpath = self.cached_file_path("cached/import.css")
+ self.assertEqual(relpath, "cached/import.2b1d40b0bbd4.css")
+ with storage.staticfiles_storage.open(relpath) as relfile:
+ self.assertIn(b"""import url("styles.93b1147e8552.css")""", relfile.read())
+
def test_template_tag_deep_relative(self):
relpath = self.cached_file_path("cached/css/window.css")
self.assertEqual(relpath, "cached/css/window.9db38d5169f3.css")
@@ -494,8 +520,9 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
collectstatic_cmd = CollectstaticCommand()
collectstatic_cmd.set_options(**collectstatic_args)
stats = collectstatic_cmd.collect()
- self.assertTrue(os.path.join('cached', 'css', 'window.css') in stats['post_processed'])
- self.assertTrue(os.path.join('cached', 'css', 'img', 'window.png') in stats['unmodified'])
+ self.assertIn(os.path.join('cached', 'css', 'window.css'), stats['post_processed'])
+ self.assertIn(os.path.join('cached', 'css', 'img', 'window.png'), stats['unmodified'])
+ self.assertIn(os.path.join('test', 'nonascii.css'), stats['post_processed'])
def test_cache_key_memcache_validation(self):
"""
diff --git a/tests/regressiontests/templates/templatetags/custom.py b/tests/regressiontests/templates/templatetags/custom.py
index 7f788311c6..95fcd551de 100644
--- a/tests/regressiontests/templates/templatetags/custom.py
+++ b/tests/regressiontests/templates/templatetags/custom.py
@@ -3,6 +3,7 @@ import operator
from django import template
from django.template.defaultfilters import stringfilter
from django.template.loader import get_template
+from django.utils import six
register = template.Library()
@@ -56,13 +57,13 @@ simple_one_default.anything = "Expected simple_one_default __dict__"
@register.simple_tag
def simple_unlimited_args(one, two='hi', *args):
"""Expected simple_unlimited_args __doc__"""
- return "simple_unlimited_args - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))
+ return "simple_unlimited_args - Expected result: %s" % (', '.join([six.text_type(arg) for arg in [one, two] + list(args)]))
simple_unlimited_args.anything = "Expected simple_unlimited_args __dict__"
@register.simple_tag
def simple_only_unlimited_args(*args):
"""Expected simple_only_unlimited_args __doc__"""
- return "simple_only_unlimited_args - Expected result: %s" % ', '.join([unicode(arg) for arg in args])
+ return "simple_only_unlimited_args - Expected result: %s" % ', '.join([six.text_type(arg) for arg in args])
simple_only_unlimited_args.anything = "Expected simple_only_unlimited_args __dict__"
@register.simple_tag
@@ -71,7 +72,7 @@ def simple_unlimited_args_kwargs(one, two='hi', *args, **kwargs):
# Sort the dictionary by key to guarantee the order for testing.
sorted_kwarg = sorted(kwargs.iteritems(), key=operator.itemgetter(0))
return "simple_unlimited_args_kwargs - Expected result: %s / %s" % (
- ', '.join([unicode(arg) for arg in [one, two] + list(args)]),
+ ', '.join([six.text_type(arg) for arg in [one, two] + list(args)]),
', '.join(['%s=%s' % (k, v) for (k, v) in sorted_kwarg])
)
simple_unlimited_args_kwargs.anything = "Expected simple_unlimited_args_kwargs __dict__"
@@ -183,25 +184,25 @@ inclusion_one_default_from_template.anything = "Expected inclusion_one_default_f
@register.inclusion_tag('inclusion.html')
def inclusion_unlimited_args(one, two='hi', *args):
"""Expected inclusion_unlimited_args __doc__"""
- return {"result": "inclusion_unlimited_args - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))}
+ return {"result": "inclusion_unlimited_args - Expected result: %s" % (', '.join([six.text_type(arg) for arg in [one, two] + list(args)]))}
inclusion_unlimited_args.anything = "Expected inclusion_unlimited_args __dict__"
@register.inclusion_tag(get_template('inclusion.html'))
def inclusion_unlimited_args_from_template(one, two='hi', *args):
"""Expected inclusion_unlimited_args_from_template __doc__"""
- return {"result": "inclusion_unlimited_args_from_template - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))}
+ return {"result": "inclusion_unlimited_args_from_template - Expected result: %s" % (', '.join([six.text_type(arg) for arg in [one, two] + list(args)]))}
inclusion_unlimited_args_from_template.anything = "Expected inclusion_unlimited_args_from_template __dict__"
@register.inclusion_tag('inclusion.html')
def inclusion_only_unlimited_args(*args):
"""Expected inclusion_only_unlimited_args __doc__"""
- return {"result": "inclusion_only_unlimited_args - Expected result: %s" % (', '.join([unicode(arg) for arg in args]))}
+ return {"result": "inclusion_only_unlimited_args - Expected result: %s" % (', '.join([six.text_type(arg) for arg in args]))}
inclusion_only_unlimited_args.anything = "Expected inclusion_only_unlimited_args __dict__"
@register.inclusion_tag(get_template('inclusion.html'))
def inclusion_only_unlimited_args_from_template(*args):
"""Expected inclusion_only_unlimited_args_from_template __doc__"""
- return {"result": "inclusion_only_unlimited_args_from_template - Expected result: %s" % (', '.join([unicode(arg) for arg in args]))}
+ return {"result": "inclusion_only_unlimited_args_from_template - Expected result: %s" % (', '.join([six.text_type(arg) for arg in args]))}
inclusion_only_unlimited_args_from_template.anything = "Expected inclusion_only_unlimited_args_from_template __dict__"
@register.inclusion_tag('test_incl_tag_current_app.html', takes_context=True)
@@ -222,7 +223,7 @@ def inclusion_unlimited_args_kwargs(one, two='hi', *args, **kwargs):
# Sort the dictionary by key to guarantee the order for testing.
sorted_kwarg = sorted(kwargs.iteritems(), key=operator.itemgetter(0))
return {"result": "inclusion_unlimited_args_kwargs - Expected result: %s / %s" % (
- ', '.join([unicode(arg) for arg in [one, two] + list(args)]),
+ ', '.join([six.text_type(arg) for arg in [one, two] + list(args)]),
', '.join(['%s=%s' % (k, v) for (k, v) in sorted_kwarg])
)}
inclusion_unlimited_args_kwargs.anything = "Expected inclusion_unlimited_args_kwargs __dict__"
@@ -278,13 +279,13 @@ assignment_one_default.anything = "Expected assignment_one_default __dict__"
@register.assignment_tag
def assignment_unlimited_args(one, two='hi', *args):
"""Expected assignment_unlimited_args __doc__"""
- return "assignment_unlimited_args - Expected result: %s" % (', '.join([unicode(arg) for arg in [one, two] + list(args)]))
+ return "assignment_unlimited_args - Expected result: %s" % (', '.join([six.text_type(arg) for arg in [one, two] + list(args)]))
assignment_unlimited_args.anything = "Expected assignment_unlimited_args __dict__"
@register.assignment_tag
def assignment_only_unlimited_args(*args):
"""Expected assignment_only_unlimited_args __doc__"""
- return "assignment_only_unlimited_args - Expected result: %s" % ', '.join([unicode(arg) for arg in args])
+ return "assignment_only_unlimited_args - Expected result: %s" % ', '.join([six.text_type(arg) for arg in args])
assignment_only_unlimited_args.anything = "Expected assignment_only_unlimited_args __dict__"
@register.assignment_tag
@@ -293,7 +294,7 @@ def assignment_unlimited_args_kwargs(one, two='hi', *args, **kwargs):
# Sort the dictionary by key to guarantee the order for testing.
sorted_kwarg = sorted(kwargs.iteritems(), key=operator.itemgetter(0))
return "assignment_unlimited_args_kwargs - Expected result: %s / %s" % (
- ', '.join([unicode(arg) for arg in [one, two] + list(args)]),
+ ', '.join([six.text_type(arg) for arg in [one, two] + list(args)]),
', '.join(['%s=%s' % (k, v) for (k, v) in sorted_kwarg])
)
assignment_unlimited_args_kwargs.anything = "Expected assignment_unlimited_args_kwargs __dict__"
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 989fd72d94..402cbb19d2 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -13,7 +13,10 @@ import time
import os
import sys
import traceback
-from urlparse import urljoin
+try:
+ from urllib.parse import urljoin
+except ImportError: # Python 2
+ from urlparse import urljoin
from django import template
from django.template import base as template_base, RequestContext, Template, Context
@@ -1616,6 +1619,8 @@ class Templates(unittest.TestCase):
'static-prefixtag04': ('{% load static %}{% get_media_prefix as media_prefix %}{{ media_prefix }}', {}, settings.MEDIA_URL),
'static-statictag01': ('{% load static %}{% static "admin/base.css" %}', {}, urljoin(settings.STATIC_URL, 'admin/base.css')),
'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')),
+ 'static-statictag03': ('{% load static %}{% static "admin/base.css" as foo %}{{ foo }}', {}, urljoin(settings.STATIC_URL, 'admin/base.css')),
+ 'static-statictag04': ('{% load static %}{% static base_css as foo %}{{ foo }}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')),
# Verbatim template tag outputs contents without rendering.
'verbatim-tag01': ('{% verbatim %}{{bare }}{% endverbatim %}', {}, '{{bare }}'),
@@ -1623,7 +1628,7 @@ class Templates(unittest.TestCase):
'verbatim-tag03': ("{% verbatim %}It's the {% verbatim %} tag{% endverbatim %}", {}, "It's the {% verbatim %} tag"),
'verbatim-tag04': ('{% verbatim %}{% verbatim %}{% endverbatim %}{% endverbatim %}', {}, template.TemplateSyntaxError),
'verbatim-tag05': ('{% verbatim %}{% endverbatim %}{% verbatim %}{% endverbatim %}', {}, ''),
- 'verbatim-tag06': ("{% verbatim -- %}Don't {% endverbatim %} just yet{% -- %}", {}, "Don't {% endverbatim %} just yet"),
+ 'verbatim-tag06': ("{% verbatim special %}Don't {% endverbatim %} just yet{% endverbatim special %}", {}, "Don't {% endverbatim %} just yet"),
}
return tests
diff --git a/tests/regressiontests/templates/unicode.py b/tests/regressiontests/templates/unicode.py
index 2c41176b01..7cb2a28d15 100644
--- a/tests/regressiontests/templates/unicode.py
+++ b/tests/regressiontests/templates/unicode.py
@@ -3,6 +3,7 @@ from __future__ import unicode_literals
from django.template import Template, TemplateEncodingError, Context
from django.utils.safestring import SafeData
+from django.utils import six
from django.utils.unittest import TestCase
@@ -27,5 +28,5 @@ class UnicodeTests(TestCase):
# they all render the same (and are returned as unicode objects and
# "safe" objects as well, for auto-escaping purposes).
self.assertEqual(t1.render(c3), t2.render(c3))
- self.assertIsInstance(t1.render(c3), unicode)
+ self.assertIsInstance(t1.render(c3), six.text_type)
self.assertIsInstance(t1.render(c3), SafeData)
diff --git a/tests/regressiontests/test_client_regress/views.py b/tests/regressiontests/test_client_regress/views.py
index 3a934ea047..8792a97dc0 100644
--- a/tests/regressiontests/test_client_regress/views.py
+++ b/tests/regressiontests/test_client_regress/views.py
@@ -84,7 +84,7 @@ def return_json_file(request):
cls=DjangoJSONEncoder,
ensure_ascii=False)
response = HttpResponse(obj_json.encode(charset), status=200,
- mimetype='application/json; charset=%s' % charset)
+ content_type='application/json; charset=%s' % charset)
response['Content-Disposition'] = 'attachment; filename=testfile.json'
return response
diff --git a/tests/regressiontests/test_runner/tests.py b/tests/regressiontests/test_runner/tests.py
index 8c6dabf771..c723f162a4 100644
--- a/tests/regressiontests/test_runner/tests.py
+++ b/tests/regressiontests/test_runner/tests.py
@@ -267,6 +267,9 @@ class AutoIncrementResetTest(TransactionTestCase):
and check that both times they get "1" as their PK value. That is, we test
that AutoField values start from 1 for each transactional test case.
"""
+
+ reset_sequences = True
+
@skipUnlessDBFeature('supports_sequence_reset')
def test_autoincrement_reset1(self):
p = Person.objects.create(first_name='Jack', last_name='Smith')
diff --git a/tests/regressiontests/transactions_regress/tests.py b/tests/regressiontests/transactions_regress/tests.py
index abd7a4ceaa..90b3df03d4 100644
--- a/tests/regressiontests/transactions_regress/tests.py
+++ b/tests/regressiontests/transactions_regress/tests.py
@@ -1,11 +1,11 @@
from __future__ import absolute_import
from django.core.exceptions import ImproperlyConfigured
-from django.db import connection, transaction
+from django.db import connection, connections, transaction, DEFAULT_DB_ALIAS
from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
from django.test import TransactionTestCase, skipUnlessDBFeature
from django.test.utils import override_settings
-from django.utils.unittest import skipIf
+from django.utils.unittest import skipIf, skipUnless
from .models import Mod, M2mA, M2mB
@@ -175,6 +175,59 @@ class TestTransactionClosing(TransactionTestCase):
self.test_failing_query_transaction_closed()
+@skipUnless(connection.vendor == 'postgresql',
+ "This test only valid for PostgreSQL")
+class TestPostgresAutocommit(TransactionTestCase):
+ """
+ Tests to make sure psycopg2's autocommit mode is restored after entering
+ and leaving transaction management. Refs #16047.
+ """
+ def setUp(self):
+ from psycopg2.extensions import (ISOLATION_LEVEL_AUTOCOMMIT,
+ ISOLATION_LEVEL_READ_COMMITTED)
+ self._autocommit = ISOLATION_LEVEL_AUTOCOMMIT
+ self._read_committed = ISOLATION_LEVEL_READ_COMMITTED
+
+ # We want a clean backend with autocommit = True, so
+ # first we need to do a bit of work to have that.
+ self._old_backend = connections[DEFAULT_DB_ALIAS]
+ settings = self._old_backend.settings_dict.copy()
+ opts = settings['OPTIONS'].copy()
+ opts['autocommit'] = True
+ settings['OPTIONS'] = opts
+ new_backend = self._old_backend.__class__(settings, DEFAULT_DB_ALIAS)
+ connections[DEFAULT_DB_ALIAS] = new_backend
+
+ def tearDown(self):
+ connections[DEFAULT_DB_ALIAS] = self._old_backend
+
+ def test_initial_autocommit_state(self):
+ self.assertTrue(connection.features.uses_autocommit)
+ self.assertEqual(connection.isolation_level, self._autocommit)
+
+ def test_transaction_management(self):
+ transaction.enter_transaction_management()
+ transaction.managed(True)
+ self.assertEqual(connection.isolation_level, self._read_committed)
+
+ transaction.leave_transaction_management()
+ self.assertEqual(connection.isolation_level, self._autocommit)
+
+ def test_transaction_stacking(self):
+ transaction.enter_transaction_management()
+ transaction.managed(True)
+ self.assertEqual(connection.isolation_level, self._read_committed)
+
+ transaction.enter_transaction_management()
+ self.assertEqual(connection.isolation_level, self._read_committed)
+
+ transaction.leave_transaction_management()
+ self.assertEqual(connection.isolation_level, self._read_committed)
+
+ transaction.leave_transaction_management()
+ self.assertEqual(connection.isolation_level, self._autocommit)
+
+
class TestManyToManyAddTransaction(TransactionTestCase):
def test_manyrelated_add_commit(self):
"Test for https://code.djangoproject.com/ticket/16818"
diff --git a/tests/regressiontests/urlpatterns_reverse/erroneous_urls.py b/tests/regressiontests/urlpatterns_reverse/erroneous_urls.py
index 8e6433e16e..d1e4f3db5d 100644
--- a/tests/regressiontests/urlpatterns_reverse/erroneous_urls.py
+++ b/tests/regressiontests/urlpatterns_reverse/erroneous_urls.py
@@ -11,4 +11,6 @@ urlpatterns = patterns('',
url(r'uncallable/$', 'regressiontests.urlpatterns_reverse.views.uncallable'),
# Module does not exist
url(r'missing_outer/$', 'regressiontests.urlpatterns_reverse.missing_module.missing_view'),
+ # Regex contains an error (refs #6170)
+ url(r'(regex_error/$', 'regressiontestes.urlpatterns_reverse.views.empty_view'),
)
diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
index bb25806830..500a0e0327 100644
--- a/tests/regressiontests/urlpatterns_reverse/tests.py
+++ b/tests/regressiontests/urlpatterns_reverse/tests.py
@@ -511,3 +511,11 @@ class ErroneousViewTests(TestCase):
self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_outer/')
self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable/')
+ def test_erroneous_reverse(self):
+ """
+ Ensure that a useful exception is raised when a regex is invalid in the
+ URLConf.
+ Refs #6170.
+ """
+ # The regex error will be hit before NoReverseMatch can be raised
+ self.assertRaises(ImproperlyConfigured, reverse, 'whatever blah blah')
diff --git a/tests/regressiontests/utils/datastructures.py b/tests/regressiontests/utils/datastructures.py
index 000f7f76a1..dbc65d37a8 100644
--- a/tests/regressiontests/utils/datastructures.py
+++ b/tests/regressiontests/utils/datastructures.py
@@ -4,10 +4,12 @@ Tests for stuff in django.utils.datastructures.
import copy
import pickle
+import warnings
from django.test import SimpleTestCase
-from django.utils.datastructures import (DictWrapper, DotExpandedDict,
- ImmutableList, MultiValueDict, MultiValueDictKeyError, MergeDict, SortedDict)
+from django.utils.datastructures import (DictWrapper, ImmutableList,
+ MultiValueDict, MultiValueDictKeyError, MergeDict, SortedDict)
+from django.utils import six
class SortedDictTests(SimpleTestCase):
@@ -24,19 +26,19 @@ class SortedDictTests(SimpleTestCase):
self.d2[7] = 'seven'
def test_basic_methods(self):
- self.assertEqual(self.d1.keys(), [7, 1, 9])
- self.assertEqual(self.d1.values(), ['seven', 'one', 'nine'])
- self.assertEqual(self.d1.items(), [(7, 'seven'), (1, 'one'), (9, 'nine')])
+ self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9])
+ self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'one', 'nine'])
+ self.assertEqual(list(six.iteritems(self.d1)), [(7, 'seven'), (1, 'one'), (9, 'nine')])
def test_overwrite_ordering(self):
- """ Overwriting an item keeps it's place. """
+ """ Overwriting an item keeps its place. """
self.d1[1] = 'ONE'
- self.assertEqual(self.d1.values(), ['seven', 'ONE', 'nine'])
+ self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'ONE', 'nine'])
def test_append_items(self):
""" New items go to the end. """
self.d1[0] = 'nil'
- self.assertEqual(self.d1.keys(), [7, 1, 9, 0])
+ self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9, 0])
def test_delete_and_insert(self):
"""
@@ -44,18 +46,22 @@ class SortedDictTests(SimpleTestCase):
at the end.
"""
del self.d2[7]
- self.assertEqual(self.d2.keys(), [1, 9, 0])
+ self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0])
self.d2[7] = 'lucky number 7'
- self.assertEqual(self.d2.keys(), [1, 9, 0, 7])
+ self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0, 7])
- def test_change_keys(self):
- """
- Changing the keys won't do anything, it's only a copy of the
- keys dict.
- """
- k = self.d2.keys()
- k.remove(9)
- self.assertEqual(self.d2.keys(), [1, 9, 0, 7])
+ if not six.PY3:
+ def test_change_keys(self):
+ """
+ Changing the keys won't do anything, it's only a copy of the
+ keys dict.
+
+ This test doesn't make sense under Python 3 because keys is
+ an iterator.
+ """
+ k = self.d2.keys()
+ k.remove(9)
+ self.assertEqual(self.d2.keys(), [1, 9, 0, 7])
def test_init_keys(self):
"""
@@ -67,18 +73,18 @@ class SortedDictTests(SimpleTestCase):
tuples = ((2, 'two'), (1, 'one'), (2, 'second-two'))
d = SortedDict(tuples)
- self.assertEqual(d.keys(), [2, 1])
+ self.assertEqual(list(six.iterkeys(d)), [2, 1])
real_dict = dict(tuples)
- self.assertEqual(sorted(real_dict.values()), ['one', 'second-two'])
+ self.assertEqual(sorted(six.itervalues(real_dict)), ['one', 'second-two'])
# Here the order of SortedDict values *is* what we are testing
- self.assertEqual(d.values(), ['second-two', 'one'])
+ self.assertEqual(list(six.itervalues(d)), ['second-two', 'one'])
def test_overwrite(self):
self.d1[1] = 'not one'
self.assertEqual(self.d1[1], 'not one')
- self.assertEqual(self.d1.keys(), self.d1.copy().keys())
+ self.assertEqual(list(six.iterkeys(self.d1)), list(six.iterkeys(self.d1.copy())))
def test_append(self):
self.d1[13] = 'thirteen'
@@ -98,7 +104,7 @@ class SortedDictTests(SimpleTestCase):
self.assertEqual(l - len(self.d1), 1)
def test_dict_equality(self):
- d = SortedDict((i, i) for i in xrange(3))
+ d = SortedDict((i, i) for i in range(3))
self.assertEqual(d, {0: 0, 1: 1, 2: 2})
def test_tuple_init(self):
@@ -114,14 +120,29 @@ class SortedDictTests(SimpleTestCase):
def test_copy(self):
orig = SortedDict(((1, "one"), (0, "zero"), (2, "two")))
copied = copy.copy(orig)
- self.assertEqual(orig.keys(), [1, 0, 2])
- self.assertEqual(copied.keys(), [1, 0, 2])
+ self.assertEqual(list(six.iterkeys(orig)), [1, 0, 2])
+ self.assertEqual(list(six.iterkeys(copied)), [1, 0, 2])
def test_clear(self):
self.d1.clear()
self.assertEqual(self.d1, {})
self.assertEqual(self.d1.keyOrder, [])
+ def test_insert(self):
+ d = SortedDict()
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter("always")
+ d.insert(0, "hello", "world")
+ assert w[0].category is PendingDeprecationWarning
+
+ def test_value_for_index(self):
+ d = SortedDict({"a": 3})
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter("always")
+ self.assertEqual(d.value_for_index(0), 3)
+ assert w[0].category is PendingDeprecationWarning
+
+
class MergeDictTests(SimpleTestCase):
def test_simple_mergedict(self):
@@ -162,12 +183,12 @@ class MergeDictTests(SimpleTestCase):
self.assertEqual(mm.getlist('key4'), ['value5', 'value6'])
self.assertEqual(mm.getlist('undefined'), [])
- self.assertEqual(sorted(mm.keys()), ['key1', 'key2', 'key4'])
- self.assertEqual(len(mm.values()), 3)
+ self.assertEqual(sorted(six.iterkeys(mm)), ['key1', 'key2', 'key4'])
+ self.assertEqual(len(list(six.itervalues(mm))), 3)
- self.assertTrue('value1' in mm.values())
+ self.assertTrue('value1' in six.itervalues(mm))
- self.assertEqual(sorted(mm.items(), key=lambda k: k[0]),
+ self.assertEqual(sorted(six.iteritems(mm), key=lambda k: k[0]),
[('key1', 'value1'), ('key2', 'value3'),
('key4', 'value6')])
@@ -185,10 +206,10 @@ class MultiValueDictTests(SimpleTestCase):
self.assertEqual(d['name'], 'Simon')
self.assertEqual(d.get('name'), 'Simon')
self.assertEqual(d.getlist('name'), ['Adrian', 'Simon'])
- self.assertEqual(list(d.iteritems()),
+ self.assertEqual(list(six.iteritems(d)),
[('position', 'Developer'), ('name', 'Simon')])
- self.assertEqual(list(d.iterlists()),
+ self.assertEqual(list(six.iterlists(d)),
[('position', ['Developer']),
('name', ['Adrian', 'Simon'])])
@@ -208,8 +229,7 @@ class MultiValueDictTests(SimpleTestCase):
d.setlist('lastname', ['Holovaty', 'Willison'])
self.assertEqual(d.getlist('lastname'), ['Holovaty', 'Willison'])
- self.assertEqual(d.values(), ['Developer', 'Simon', 'Willison'])
- self.assertEqual(list(d.itervalues()),
+ self.assertEqual(list(six.itervalues(d)),
['Developer', 'Simon', 'Willison'])
def test_appendlist(self):
@@ -244,27 +264,13 @@ class MultiValueDictTests(SimpleTestCase):
'pm': ['Rory'],
})
d = mvd.dict()
- self.assertEqual(d.keys(), mvd.keys())
- for key in mvd.keys():
+ self.assertEqual(list(six.iterkeys(d)), list(six.iterkeys(mvd)))
+ for key in six.iterkeys(mvd):
self.assertEqual(d[key], mvd[key])
self.assertEqual({}, MultiValueDict().dict())
-class DotExpandedDictTests(SimpleTestCase):
-
- def test_dotexpandeddict(self):
-
- d = DotExpandedDict({'person.1.firstname': ['Simon'],
- 'person.1.lastname': ['Willison'],
- 'person.2.firstname': ['Adrian'],
- 'person.2.lastname': ['Holovaty']})
-
- self.assertEqual(d['person']['1']['lastname'], ['Willison'])
- self.assertEqual(d['person']['2']['lastname'], ['Holovaty'])
- self.assertEqual(d['person']['2']['firstname'], ['Adrian'])
-
-
class ImmutableListTests(SimpleTestCase):
def test_sort(self):
diff --git a/tests/regressiontests/utils/html.py b/tests/regressiontests/utils/html.py
index 434873b9e0..fe40d4eaae 100644
--- a/tests/regressiontests/utils/html.py
+++ b/tests/regressiontests/utils/html.py
@@ -34,6 +34,17 @@ class TestUtilsHtml(unittest.TestCase):
# Verify it doesn't double replace &.
self.check_output(f, '<&', '&lt;&amp;')
+ def test_format_html(self):
+ self.assertEqual(
+ html.format_html("{0} {1} {third} {fourth}",
+ "< Dangerous >",
+ html.mark_safe("<b>safe</b>"),
+ third="< dangerous again",
+ fourth=html.mark_safe("<i>safe again</i>")
+ ),
+ "&lt; Dangerous &gt; <b>safe</b> &lt; dangerous again <i>safe again</i>"
+ )
+
def test_linebreaks(self):
f = html.linebreaks
items = (
diff --git a/tests/regressiontests/utils/simplelazyobject.py b/tests/regressiontests/utils/simplelazyobject.py
index 982d2226e6..960a5e3201 100644
--- a/tests/regressiontests/utils/simplelazyobject.py
+++ b/tests/regressiontests/utils/simplelazyobject.py
@@ -4,6 +4,7 @@ import copy
import pickle
from django.test.utils import str_prefix
+from django.utils import six
from django.utils.unittest import TestCase
from django.utils.functional import SimpleLazyObject, empty
@@ -22,7 +23,7 @@ class _ComplexObject(object):
return "I am _ComplexObject(%r)" % self.name
def __unicode__(self):
- return unicode(self.name)
+ return six.text_type(self.name)
def __repr__(self):
return "_ComplexObject(%r)" % self.name
@@ -58,7 +59,7 @@ class TestUtilsSimpleLazyObject(TestCase):
str(SimpleLazyObject(complex_object)))
def test_unicode(self):
- self.assertEqual("joe", unicode(SimpleLazyObject(complex_object)))
+ self.assertEqual("joe", six.text_type(SimpleLazyObject(complex_object)))
def test_class(self):
# This is important for classes that use __class__ in things like
@@ -108,5 +109,5 @@ class TestUtilsSimpleLazyObject(TestCase):
pickled = pickle.dumps(x)
unpickled = pickle.loads(pickled)
self.assertEqual(unpickled, x)
- self.assertEqual(unicode(unpickled), unicode(x))
+ self.assertEqual(six.text_type(unpickled), six.text_type(x))
self.assertEqual(unpickled.name, x.name)
diff --git a/tests/regressiontests/utils/tests.py b/tests/regressiontests/utils/tests.py
index f5ca06ef1e..a7deeeefae 100644
--- a/tests/regressiontests/utils/tests.py
+++ b/tests/regressiontests/utils/tests.py
@@ -16,7 +16,7 @@ from .decorators import DecoratorFromMiddlewareTests
from .functional import FunctionalTestCase
from .timesince import TimesinceTests
from .datastructures import (MultiValueDictTests, SortedDictTests,
- DictWrapperTests, ImmutableListTests, DotExpandedDictTests, MergeDictTests)
+ DictWrapperTests, ImmutableListTests, MergeDictTests)
from .tzinfo import TzinfoTests
from .datetime_safe import DatetimeTests
from .baseconv import TestBaseConv
diff --git a/tests/regressiontests/wsgi/tests.py b/tests/regressiontests/wsgi/tests.py
index 9614a81c67..a482a5c1eb 100644
--- a/tests/regressiontests/wsgi/tests.py
+++ b/tests/regressiontests/wsgi/tests.py
@@ -6,6 +6,7 @@ from django.core.wsgi import get_wsgi_application
from django.test import TestCase
from django.test.client import RequestFactory
from django.test.utils import override_settings
+from django.utils import six
from django.utils import unittest
@@ -39,7 +40,7 @@ class WSGITest(TestCase):
response_data["headers"],
[('Content-Type', 'text/html; charset=utf-8')])
self.assertEqual(
- unicode(response),
+ six.text_type(response),
"Content-Type: text/html; charset=utf-8\n\nHello World!")
diff --git a/tests/runtests.py b/tests/runtests.py
index b71cf98b13..c548d2745b 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -7,6 +7,7 @@ import tempfile
import warnings
from django import contrib
+from django.utils import six
# databrowse is deprecated, but we still want to run its tests
warnings.filterwarnings('ignore', "The Databrowse contrib app is deprecated",
@@ -142,7 +143,7 @@ def teardown(state):
# so that it will successfully remove temp trees containing
# non-ASCII filenames on Windows. (We're assuming the temp dir
# name itself does not contain non-ASCII characters.)
- shutil.rmtree(unicode(TEMP_DIR))
+ shutil.rmtree(six.text_type(TEMP_DIR))
# Restore the old settings.
for key, value in state.items():
setattr(settings, key, value)