From 813241f65562bc0e7f20264238424d82bee2febc Mon Sep 17 00:00:00 2001 From: Matt Stevens Date: Mon, 3 Sep 2012 15:20:05 +0100 Subject: [PATCH 01/23] Clarifies day and month in example queryset --- docs/topics/db/queries.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 60437c1120..1203dab092 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -235,14 +235,14 @@ refinements together. For example:: ... ).exclude( ... pub_date__gte=datetime.now() ... ).filter( - ... pub_date__gte=datetime(2005, 1, 1) + ... pub_date__gte=datetime(2005, 1, 2) ... ) This takes the initial :class:`~django.db.models.query.QuerySet` of all entries in the database, adds a filter, then an exclusion, then another filter. The final result is a :class:`~django.db.models.query.QuerySet` containing all entries with a headline that starts with "What", that were published between -January 1, 2005, and the current day. +January 2, 2005, and the current day. .. _filtered-querysets-are-unique: From a7d831a3056449b2aca88492031be8cedef58f87 Mon Sep 17 00:00:00 2001 From: Matt Stevens Date: Mon, 3 Sep 2012 16:31:37 +0100 Subject: [PATCH 02/23] Changes day to from 2 to 30 --- docs/topics/db/queries.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt index 1203dab092..f87fa2920f 100644 --- a/docs/topics/db/queries.txt +++ b/docs/topics/db/queries.txt @@ -235,14 +235,14 @@ refinements together. For example:: ... ).exclude( ... pub_date__gte=datetime.now() ... ).filter( - ... pub_date__gte=datetime(2005, 1, 2) + ... pub_date__gte=datetime(2005, 1, 30) ... ) This takes the initial :class:`~django.db.models.query.QuerySet` of all entries in the database, adds a filter, then an exclusion, then another filter. The final result is a :class:`~django.db.models.query.QuerySet` containing all entries with a headline that starts with "What", that were published between -January 2, 2005, and the current day. +January 30, 2005, and the current day. .. _filtered-querysets-are-unique: From e5983af7c16cc889cf7d52fdae67270717a1a846 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Wed, 5 Sep 2012 17:50:17 -0400 Subject: [PATCH 03/23] Fixed #18904 - Typo in MySQL link; thanks Johie Anderson for the report. --- docs/ref/models/querysets.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index b59b2ece82..4f5f8858b5 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -2064,7 +2064,7 @@ Note this is only available in MySQL and requires direct manipulation of the database to add the full-text index. By default Django uses BOOLEAN MODE for full text searches. See the `MySQL documentation`_ for additional details. -.. _MySQL documentation: http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.html> +.. _MySQL documentation: http://dev.mysql.com/doc/refman/5.1/en/fulltext-boolean.html .. fieldlookup:: regex @@ -2236,4 +2236,3 @@ Variance extension. .. _SQLite documentation: http://www.sqlite.org/contrib - From 5262a288df07daa050a0e17669c3f103f47a8640 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Wed, 5 Sep 2012 23:02:33 -0400 Subject: [PATCH 04/23] Fixed #18687: Removed test_performance_scalability Even after repeated adjustment of the constants, this test still fails randomly. It has educated us to ignore messages from Jenkins, to a point where we missed some actual failures. In addition, it accounts for a non-negligible percentage of the run time of the test suite just by itself. Since no one has proposed a convincing patch in months, I'm going to remove the patch. We can't keep a randomly failing test forever. --- tests/regressiontests/utils/crypto.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/regressiontests/utils/crypto.py b/tests/regressiontests/utils/crypto.py index 4c6b722ca9..5cf2934ab0 100644 --- a/tests/regressiontests/utils/crypto.py +++ b/tests/regressiontests/utils/crypto.py @@ -144,21 +144,3 @@ class TestUtilsCryptoPBKDF2(unittest.TestCase): result = pbkdf2(**vector['args']) self.assertEqual(binascii.hexlify(result).decode('ascii'), vector['result']) - - def test_performance_scalability(self): - """ - Theory: If you run with 100 iterations, it should take 100 - times as long as running with 1 iteration. - """ - # These values are chosen as a reasonable tradeoff between time - # to run the test suite and false positives caused by imprecise - # measurement. - n1, n2 = 200000, 800000 - elapsed = lambda f: timeit.Timer(f, - 'from django.utils.crypto import pbkdf2').timeit(number=1) - t1 = elapsed('pbkdf2("password", "salt", iterations=%d)' % n1) - t2 = elapsed('pbkdf2("password", "salt", iterations=%d)' % n2) - measured_scale_exponent = math.log(t2 / t1, n2 / n1) - # This should be less than 1. We allow up to 1.2 so that tests don't - # fail nondeterministically too often. - self.assertLess(measured_scale_exponent, 1.2) From ee1b3e2a3a50e29254a91cf9f4de2996701ccee0 Mon Sep 17 00:00:00 2001 From: Simon Meers Date: Thu, 6 Sep 2012 21:00:16 +1000 Subject: [PATCH 05/23] Fixed minor typo in 1.3 release notes. --- docs/releases/1.3.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases/1.3.txt b/docs/releases/1.3.txt index 772dbdb2e7..c507f1bed6 100644 --- a/docs/releases/1.3.txt +++ b/docs/releases/1.3.txt @@ -587,7 +587,7 @@ gettext domain): ones listed later. * The ``locale`` subdirectory of the directory containing the settings, that - usually coincides with and is know as the *project directory* is being + usually coincides with and is known as the *project directory* is being deprecated in this release as a source of translations. (the precedence of these translations is intermediate between applications and :setting:`LOCALE_PATHS` translations). See the `corresponding deprecated features section`_ From ba141e6906a32683a9a4ae7059351fa951b6470b Mon Sep 17 00:00:00 2001 From: David Fischer Date: Thu, 6 Sep 2012 15:13:31 -0400 Subject: [PATCH 06/23] Added note about Strict Transport Security (HSTS) --- docs/topics/security.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/topics/security.txt b/docs/topics/security.txt index 151853d4ac..4589d01fd4 100644 --- a/docs/topics/security.txt +++ b/docs/topics/security.txt @@ -147,6 +147,14 @@ server, there are some additional steps you may need: any POST data being accepted over HTTP (which will be fine if you are redirecting all HTTP traffic to HTTPS). +* Use HTTP Strict Transport Security (HSTS) + + HSTS is an HTTP header that informs a browser that all future connections + to a particular site should always use HTTPS. Combined with redirecting + requests over HTTP to HTTPS, this will ensure that connections always enjoy + the added security of SSL provided one successful connection has occurred. + HSTS is usually configured on the web server. + .. _additional-security-topics: Host headers and virtual hosting From c65100248ddc4c305487013846b9fd343f7f3078 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Thu, 6 Sep 2012 16:08:14 -0400 Subject: [PATCH 07/23] Added CSRF with HTTPS/HSTS and forwarding note --- docs/topics/security.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/topics/security.txt b/docs/topics/security.txt index 4589d01fd4..797ab0b594 100644 --- a/docs/topics/security.txt +++ b/docs/topics/security.txt @@ -76,9 +76,17 @@ POST to your Web site and have another logged in user unwittingly submit that form. The malicious user would have to know the nonce, which is user specific (using a cookie). +When deployed with :ref:`HTTPS `, +``CsrfViewMiddleware`` will check that the HTTP referer header is set to a +URL on the same origin (including subdomain and port). Because HTTPS +provides additional security, it is imperative to ensure connections use HTTPS +where it is available by forwarding insecure connection requests and using +HSTS for supported browsers. + Be very careful with marking views with the ``csrf_exempt`` decorator unless it is absolutely necessary. + SQL injection protection ======================== @@ -112,6 +120,8 @@ The middleware is strongly recommended for any site that does not need to have its pages wrapped in a frame by third party sites, or only needs to allow that for a small section of the site. +.. _security-recommendation-ssl: + SSL/HTTPS ========= @@ -155,7 +165,7 @@ server, there are some additional steps you may need: the added security of SSL provided one successful connection has occurred. HSTS is usually configured on the web server. -.. _additional-security-topics: +.. _host-headers-virtual-hosting: Host headers and virtual hosting ================================ @@ -175,6 +185,8 @@ recommend you ensure your Web server is configured such that: Additionally, as of 1.3.1, Django requires you to explicitly enable support for the ``X-Forwarded-Host`` header if your configuration requires it. +.. _additional-security-topics: + Additional security topics ========================== From 58786897a1e3ef5d31134cb0870a321425d56fea Mon Sep 17 00:00:00 2001 From: David Fischer Date: Thu, 6 Sep 2012 16:10:08 -0400 Subject: [PATCH 08/23] Formatting fix for host headers section --- docs/topics/security.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/topics/security.txt b/docs/topics/security.txt index 797ab0b594..0a3c6bff02 100644 --- a/docs/topics/security.txt +++ b/docs/topics/security.txt @@ -176,11 +176,11 @@ Site Scripting attacks, they can be used for Cross-Site Request Forgery and cache poisoning attacks in some circumstances. We recommend you ensure your Web server is configured such that: - * It always validates incoming HTTP ``Host`` headers against the expected - host name. - * Disallows requests with no ``Host`` header. - * Is *not* configured with a catch-all virtual host that forwards requests - to a Django application. +* It always validates incoming HTTP ``Host`` headers against the expected + host name. +* Disallows requests with no ``Host`` header. +* Is *not* configured with a catch-all virtual host that forwards requests + to a Django application. Additionally, as of 1.3.1, Django requires you to explicitly enable support for the ``X-Forwarded-Host`` header if your configuration requires it. From 39aa8901e11f07627958ad624146bffe0e1d05a3 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Thu, 6 Sep 2012 23:07:14 +0200 Subject: [PATCH 09/23] Made use of property decorator in formsets.py --- django/forms/formsets.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/django/forms/formsets.py b/django/forms/formsets.py index bdcef92dec..42d25fac6d 100644 --- a/django/forms/formsets.py +++ b/django/forms/formsets.py @@ -71,7 +71,8 @@ class BaseFormSet(object): return True __nonzero__ = __bool__ # Python 2 - def _management_form(self): + @property + def management_form(self): """Returns the ManagementForm instance for this FormSet.""" if self.is_bound: form = ManagementForm(self.data, auto_id=self.auto_id, prefix=self.prefix) @@ -84,7 +85,6 @@ class BaseFormSet(object): MAX_NUM_FORM_COUNT: self.max_num }) return form - management_form = property(_management_form) def total_form_count(self): """Returns the total number of forms in this FormSet.""" @@ -140,17 +140,18 @@ class BaseFormSet(object): self.add_fields(form, i) return form - def _get_initial_forms(self): + @property + def initial_forms(self): """Return a list of all the initial forms in this formset.""" return self.forms[:self.initial_form_count()] - initial_forms = property(_get_initial_forms) - def _get_extra_forms(self): + @property + def extra_forms(self): """Return a list of all the extra forms in this formset.""" return self.forms[self.initial_form_count():] - extra_forms = property(_get_extra_forms) - def _get_empty_form(self, **kwargs): + @property + def empty_form(self, **kwargs): defaults = { 'auto_id': self.auto_id, 'prefix': self.add_prefix('__prefix__'), @@ -160,19 +161,19 @@ class BaseFormSet(object): form = self.form(**defaults) self.add_fields(form, None) return form - empty_form = property(_get_empty_form) # Maybe this should just go away? - def _get_cleaned_data(self): + @property + def cleaned_data(self): """ Returns a list of form.cleaned_data dicts for every form in self.forms. """ if not self.is_valid(): raise AttributeError("'%s' object has no attribute 'cleaned_data'" % self.__class__.__name__) return [form.cleaned_data for form in self.forms] - cleaned_data = property(_get_cleaned_data) - def _get_deleted_forms(self): + @property + def deleted_forms(self): """ Returns a list of forms that have been marked for deletion. Raises an AttributeError if deletion is not allowed. @@ -191,9 +192,9 @@ class BaseFormSet(object): if self._should_delete_form(form): self._deleted_form_indexes.append(i) return [self.forms[i] for i in self._deleted_form_indexes] - deleted_forms = property(_get_deleted_forms) - def _get_ordered_forms(self): + @property + def ordered_forms(self): """ Returns a list of form in the order specified by the incoming data. Raises an AttributeError if ordering is not allowed. @@ -228,7 +229,6 @@ class BaseFormSet(object): # Return a list of form.cleaned_data dicts in the order specified by # the form data. return [self.forms[i[0]] for i in self._ordering] - ordered_forms = property(_get_ordered_forms) @classmethod def get_default_prefix(cls): @@ -244,14 +244,14 @@ class BaseFormSet(object): return self._non_form_errors return self.error_class() - def _get_errors(self): + @property + def errors(self): """ Returns a list of form.errors for every form in self.forms. """ if self._errors is None: self.full_clean() return self._errors - errors = property(_get_errors) def _should_delete_form(self, form): """ @@ -332,14 +332,14 @@ class BaseFormSet(object): """ return self.forms and self.forms[0].is_multipart() - def _get_media(self): + @property + def media(self): # All the forms on a FormSet are the same, so you only need to # interrogate the first form for media. if self.forms: return self.forms[0].media else: return Media() - media = property(_get_media) def as_table(self): "Returns this formset rendered as HTML s -- excluding the
." From c634375e9c47220d272525fcf35ddf4d6989e208 Mon Sep 17 00:00:00 2001 From: Brad Pitcher Date: Fri, 7 Sep 2012 10:43:55 -0400 Subject: [PATCH 10/23] clarify clean_ docs, ticket #18917 --- docs/ref/forms/validation.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt index 95424d0cd0..1af32da875 100644 --- a/docs/ref/forms/validation.txt +++ b/docs/ref/forms/validation.txt @@ -70,9 +70,8 @@ overridden: formfield-specific piece of validation and, possibly, cleaning/normalizing the data. - Just like the general field ``clean()`` method, above, this method - should return the cleaned data, regardless of whether it changed - anything or not. + This method should return the cleaned value obtained from cleaned_data, + regardless of whether it changed anything or not. * The Form subclass's ``clean()`` method. This method can perform any validation that requires access to multiple fields from the form at From 0e296131bb9c94b9bedee34c2a30774107d1d899 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 10:58:17 -0400 Subject: [PATCH 11/23] Cleaned up some small bits of the ORM, including removing an import *. --- django/db/models/sql/compiler.py | 12 +++--------- django/db/models/sql/query.py | 5 +++-- tests/modeltests/raw_query/tests.py | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index cf7cad29bd..caf2330bd1 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -4,7 +4,8 @@ from django.core.exceptions import FieldError from django.db import transaction from django.db.backends.util import truncate_name from django.db.models.query_utils import select_related_descend -from django.db.models.sql.constants import * +from django.db.models.sql.constants import (SINGLE, MULTI, ORDER_DIR, + LOOKUP_SEP, GET_ITERATOR_CHUNK_SIZE) from django.db.models.sql.datastructures import EmptyResultSet from django.db.models.sql.expressions import SQLEvaluator from django.db.models.sql.query import get_order_dir, Query @@ -811,7 +812,7 @@ class SQLCompiler(object): raise EmptyResultSet except EmptyResultSet: if result_type == MULTI: - return empty_iter() + return iter([]) else: return @@ -1088,13 +1089,6 @@ class SQLDateCompiler(SQLCompiler): yield date -def empty_iter(): - """ - Returns an iterator containing no results. - """ - yield next(iter([])) - - def order_modified_iter(cursor, trim, sentinel): """ Yields blocks of rows from a cursor. We use this iterator in the special diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 1915efa7b9..f259a2c7d5 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -17,9 +17,9 @@ from django.db import connections, DEFAULT_DB_ALIAS from django.db.models import signals from django.db.models.expressions import ExpressionNode from django.db.models.fields import FieldDoesNotExist -from django.db.models.query_utils import InvalidQuery from django.db.models.sql import aggregates as base_aggregates_module -from django.db.models.sql.constants import * +from django.db.models.sql.constants import (QUERY_TERMS, LOOKUP_SEP, ORDER_DIR, + SINGLE, ORDER_PATTERN, JoinInfo) from django.db.models.sql.datastructures import EmptyResultSet, Empty, MultiJoin from django.db.models.sql.expressions import SQLEvaluator from django.db.models.sql.where import (WhereNode, Constraint, EverythingNode, @@ -28,6 +28,7 @@ from django.core.exceptions import FieldError __all__ = ['Query', 'RawQuery'] + class RawQuery(object): """ A single raw SQL query diff --git a/tests/modeltests/raw_query/tests.py b/tests/modeltests/raw_query/tests.py index cef9e1be1a..e404c8b065 100644 --- a/tests/modeltests/raw_query/tests.py +++ b/tests/modeltests/raw_query/tests.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from datetime import date -from django.db.models.sql.query import InvalidQuery +from django.db.models.query_utils import InvalidQuery from django.test import TestCase from .models import Author, Book, Coffee, Reviewer, FriendlyAuthor From 09e3d364b922510f4c14a4d843e59c37304fa1a7 Mon Sep 17 00:00:00 2001 From: Dan Loewenherz Date: Fri, 7 Sep 2012 11:34:15 -0400 Subject: [PATCH 12/23] specify any orderable field can be specified in get_latest_by, closes #18875 --- docs/ref/models/options.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt index 9d076f6274..c5ae8398ea 100644 --- a/docs/ref/models/options.txt +++ b/docs/ref/models/options.txt @@ -83,9 +83,10 @@ Django quotes column and table names behind the scenes. .. attribute:: Options.get_latest_by - The name of a :class:`DateField` or :class:`DateTimeField` in the model. - This specifies the default field to use in your model :class:`Manager`'s - :class:`~QuerySet.latest` method. + The name of an orderable field in the model, typically a :class:`DateField`, + :class:`DateTimeField`, or :class:`IntegerField`. This specifies the default + field to use in your model :class:`Manager`'s :class:`~QuerySet.latest` + method. Example:: From 07b3d39d101ff0465a5084266745b3db143552e9 Mon Sep 17 00:00:00 2001 From: Dan Loewenherz Date: Fri, 7 Sep 2012 11:46:53 -0400 Subject: [PATCH 13/23] remove unused import in decoupling URLs tutorial, closes #18915 The `include` function isn't used in polls/urls.py. --- docs/intro/tutorial03.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/intro/tutorial03.txt b/docs/intro/tutorial03.txt index 6d4fb7eef1..2430bc3a2d 100644 --- a/docs/intro/tutorial03.txt +++ b/docs/intro/tutorial03.txt @@ -517,7 +517,7 @@ URLconf by removing the leading "polls/" from each line, and removing the lines registering the admin site. Your ``polls/urls.py`` file should now look like this:: - from django.conf.urls import patterns, include, url + from django.conf.urls import patterns, url urlpatterns = patterns('polls.views', url(r'^$', 'index'), From e1a37d55374a399dee9c302419fbe9badd92abb0 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Fri, 7 Sep 2012 11:57:46 -0400 Subject: [PATCH 14/23] [py3] Documented forwards-compatible aliases that will be available as of version 1.4.2. --- docs/topics/python3.txt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/topics/python3.txt b/docs/topics/python3.txt index 457486caa4..d816db8046 100644 --- a/docs/topics/python3.txt +++ b/docs/topics/python3.txt @@ -25,10 +25,11 @@ free to chose another strategy for your own code, especially if you don't need to stay compatible with Python 2. But authors of pluggable applications are encouraged to use the same porting strategy as Django itself. -Writing compatible code is much easier if you target Python ≥ 2.6. You will -most likely take advantage of the compatibility functions introduced in Django -1.5, like :mod:`django.utils.six`, so your application will also require -Django ≥ 1.5. +Writing compatible code is much easier if you target Python ≥ 2.6. Django 1.5 +introduces compatibility tools such as :mod:`django.utils.six`. For +convenience, forwards-compatible aliases were introduced in Django 1.4.2. If +your application takes advantage of these tools, it will require Django ≥ +1.4.2. Obviously, writing compatible source code adds some overhead, and that can cause frustration. Django's developers have found that attempting to write @@ -102,6 +103,8 @@ Old name New name For backwards compatibility, the old names still work on Python 2. Under Python 3, ``smart_str`` is an alias for ``smart_text``. +For forwards compatibility, the new names work as of Django 1.4.2. + .. note:: :mod:`django.utils.encoding` was deeply refactored in Django 1.5 to @@ -126,6 +129,8 @@ For backwards compatibility, the old names still work on Python 2. Under Python 3, ``EscapeString`` and ``SafeString`` are aliases for ``EscapeText`` and ``SafeText`` respectively. +For forwards compatibility, the new names work as of Django 1.4.2. + :meth:`__str__` and :meth:`__unicode__` methods ----------------------------------------------- @@ -166,6 +171,8 @@ On Python 3, the decorator is a no-op. On Python 2, it defines appropriate This technique is the best match for Django's porting philosophy. +For forwards compatibility, this decorator is available as of Django 1.4.2. + Finally, note that :meth:`__repr__` must return a :class:`str` on all versions of Python. @@ -317,7 +324,8 @@ Writing compatible code with six six_ is the canonical compatibility library for supporting Python 2 and 3 in a single codebase. Read its documentation! -:mod:`six` is bundled with Django: you can import it as :mod:`django.utils.six`. +:mod`six` is bundled with Django as of version 1.4.2. You can import it as +:mod`django.utils.six`. Here are the most common changes required to write compatible code. From 292322f977b1844e15ba25d59d1e985461571c15 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 13:17:09 -0400 Subject: [PATCH 15/23] [py3k] Silence many warnings while running the tests. --- django/contrib/auth/tests/models.py | 11 +- django/test/testcases.py | 2 +- django/utils/six.py | 7 + tests/modeltests/basic/tests.py | 28 ++-- tests/modeltests/empty/tests.py | 7 +- tests/modeltests/fixtures/tests.py | 34 ++--- tests/modeltests/many_to_many/tests.py | 3 +- tests/modeltests/many_to_one/tests.py | 2 +- tests/modeltests/update_only_fields/tests.py | 3 +- .../validation/test_error_messages.py | 3 +- tests/regressiontests/admin_filters/tests.py | 7 +- tests/regressiontests/admin_scripts/tests.py | 6 +- tests/regressiontests/backends/tests.py | 2 +- tests/regressiontests/cache/tests.py | 7 +- tests/regressiontests/file_storage/tests.py | 2 +- .../regressiontests/fixtures_regress/tests.py | 17 +-- tests/regressiontests/forms/tests/fields.py | 6 +- .../i18n/commands/compilation.py | 2 +- .../regressiontests/inline_formsets/tests.py | 4 +- tests/regressiontests/localflavor/tr/tests.py | 32 +++-- tests/regressiontests/m2m_regress/tests.py | 5 +- .../many_to_one_regress/tests.py | 5 +- tests/regressiontests/modeladmin/tests.py | 128 +++++++++--------- .../staticfiles_tests/tests.py | 2 +- tests/regressiontests/templates/custom.py | 51 +++---- tests/regressiontests/templates/loaders.py | 12 +- tests/regressiontests/test_utils/tests.py | 6 +- .../urlpatterns_reverse/tests.py | 8 +- tests/regressiontests/wsgi/tests.py | 7 +- 29 files changed, 213 insertions(+), 196 deletions(-) diff --git a/django/contrib/auth/tests/models.py b/django/contrib/auth/tests/models.py index b40157bfe2..e4efee4339 100644 --- a/django/contrib/auth/tests/models.py +++ b/django/contrib/auth/tests/models.py @@ -1,8 +1,9 @@ from django.conf import settings +from django.contrib.auth.models import (Group, User, SiteProfileNotAvailable, + UserManager) from django.test import TestCase from django.test.utils import override_settings -from django.contrib.auth.models import (Group, User, - SiteProfileNotAvailable, UserManager) +from django.utils import six @override_settings(USE_TZ=False, AUTH_PROFILE_MODULE='') @@ -13,19 +14,19 @@ class ProfileTestCase(TestCase): # calling get_profile without AUTH_PROFILE_MODULE set del settings.AUTH_PROFILE_MODULE - with self.assertRaisesRegexp(SiteProfileNotAvailable, + with six.assertRaisesRegex(self, SiteProfileNotAvailable, "You need to set AUTH_PROFILE_MODULE in your project"): user.get_profile() # Bad syntax in AUTH_PROFILE_MODULE: settings.AUTH_PROFILE_MODULE = 'foobar' - with self.assertRaisesRegexp(SiteProfileNotAvailable, + with six.assertRaisesRegex(self, SiteProfileNotAvailable, "app_label and model_name should be separated by a dot"): user.get_profile() # module that doesn't exist settings.AUTH_PROFILE_MODULE = 'foo.bar' - with self.assertRaisesRegexp(SiteProfileNotAvailable, + with six.assertRaisesRegex(self, SiteProfileNotAvailable, "Unable to load the profile model"): user.get_profile() diff --git a/django/test/testcases.py b/django/test/testcases.py index f12c431d3a..3c681db329 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -358,7 +358,7 @@ class SimpleTestCase(ut2.TestCase): args: Extra args. kwargs: Extra kwargs. """ - return self.assertRaisesRegexp(expected_exception, + return six.assertRaisesRegex(self, expected_exception, re.escape(expected_message), callable_obj, *args, **kwargs) def assertFieldOutput(self, fieldclass, valid, invalid, field_args=None, diff --git a/django/utils/six.py b/django/utils/six.py index e4ce939844..9e3823128f 100644 --- a/django/utils/six.py +++ b/django/utils/six.py @@ -370,13 +370,20 @@ def with_metaclass(meta, base=object): if PY3: _iterlists = "lists" + _assertRaisesRegex = "assertRaisesRegex" else: _iterlists = "iterlists" + _assertRaisesRegex = "assertRaisesRegexp" + def iterlists(d): """Return an iterator over the values of a MultiValueDict.""" return getattr(d, _iterlists)() +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + add_move(MovedModule("_dummy_thread", "dummy_thread")) add_move(MovedModule("_thread", "thread")) diff --git a/tests/modeltests/basic/tests.py b/tests/modeltests/basic/tests.py index d96c60bbe8..6ec9ca03af 100644 --- a/tests/modeltests/basic/tests.py +++ b/tests/modeltests/basic/tests.py @@ -5,7 +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 import six from django.utils.translation import ugettext_lazy from .models import Article @@ -82,7 +82,7 @@ class ModelTest(TestCase): # Django raises an Article.DoesNotExist exception for get() if the # parameters don't match any object. - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ObjectDoesNotExist, "Article matching query does not exist. Lookup parameters were " "{'id__exact': 2000}", @@ -91,14 +91,14 @@ class ModelTest(TestCase): ) # To avoid dict-ordering related errors check only one lookup # in single assert. - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ObjectDoesNotExist, ".*'pub_date__year': 2005.*", Article.objects.get, pub_date__year=2005, pub_date__month=8, ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ObjectDoesNotExist, ".*'pub_date__month': 8.*", Article.objects.get, @@ -106,7 +106,7 @@ class ModelTest(TestCase): pub_date__month=8, ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ObjectDoesNotExist, "Article matching query does not exist. Lookup parameters were " "{'pub_date__week_day': 6}", @@ -168,7 +168,7 @@ class ModelTest(TestCase): self.assertEqual(a4.headline, 'Fourth article') # Don't use invalid keyword arguments. - self.assertRaisesRegexp( + six.assertRaisesRegex(self, TypeError, "'foo' is an invalid keyword argument for this function", Article, @@ -259,13 +259,13 @@ class ModelTest(TestCase): "datetime.datetime(2005, 7, 28, 0, 0)"]) # dates() requires valid arguments. - self.assertRaisesRegexp( + six.assertRaisesRegex(self, TypeError, "dates\(\) takes at least 3 arguments \(1 given\)", Article.objects.dates, ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, FieldDoesNotExist, "Article has no field named 'invalid_field'", Article.objects.dates, @@ -273,7 +273,7 @@ class ModelTest(TestCase): "year", ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, AssertionError, "'kind' must be one of 'year', 'month' or 'day'.", Article.objects.dates, @@ -281,7 +281,7 @@ class ModelTest(TestCase): "bad_kind", ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, AssertionError, "'order' must be either 'ASC' or 'DESC'.", Article.objects.dates, @@ -323,7 +323,7 @@ class ModelTest(TestCase): ""]) # Slicing works with longs (Python 2 only -- Python 3 doesn't have longs). - if not PY3: + if not six.PY3: self.assertEqual(Article.objects.all()[long(0)], a) self.assertQuerysetEqual(Article.objects.all()[long(1):long(3)], ["", ""]) @@ -369,14 +369,14 @@ class ModelTest(TestCase): ""]) # Also, once you have sliced you can't filter, re-order or combine - self.assertRaisesRegexp( + six.assertRaisesRegex(self, AssertionError, "Cannot filter a query once a slice has been taken.", Article.objects.all()[0:5].filter, id=a.id, ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, AssertionError, "Cannot reorder a query once a slice has been taken.", Article.objects.all()[0:5].order_by, @@ -411,7 +411,7 @@ class ModelTest(TestCase): # An Article instance doesn't have access to the "objects" attribute. # That's only available on the class. - self.assertRaisesRegexp( + six.assertRaisesRegex(self, AttributeError, "Manager isn't accessible via Article instances", getattr, diff --git a/tests/modeltests/empty/tests.py b/tests/modeltests/empty/tests.py index db464c632d..4c0c4409d8 100644 --- a/tests/modeltests/empty/tests.py +++ b/tests/modeltests/empty/tests.py @@ -1,10 +1,10 @@ from __future__ import absolute_import -from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.db.models.loading import get_app from django.test import TestCase from django.test.utils import override_settings +from django.utils import six from .models import Empty @@ -14,12 +14,13 @@ class EmptyModelTests(TestCase): m = Empty() self.assertEqual(m.id, None) m.save() - m2 = Empty.objects.create() + Empty.objects.create() self.assertEqual(len(Empty.objects.all()), 2) self.assertTrue(m.id is not None) existing = Empty(m.id) existing.save() + class NoModelTests(TestCase): """ Test for #7198 to ensure that the proper error message is raised @@ -32,6 +33,6 @@ class NoModelTests(TestCase): """ @override_settings(INSTALLED_APPS=("modeltests.empty.no_models",)) def test_no_models(self): - with self.assertRaisesRegexp(ImproperlyConfigured, + with six.assertRaisesRegex(self, ImproperlyConfigured, 'App with label no_models is missing a models.py module.'): get_app('no_models') diff --git a/tests/modeltests/fixtures/tests.py b/tests/modeltests/fixtures/tests.py index b332348425..f9b0ac8a46 100644 --- a/tests/modeltests/fixtures/tests.py +++ b/tests/modeltests/fixtures/tests.py @@ -4,7 +4,7 @@ from django.contrib.sites.models import Site from django.core import management from django.db import connection, IntegrityError from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature -from django.utils.six import StringIO +from django.utils import six from .models import Article, Book, Spy, Tag, Visa @@ -21,16 +21,17 @@ class TestCaseFixtureLoadingTests(TestCase): '', ]) + class FixtureLoadingTests(TestCase): def _dumpdata_assert(self, args, output, format='json', natural_keys=False, use_base_manager=False, exclude_list=[]): - new_io = StringIO() - management.call_command('dumpdata', *args, **{'format':format, - 'stdout':new_io, - 'stderr':new_io, - 'use_natural_keys':natural_keys, - 'use_base_manager':use_base_manager, + new_io = six.StringIO() + management.call_command('dumpdata', *args, **{'format': format, + 'stdout': new_io, + 'stderr': new_io, + 'use_natural_keys': natural_keys, + 'use_base_manager': use_base_manager, 'exclude': exclude_list}) command_output = new_io.getvalue().strip() self.assertEqual(command_output, output) @@ -42,8 +43,6 @@ class FixtureLoadingTests(TestCase): ]) def test_loading_and_dumping(self): - new_io = StringIO() - Site.objects.all().delete() # Load fixture 1. Single JSON file, with two objects. management.call_command('loaddata', 'fixture1.json', verbosity=0, commit=False) @@ -184,12 +183,12 @@ class FixtureLoadingTests(TestCase): exclude_list=['fixtures.Article', 'fixtures.Book', 'sites']) # Excluding a bogus app should throw an error - with self.assertRaisesRegexp(management.CommandError, + with six.assertRaisesRegex(self, management.CommandError, "Unknown app in excludes: foo_app"): self._dumpdata_assert(['fixtures', 'sites'], '', exclude_list=['foo_app']) # Excluding a bogus model should throw an error - with self.assertRaisesRegexp(management.CommandError, + with six.assertRaisesRegex(self, management.CommandError, "Unknown model in excludes: fixtures.FooModel"): self._dumpdata_assert(['fixtures', 'sites'], '', exclude_list=['fixtures.FooModel']) @@ -199,7 +198,7 @@ class FixtureLoadingTests(TestCase): self.assertQuerysetEqual(Spy.objects.all(), ['']) # Use the default manager - self._dumpdata_assert(['fixtures.Spy'],'[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % spy1.pk) + self._dumpdata_assert(['fixtures.Spy'], '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % spy1.pk) # Dump using Django's base manager. Should return all objects, # even those normally filtered by the manager self._dumpdata_assert(['fixtures.Spy'], '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": true}}, {"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % (spy2.pk, spy1.pk), use_base_manager=True) @@ -227,7 +226,7 @@ class FixtureLoadingTests(TestCase): def test_ambiguous_compressed_fixture(self): # The name "fixture5" is ambigous, so loading it will raise an error - with self.assertRaisesRegexp(management.CommandError, + with six.assertRaisesRegex(self, management.CommandError, "Multiple fixtures named 'fixture5'"): management.call_command('loaddata', 'fixture5', verbosity=0, commit=False) @@ -251,7 +250,7 @@ class FixtureLoadingTests(TestCase): # is closed at the end of each test. if connection.vendor == 'mysql': connection.cursor().execute("SET sql_mode = 'TRADITIONAL'") - with self.assertRaisesRegexp(IntegrityError, + with six.assertRaisesRegex(self, IntegrityError, "Could not load fixtures.Article\(pk=1\): .*$"): management.call_command('loaddata', 'invalid.json', verbosity=0, commit=False) @@ -290,10 +289,11 @@ class FixtureLoadingTests(TestCase): self._dumpdata_assert(['fixtures'], """ News StoriesLatest news storiesPoker has no place on ESPN2006-06-16T12:00:00Time to reform copyright2006-06-16T13:00:00copyrightfixturesarticle3lawfixturesarticle3Django ReinhardtStephane GrappelliPrinceAchieving self-awareness of Python programs""", format='xml', natural_keys=True) + class FixtureTransactionTests(TransactionTestCase): def _dumpdata_assert(self, args, output, format='json'): - new_io = StringIO() - management.call_command('dumpdata', *args, **{'format':format, 'stdout':new_io}) + new_io = six.StringIO() + management.call_command('dumpdata', *args, **{'format': format, 'stdout': new_io}) command_output = new_io.getvalue().strip() self.assertEqual(command_output, output) @@ -308,7 +308,7 @@ class FixtureTransactionTests(TransactionTestCase): # Try to load fixture 2 using format discovery; this will fail # because there are two fixture2's in the fixtures directory - with self.assertRaisesRegexp(management.CommandError, + with six.assertRaisesRegex(self, management.CommandError, "Multiple fixtures named 'fixture2'"): management.call_command('loaddata', 'fixture2', verbosity=0) diff --git a/tests/modeltests/many_to_many/tests.py b/tests/modeltests/many_to_many/tests.py index 44bdde3aeb..7d30379b94 100644 --- a/tests/modeltests/many_to_many/tests.py +++ b/tests/modeltests/many_to_many/tests.py @@ -1,6 +1,7 @@ from __future__ import absolute_import from django.test import TestCase +from django.utils import six from .models import Article, Publication @@ -52,7 +53,7 @@ class ManyToManyTests(TestCase): ]) # Adding an object of the wrong type raises TypeError - with self.assertRaisesRegexp(TypeError, "'Publication' instance expected, got "]) # Adding an object of the wrong type raises TypeError. - with self.assertRaisesRegexp(TypeError, "'Article' instance expected, got has more than 1 ForeignKey to ", inlineformset_factory, Parent, Child ) @@ -143,7 +143,7 @@ class InlineFormsetFactoryTest(TestCase): If the field specified in fk_name is not a ForeignKey, we should get an exception. """ - self.assertRaisesRegexp(Exception, + six.assertRaisesRegex(self, Exception, " has no field named 'test'", inlineformset_factory, Parent, Child, fk_name='test' ) diff --git a/tests/regressiontests/localflavor/tr/tests.py b/tests/regressiontests/localflavor/tr/tests.py index 3ec1f5b7c4..476efc12ba 100644 --- a/tests/regressiontests/localflavor/tr/tests.py +++ b/tests/regressiontests/localflavor/tr/tests.py @@ -2,29 +2,31 @@ from django.contrib.localflavor.tr import forms as trforms from django.core.exceptions import ValidationError +from django.utils import six from django.utils.unittest import TestCase + class TRLocalFlavorTests(TestCase): def test_TRPostalCodeField(self): f = trforms.TRPostalCodeField() self.assertEqual(f.clean("06531"), "06531") self.assertEqual(f.clean("12345"), "12345") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, "Enter a postal code in the format XXXXX.", f.clean, "a1234") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, "Enter a postal code in the format XXXXX.", f.clean, "1234") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, "Enter a postal code in the format XXXXX.", f.clean, "82123") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, "Enter a postal code in the format XXXXX.", f.clean, "00123") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, "Enter a postal code in the format XXXXX.", f.clean, "123456") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, "Enter a postal code in the format XXXXX.", f.clean, "12 34") self.assertRaises(ValidationError, f.clean, None) @@ -40,34 +42,34 @@ class TRLocalFlavorTests(TestCase): self.assertEqual(f.clean("+90 312 455 4567"), "3124554567") self.assertEqual(f.clean("+90 312 455 45 67"), "3124554567") self.assertEqual(f.clean("+90 (312) 4554567"), "3124554567") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Phone numbers must be in 0XXX XXX XXXX format.', f.clean, "1234 233 1234") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Phone numbers must be in 0XXX XXX XXXX format.', f.clean, "0312 233 12345") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Phone numbers must be in 0XXX XXX XXXX format.', f.clean, "0312 233 123") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Phone numbers must be in 0XXX XXX XXXX format.', f.clean, "0312 233 xxxx") def test_TRIdentificationNumberField(self): f = trforms.TRIdentificationNumberField() self.assertEqual(f.clean("10000000146"), "10000000146") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Enter a valid Turkish Identification number.', f.clean, "10000000136") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Enter a valid Turkish Identification number.', f.clean, "10000000147") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Turkish Identification number must be 11 digits.', f.clean, "123456789") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Enter a valid Turkish Identification number.', f.clean, "1000000014x") - self.assertRaisesRegexp(ValidationError, + six.assertRaisesRegex(self, ValidationError, 'Enter a valid Turkish Identification number.', f.clean, "x0000000146") diff --git a/tests/regressiontests/m2m_regress/tests.py b/tests/regressiontests/m2m_regress/tests.py index e3dab59b9f..92628c1825 100644 --- a/tests/regressiontests/m2m_regress/tests.py +++ b/tests/regressiontests/m2m_regress/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 (SelfRefer, Tag, TagCollection, Entry, SelfReferChild, SelfReferChildSibling, Worksheet) @@ -35,7 +36,7 @@ class M2MRegressionTests(TestCase): # The secret internal related names for self-referential many-to-many # fields shouldn't appear in the list when an error is made. - self.assertRaisesRegexp(FieldError, + six.assertRaisesRegex(self, FieldError, "Choices are: id, name, references, related, selfreferchild, selfreferchildsibling$", lambda: SelfRefer.objects.filter(porcupine='fred') ) @@ -70,7 +71,7 @@ class M2MRegressionTests(TestCase): t2 = Tag.objects.create(name='t2') c1 = TagCollection.objects.create(name='c1') - c1.tags = [t1,t2] + c1.tags = [t1, t2] c1 = TagCollection.objects.get(name='c1') self.assertQuerysetEqual(c1.tags.all(), ["", ""]) diff --git a/tests/regressiontests/many_to_one_regress/tests.py b/tests/regressiontests/many_to_one_regress/tests.py index 481a037139..d980d7437c 100644 --- a/tests/regressiontests/many_to_one_regress/tests.py +++ b/tests/regressiontests/many_to_one_regress/tests.py @@ -2,8 +2,9 @@ from __future__ import absolute_import from django.db import models from django.test import TestCase +from django.utils import six -from .models import First, Second, Third, Parent, Child, Category, Record, Relation +from .models import First, Third, Parent, Child, Category, Record, Relation class ManyToOneRegressionTests(TestCase): @@ -59,7 +60,7 @@ class ManyToOneRegressionTests(TestCase): self.assertRaises(ValueError, Child.objects.create, name='xyzzy', parent=None) # Trying to assign to unbound attribute raises AttributeError - self.assertRaisesRegexp(AttributeError, "must be accessed via instance", + six.assertRaisesRegex(self, AttributeError, "must be accessed via instance", Child.parent.__set__, None, p) # Creation using keyword argument should cache the related object. diff --git a/tests/regressiontests/modeladmin/tests.py b/tests/regressiontests/modeladmin/tests.py index d55d50d0a5..b0a181218b 100644 --- a/tests/regressiontests/modeladmin/tests.py +++ b/tests/regressiontests/modeladmin/tests.py @@ -16,7 +16,7 @@ from django.forms.models import BaseModelFormSet from django.forms.widgets import Select from django.test import TestCase from django.test.utils import str_prefix -from django.utils import unittest +from django.utils import unittest, six from .models import Band, Concert, ValidationTestModel, ValidationTestInlineModel @@ -506,7 +506,7 @@ class ValidationTests(unittest.TestCase): site = AdminSite() - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.", site.register, @@ -524,7 +524,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.", validate, @@ -535,7 +535,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = ('non_existent_field',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -546,7 +546,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): raw_id_fields = ('name',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.raw_id_fields\[0\]', 'name' must be either a ForeignKey or ManyToManyField.", validate, @@ -564,7 +564,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.fieldsets' must be a list or tuple.", validate, @@ -575,7 +575,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = ({},) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.fieldsets\[0\]' must be a list or tuple.", validate, @@ -586,7 +586,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = ((),) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.fieldsets\[0\]' does not have exactly two elements.", validate, @@ -597,7 +597,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = (("General", ()),) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.fieldsets\[0\]\[1\]' must be a dictionary.", validate, @@ -608,7 +608,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = (("General", {}),) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'fields' key is required in ValidationTestModelAdmin.fieldsets\[0\]\[1\] field options dict.", validate, @@ -619,7 +619,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = (("General", {"fields": ("non_existent_field",)}),) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.fieldsets\[0\]\[1\]\['fields'\]' refers to field 'non_existent_field' that is missing from the form.", validate, @@ -636,7 +636,7 @@ class ValidationTests(unittest.TestCase): fieldsets = (("General", {"fields": ("name",)}),) fields = ["name",] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "Both fieldsets and fields are specified in ValidationTestModelAdmin.", validate, @@ -647,7 +647,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fieldsets = [(None, {'fields': ['name', 'name']})] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "There are duplicate field\(s\) in ValidationTestModelAdmin.fieldsets", validate, @@ -658,7 +658,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): fields = ["name", "name"] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "There are duplicate field\(s\) in ValidationTestModelAdmin.fields", validate, @@ -674,7 +674,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): form = FakeForm - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "ValidationTestModelAdmin.form does not inherit from BaseModelForm.", validate, @@ -692,7 +692,7 @@ class ValidationTests(unittest.TestCase): }), ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'BandAdmin.fieldsets\[0\]\[1\]\['fields'\]' refers to field 'non_existent_field' that is missing from the form.", validate, @@ -722,7 +722,7 @@ class ValidationTests(unittest.TestCase): }), ) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'BandAdmin.fieldsets\[0]\[1\]\['fields'\]' refers to field 'non_existent_field' that is missing from the form.", validate, @@ -752,7 +752,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): filter_vertical = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.filter_vertical' must be a list or tuple.", validate, @@ -763,7 +763,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): filter_vertical = ("non_existent_field",) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.filter_vertical' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -774,7 +774,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): filter_vertical = ("name",) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.filter_vertical\[0\]' must be a ManyToManyField.", validate, @@ -792,7 +792,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): filter_horizontal = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.filter_horizontal' must be a list or tuple.", validate, @@ -803,7 +803,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): filter_horizontal = ("non_existent_field",) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.filter_horizontal' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -814,7 +814,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): filter_horizontal = ("name",) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.filter_horizontal\[0\]' must be a ManyToManyField.", validate, @@ -832,7 +832,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): radio_fields = () - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.radio_fields' must be a dictionary.", validate, @@ -843,7 +843,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): radio_fields = {"non_existent_field": None} - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.radio_fields' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -854,7 +854,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): radio_fields = {"name": None} - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.radio_fields\['name'\]' is neither an instance of ForeignKey nor does have choices set.", validate, @@ -865,7 +865,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): radio_fields = {"state": None} - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.radio_fields\['state'\]' is neither admin.HORIZONTAL nor admin.VERTICAL.", validate, @@ -883,7 +883,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): prepopulated_fields = () - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.prepopulated_fields' must be a dictionary.", validate, @@ -894,7 +894,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): prepopulated_fields = {"non_existent_field": None} - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.prepopulated_fields' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -905,7 +905,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): prepopulated_fields = {"slug": ("non_existent_field",)} - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.prepopulated_fields\['slug'\]\[0\]' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -916,7 +916,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): prepopulated_fields = {"users": ("name",)} - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.prepopulated_fields\['users'\]' is either a DateTimeField, ForeignKey or ManyToManyField. This isn't allowed.", validate, @@ -934,7 +934,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_display = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_display' must be a list or tuple.", validate, @@ -945,7 +945,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_display = ('non_existent_field',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, str_prefix("ValidationTestModelAdmin.list_display\[0\], %(_)s'non_existent_field' is not a callable or an attribute of 'ValidationTestModelAdmin' or found in the model 'ValidationTestModel'."), validate, @@ -956,7 +956,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_display = ('users',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_display\[0\]', 'users' is a ManyToManyField which is not supported.", validate, @@ -979,7 +979,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_display_links = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_display_links' must be a list or tuple.", validate, @@ -990,7 +990,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_display_links = ('non_existent_field',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_display_links\[0\]' refers to 'non_existent_field' which is not defined in 'list_display'.", validate, @@ -1001,7 +1001,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_display_links = ('name',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_display_links\[0\]' refers to 'name' which is not defined in 'list_display'.", validate, @@ -1025,7 +1025,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_filter = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_filter' must be a list or tuple.", validate, @@ -1036,7 +1036,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_filter = ('non_existent_field',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_filter\[0\]' refers to 'non_existent_field' which does not refer to a Field.", validate, @@ -1050,7 +1050,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_filter = (RandomClass,) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_filter\[0\]' is 'RandomClass' which is not a descendant of ListFilter.", validate, @@ -1061,7 +1061,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_filter = (('is_active', RandomClass),) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_filter\[0\]\[1\]' is 'RandomClass' which is not of type FieldListFilter.", validate, @@ -1080,7 +1080,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_filter = (('is_active', AwesomeFilter),) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_filter\[0\]\[1\]' is 'AwesomeFilter' which is not of type FieldListFilter.", validate, @@ -1091,7 +1091,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_filter = (BooleanFieldListFilter,) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_filter\[0\]' is 'BooleanFieldListFilter' which is of type FieldListFilter but is not associated with a field name.", validate, @@ -1111,7 +1111,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_per_page = 'hello' - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_per_page' should be a integer.", validate, @@ -1129,7 +1129,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_max_show_all = 'hello' - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_max_show_all' should be an integer.", validate, @@ -1147,7 +1147,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): search_fields = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.search_fields' must be a list or tuple.", validate, @@ -1160,7 +1160,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): date_hierarchy = 'non_existent_field' - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.date_hierarchy' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -1171,7 +1171,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): date_hierarchy = 'name' - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.date_hierarchy is neither an instance of DateField nor DateTimeField.", validate, @@ -1189,7 +1189,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): ordering = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.ordering' must be a list or tuple.", validate, @@ -1200,7 +1200,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): ordering = ('non_existent_field',) - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.ordering\[0\]' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestModel'.", validate, @@ -1211,7 +1211,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): ordering = ('?', 'name') - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.ordering' has the random ordering marker '\?', but contains other fields as well. Please either remove '\?' or the other fields.", validate, @@ -1239,7 +1239,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): list_select_related = 1 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.list_select_related' should be a boolean.", validate, @@ -1257,7 +1257,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): save_as = 1 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.save_as' should be a boolean.", validate, @@ -1275,7 +1275,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): save_on_top = 1 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.save_on_top' should be a boolean.", validate, @@ -1293,7 +1293,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = 10 - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.inlines' must be a list or tuple.", validate, @@ -1307,7 +1307,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.inlines\[0\]' does not inherit from BaseModelAdmin.", validate, @@ -1321,7 +1321,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'model' is a required attribute of 'ValidationTestModelAdmin.inlines\[0\]'.", validate, @@ -1338,7 +1338,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestModelAdmin.inlines\[0\].model' does not inherit from models.Model.", validate, @@ -1363,7 +1363,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestInline.fields' must be a list or tuple.", validate, @@ -1378,7 +1378,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestInline.fields' refers to field 'non_existent_field' that is missing from the form.", validate, @@ -1395,7 +1395,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestInline.fk_name' refers to field 'non_existent_field' that is missing from model 'modeladmin.ValidationTestInlineModel'.", validate, @@ -1421,7 +1421,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestInline.extra' should be a integer.", validate, @@ -1447,7 +1447,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestInline.max_num' should be an integer or None \(default\).", validate, @@ -1476,7 +1476,7 @@ class ValidationTests(unittest.TestCase): class ValidationTestModelAdmin(ModelAdmin): inlines = [ValidationTestInline] - self.assertRaisesRegexp( + six.assertRaisesRegex(self, ImproperlyConfigured, "'ValidationTestInline.formset' does not inherit from BaseModelFormSet.", validate, diff --git a/tests/regressiontests/staticfiles_tests/tests.py b/tests/regressiontests/staticfiles_tests/tests.py index 078788a6a9..7ecbccc448 100644 --- a/tests/regressiontests/staticfiles_tests/tests.py +++ b/tests/regressiontests/staticfiles_tests/tests.py @@ -617,7 +617,7 @@ class TestServeDisabled(TestServeStatic): settings.DEBUG = False def test_disabled_serving(self): - self.assertRaisesRegexp(ImproperlyConfigured, 'The staticfiles view ' + six.assertRaisesRegex(self, ImproperlyConfigured, 'The staticfiles view ' 'can only be used in debug mode ', self._response, 'test.txt') diff --git a/tests/regressiontests/templates/custom.py b/tests/regressiontests/templates/custom.py index 4e295d990e..4aea08237d 100644 --- a/tests/regressiontests/templates/custom.py +++ b/tests/regressiontests/templates/custom.py @@ -1,6 +1,7 @@ from __future__ import absolute_import, unicode_literals from django import template +from django.utils import six from django.utils.unittest import TestCase from .templatetags import custom @@ -51,7 +52,7 @@ class CustomTagTests(TestCase): t = template.Template('{% load custom %}{% simple_one_default one=99 two="hello" %}') self.assertEqual(t.render(c), 'simple_one_default - Expected result: 99, hello') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'simple_one_default' received unexpected keyword argument 'three'", template.Template, '{% load custom %}{% simple_one_default 99 two="hello" three="foo" %}') @@ -70,22 +71,22 @@ class CustomTagTests(TestCase): t = template.Template('{% load custom %}{% simple_only_unlimited_args 37 42 56 89 %}') self.assertEqual(t.render(c), 'simple_only_unlimited_args - Expected result: 37, 42, 56, 89') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'simple_two_params' received too many positional arguments", template.Template, '{% load custom %}{% simple_two_params 37 42 56 %}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'simple_one_default' received too many positional arguments", template.Template, '{% load custom %}{% simple_one_default 37 42 56 %}') t = template.Template('{% load custom %}{% simple_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" four=1|add:3 %}') self.assertEqual(t.render(c), 'simple_unlimited_args_kwargs - Expected result: 37, 42, 56 / eggs=scrambled, four=4') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'simple_unlimited_args_kwargs' received some positional argument\(s\) after some keyword argument\(s\)", template.Template, '{% load custom %}{% simple_unlimited_args_kwargs 37 40|add:2 eggs="scrambled" 56 four=1|add:3 %}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'simple_unlimited_args_kwargs' received multiple values for keyword argument 'eggs'", template.Template, '{% load custom %}{% simple_unlimited_args_kwargs 37 eggs="scrambled" eggs="scrambled" %}') @@ -101,7 +102,7 @@ class CustomTagTests(TestCase): def test_simple_tag_missing_context(self): # The 'context' parameter must be present when takes_context is True - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'simple_tag_without_context_parameter' is decorated with takes_context=True so it must have a first argument of 'context'", template.Template, '{% load custom %}{% simple_tag_without_context_parameter 123 %}') @@ -135,7 +136,7 @@ class CustomTagTests(TestCase): t = template.Template('{% load custom %}{% inclusion_one_default one=99 two="hello" %}') self.assertEqual(t.render(c), 'inclusion_one_default - Expected result: 99, hello\n') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_one_default' received unexpected keyword argument 'three'", template.Template, '{% load custom %}{% inclusion_one_default 99 two="hello" three="foo" %}') @@ -154,36 +155,36 @@ class CustomTagTests(TestCase): t = template.Template('{% load custom %}{% inclusion_only_unlimited_args 37 42 56 89 %}') self.assertEqual(t.render(c), 'inclusion_only_unlimited_args - Expected result: 37, 42, 56, 89\n') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_two_params' received too many positional arguments", template.Template, '{% load custom %}{% inclusion_two_params 37 42 56 %}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_one_default' received too many positional arguments", template.Template, '{% load custom %}{% inclusion_one_default 37 42 56 %}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_one_default' did not receive value\(s\) for the argument\(s\): 'one'", template.Template, '{% load custom %}{% inclusion_one_default %}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_unlimited_args' did not receive value\(s\) for the argument\(s\): 'one'", template.Template, '{% load custom %}{% inclusion_unlimited_args %}') t = template.Template('{% load custom %}{% inclusion_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" four=1|add:3 %}') self.assertEqual(t.render(c), 'inclusion_unlimited_args_kwargs - Expected result: 37, 42, 56 / eggs=scrambled, four=4\n') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_unlimited_args_kwargs' received some positional argument\(s\) after some keyword argument\(s\)", template.Template, '{% load custom %}{% inclusion_unlimited_args_kwargs 37 40|add:2 eggs="scrambled" 56 four=1|add:3 %}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_unlimited_args_kwargs' received multiple values for keyword argument 'eggs'", template.Template, '{% load custom %}{% inclusion_unlimited_args_kwargs 37 eggs="scrambled" eggs="scrambled" %}') def test_include_tag_missing_context(self): # The 'context' parameter must be present when takes_context is True - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'inclusion_tag_without_context_parameter' is decorated with takes_context=True so it must have a first argument of 'context'", template.Template, '{% load custom %}{% inclusion_tag_without_context_parameter 123 %}') @@ -296,7 +297,7 @@ class CustomTagTests(TestCase): t = template.Template('{% load custom %}{% assignment_one_default one=99 two="hello" as var %}The result is: {{ var }}') self.assertEqual(t.render(c), 'The result is: assignment_one_default - Expected result: 99, hello') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_one_default' received unexpected keyword argument 'three'", template.Template, '{% load custom %}{% assignment_one_default 99 two="hello" three="foo" as var %}') @@ -315,42 +316,42 @@ class CustomTagTests(TestCase): t = template.Template('{% load custom %}{% assignment_only_unlimited_args 37 42 56 89 as var %}The result is: {{ var }}') self.assertEqual(t.render(c), 'The result is: assignment_only_unlimited_args - Expected result: 37, 42, 56, 89') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'", template.Template, '{% load custom %}{% assignment_one_param 37 %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'", template.Template, '{% load custom %}{% assignment_one_param 37 as %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_one_param' tag takes at least 2 arguments and the second last argument must be 'as'", template.Template, '{% load custom %}{% assignment_one_param 37 ass var %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_two_params' received too many positional arguments", template.Template, '{% load custom %}{% assignment_two_params 37 42 56 as var %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_one_default' received too many positional arguments", template.Template, '{% load custom %}{% assignment_one_default 37 42 56 as var %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_one_default' did not receive value\(s\) for the argument\(s\): 'one'", template.Template, '{% load custom %}{% assignment_one_default as var %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_unlimited_args' did not receive value\(s\) for the argument\(s\): 'one'", template.Template, '{% load custom %}{% assignment_unlimited_args as var %}The result is: {{ var }}') t = template.Template('{% load custom %}{% assignment_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" four=1|add:3 as var %}The result is: {{ var }}') self.assertEqual(t.render(c), 'The result is: assignment_unlimited_args_kwargs - Expected result: 37, 42, 56 / eggs=scrambled, four=4') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_unlimited_args_kwargs' received some positional argument\(s\) after some keyword argument\(s\)", template.Template, '{% load custom %}{% assignment_unlimited_args_kwargs 37 40|add:2 eggs="scrambled" 56 four=1|add:3 as var %}The result is: {{ var }}') - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_unlimited_args_kwargs' received multiple values for keyword argument 'eggs'", template.Template, '{% load custom %}{% assignment_unlimited_args_kwargs 37 eggs="scrambled" eggs="scrambled" as var %}The result is: {{ var }}') @@ -371,6 +372,6 @@ class CustomTagTests(TestCase): def test_assignment_tag_missing_context(self): # The 'context' parameter must be present when takes_context is True - self.assertRaisesRegexp(template.TemplateSyntaxError, + six.assertRaisesRegex(self, template.TemplateSyntaxError, "'assignment_tag_without_context_parameter' is decorated with takes_context=True so it must have a first argument of 'context'", template.Template, '{% load custom %}{% assignment_tag_without_context_parameter 123 as var %}') diff --git a/tests/regressiontests/templates/loaders.py b/tests/regressiontests/templates/loaders.py index 6b635c8f23..7fbb0841f9 100644 --- a/tests/regressiontests/templates/loaders.py +++ b/tests/regressiontests/templates/loaders.py @@ -17,7 +17,7 @@ import os.path from django.template import TemplateDoesNotExist, Context from django.template.loaders.eggs import Loader as EggLoader from django.template import loader -from django.utils import unittest +from django.utils import unittest, six from django.utils.six import StringIO @@ -30,7 +30,7 @@ class MockProvider(pkg_resources.NullProvider): def _has(self, path): return path in self.module._resources - def _isdir(self,path): + def _isdir(self, path): return False def get_resource_stream(self, manager, resource_name): @@ -61,8 +61,8 @@ class EggLoaderTest(unittest.TestCase): self.empty_egg = create_egg("egg_empty", {}) self.egg_1 = create_egg("egg_1", { - os.path.normcase('templates/y.html') : StringIO("y"), - os.path.normcase('templates/x.txt') : StringIO("x"), + os.path.normcase('templates/y.html'): StringIO("y"), + os.path.normcase('templates/x.txt'): StringIO("x"), }) self._old_installed_apps = settings.INSTALLED_APPS settings.INSTALLED_APPS = [] @@ -144,12 +144,12 @@ class RenderToStringTest(unittest.TestCase): self.assertEqual(context['obj'], 'before') def test_empty_list(self): - self.assertRaisesRegexp(TemplateDoesNotExist, + six.assertRaisesRegex(self, TemplateDoesNotExist, 'No template names provided$', loader.render_to_string, []) def test_select_templates_from_empty_list(self): - self.assertRaisesRegexp(TemplateDoesNotExist, + six.assertRaisesRegex(self, TemplateDoesNotExist, 'No template names provided$', loader.select_template, []) diff --git a/tests/regressiontests/test_utils/tests.py b/tests/regressiontests/test_utils/tests.py index 3749014372..468af77f44 100644 --- a/tests/regressiontests/test_utils/tests.py +++ b/tests/regressiontests/test_utils/tests.py @@ -137,15 +137,15 @@ class AssertTemplateUsedContextManagerTests(TestCase): pass def test_error_message(self): - with self.assertRaisesRegexp(AssertionError, r'^template_used/base\.html'): + with six.assertRaisesRegex(self, AssertionError, r'^template_used/base\.html'): with self.assertTemplateUsed('template_used/base.html'): pass - with self.assertRaisesRegexp(AssertionError, r'^template_used/base\.html'): + with six.assertRaisesRegex(self, AssertionError, r'^template_used/base\.html'): with self.assertTemplateUsed(template_name='template_used/base.html'): pass - with self.assertRaisesRegexp(AssertionError, r'^template_used/base\.html.*template_used/alternative\.html$'): + with six.assertRaisesRegex(self, AssertionError, r'^template_used/base\.html.*template_used/alternative\.html$'): with self.assertTemplateUsed('template_used/base.html'): render_to_string('template_used/alternative.html') diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py index 168892719a..0ea5ffe380 100644 --- a/tests/regressiontests/urlpatterns_reverse/tests.py +++ b/tests/regressiontests/urlpatterns_reverse/tests.py @@ -4,6 +4,7 @@ Unit tests for reverse URL lookups. from __future__ import absolute_import, unicode_literals from django.conf import settings +from django.contrib.auth.models import User from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist from django.core.urlresolvers import (reverse, resolve, get_callable, get_resolver, NoReverseMatch, Resolver404, ResolverMatch, RegexURLResolver, @@ -11,10 +12,9 @@ from django.core.urlresolvers import (reverse, resolve, get_callable, from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect from django.shortcuts import redirect from django.test import TestCase -from django.utils import unittest -from django.contrib.auth.models import User +from django.utils import unittest, six -from . import urlconf_outer, urlconf_inner, middleware, views +from . import urlconf_outer, middleware, views resolve_test_data = ( @@ -535,7 +535,7 @@ class ViewLoadingTests(TestCase): def test_view_loading(self): # A missing view (identified by an AttributeError) should raise # ViewDoesNotExist, ... - self.assertRaisesRegexp(ViewDoesNotExist, ".*View does not exist in.*", + six.assertRaisesRegex(self, ViewDoesNotExist, ".*View does not exist in.*", get_callable, 'regressiontests.urlpatterns_reverse.views.i_should_not_exist') # ... but if the AttributeError is caused by something else don't diff --git a/tests/regressiontests/wsgi/tests.py b/tests/regressiontests/wsgi/tests.py index 5a40bd88e2..6c1483d2cd 100644 --- a/tests/regressiontests/wsgi/tests.py +++ b/tests/regressiontests/wsgi/tests.py @@ -6,8 +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 +from django.utils import six, unittest class WSGITest(TestCase): @@ -84,7 +83,7 @@ class GetInternalWSGIApplicationTest(unittest.TestCase): @override_settings(WSGI_APPLICATION="regressiontests.wsgi.noexist.app") def test_bad_module(self): - with self.assertRaisesRegexp( + with six.assertRaisesRegex(self, ImproperlyConfigured, r"^WSGI application 'regressiontests.wsgi.noexist.app' could not be loaded; could not import module 'regressiontests.wsgi.noexist':"): @@ -93,7 +92,7 @@ class GetInternalWSGIApplicationTest(unittest.TestCase): @override_settings(WSGI_APPLICATION="regressiontests.wsgi.wsgi.noexist") def test_bad_name(self): - with self.assertRaisesRegexp( + with six.assertRaisesRegex(self, ImproperlyConfigured, r"^WSGI application 'regressiontests.wsgi.wsgi.noexist' could not be loaded; can't find 'noexist' in module 'regressiontests.wsgi.wsgi':"): From 72b8f8d73bef36c555121b2550343cd9e830730e Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Fri, 7 Sep 2012 13:35:09 -0400 Subject: [PATCH 16/23] Updated the GEOS, PostGIS, and PROJ.4 versions in the GeoDjango installation docs. --- docs/ref/contrib/gis/install.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/ref/contrib/gis/install.txt b/docs/ref/contrib/gis/install.txt index 3e952c173b..5dc3726ad1 100644 --- a/docs/ref/contrib/gis/install.txt +++ b/docs/ref/contrib/gis/install.txt @@ -80,7 +80,7 @@ geospatial libraries: Program Description Required Supported Versions ======================== ==================================== ================================ ========================== :ref:`GEOS ` Geometry Engine Open Source Yes 3.3, 3.2, 3.1, 3.0 -`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.7, 4.6, 4.5, 4.4 +`PROJ.4`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 4.8, 4.7, 4.6, 4.5, 4.4 :ref:`GDAL ` Geospatial Data Abstraction Library No (but, required for SQLite) 1.9, 1.8, 1.7, 1.6, 1.5 :ref:`GeoIP ` IP-based geolocation library No 1.4 `PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 1.5, 1.4, 1.3 @@ -140,16 +140,16 @@ internal geometry representation used by GeoDjango (it's behind the "lazy" geometries). Specifically, the C API library is called (e.g., ``libgeos_c.so``) directly from Python using ctypes. -First, download GEOS 3.3.0 from the refractions Web site and untar the source +First, download GEOS 3.3.5 from the refractions Web site and untar the source archive:: - $ wget http://download.osgeo.org/geos/geos-3.3.0.tar.bz2 - $ tar xjf geos-3.3.0.tar.bz2 + $ wget http://download.osgeo.org/geos/geos-3.3.5.tar.bz2 + $ tar xjf geos-3.3.5.tar.bz2 Next, change into the directory where GEOS was unpacked, run the configure script, compile, and install:: - $ cd geos-3.3.0 + $ cd geos-3.3.5 $ ./configure $ make $ sudo make install @@ -203,15 +203,15 @@ reference systems. First, download the PROJ.4 source code and datum shifting files [#]_:: - $ wget http://download.osgeo.org/proj/proj-4.7.0.tar.gz - $ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.zip + $ wget http://download.osgeo.org/proj/proj-4.8.0.tar.gz + $ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.tar.gz Next, untar the source code archive, and extract the datum shifting files in the ``nad`` subdirectory. This must be done *prior* to configuration:: - $ tar xzf proj-4.7.0.tar.gz - $ cd proj-4.7.0/nad - $ unzip ../../proj-datumgrid-1.5.zip + $ tar xzf proj-4.8.0.tar.gz + $ cd proj-4.8.0/nad + $ tar xzf ../../proj-datumgrid-1.5.tar.gz $ cd .. Finally, configure, make and install PROJ.4:: @@ -239,9 +239,9 @@ installed prior to building PostGIS. First download the source archive, and extract:: - $ wget http://postgis.refractions.net/download/postgis-1.5.2.tar.gz - $ tar xzf postgis-1.5.2.tar.gz - $ cd postgis-1.5.2 + $ wget http://postgis.refractions.net/download/postgis-1.5.5.tar.gz + $ tar xzf postgis-1.5.5.tar.gz + $ cd postgis-1.5.5 Next, configure, make and install PostGIS:: From f47af9df1d3e03512364e5fe115f025c0a0be670 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 13:43:51 -0400 Subject: [PATCH 17/23] Cleaned up several test cases, to better isolate state. --- .../regressiontests/fixtures_regress/tests.py | 29 ++++---- tests/regressiontests/settings_tests/tests.py | 24 ++++--- .../regressiontests/signals_regress/tests.py | 70 +++++++++---------- 3 files changed, 59 insertions(+), 64 deletions(-) diff --git a/tests/regressiontests/fixtures_regress/tests.py b/tests/regressiontests/fixtures_regress/tests.py index 3e5a55372a..d675372c7a 100644 --- a/tests/regressiontests/fixtures_regress/tests.py +++ b/tests/regressiontests/fixtures_regress/tests.py @@ -21,18 +21,15 @@ from .models import (Animal, Stuff, Absolute, Parent, Child, Article, Widget, ExternalDependency, Thingy) -pre_save_checks = [] -def animal_pre_save_check(signal, sender, instance, **kwargs): - "A signal that is used to check the type of data loaded from fixtures" - pre_save_checks.append( - ( - 'Count = %s (%s)' % (instance.count, type(instance.count)), - 'Weight = %s (%s)' % (instance.weight, type(instance.weight)), - ) - ) - - class TestFixtures(TestCase): + def animal_pre_save_check(self, signal, sender, instance, **kwargs): + self.pre_save_checks.append( + ( + 'Count = %s (%s)' % (instance.count, type(instance.count)), + 'Weight = %s (%s)' % (instance.weight, type(instance.weight)), + ) + ) + def test_duplicate_pk(self): """ This is a regression test for ticket #3790. @@ -111,7 +108,6 @@ class TestFixtures(TestCase): ) self.assertEqual(Absolute.load_count, 1) - def test_unknown_format(self): """ Test for ticket #4371 -- Loading data of an unknown format should fail @@ -246,9 +242,8 @@ class TestFixtures(TestCase): Test for tickets #8298, #9942 - Field values should be coerced into the correct type by the deserializer, not as part of the database write. """ - global pre_save_checks - pre_save_checks = [] - signals.pre_save.connect(animal_pre_save_check) + self.pre_save_checks = [] + signals.pre_save.connect(self.animal_pre_save_check) try: management.call_command( 'loaddata', @@ -257,14 +252,14 @@ class TestFixtures(TestCase): commit=False, ) self.assertEqual( - pre_save_checks, + self.pre_save_checks, [ ("Count = 42 (<%s 'int'>)" % ('class' if PY3 else 'type'), "Weight = 1.2 (<%s 'float'>)" % ('class' if PY3 else 'type')) ] ) finally: - signals.pre_save.disconnect(animal_pre_save_check) + signals.pre_save.disconnect(self.animal_pre_save_check) def test_dumpdata_uses_default_manager(self): """ diff --git a/tests/regressiontests/settings_tests/tests.py b/tests/regressiontests/settings_tests/tests.py index 7225fb03ef..aaf8bcffcf 100644 --- a/tests/regressiontests/settings_tests/tests.py +++ b/tests/regressiontests/settings_tests/tests.py @@ -71,16 +71,18 @@ class SettingGetter(object): def __init__(self): self.test = getattr(settings, 'TEST', 'undefined') -testvalue = None - -def signal_callback(sender, setting, value, **kwargs): - if setting == 'TEST': - global testvalue - testvalue = value - -signals.setting_changed.connect(signal_callback) class SettingsTests(TestCase): + def setUp(self): + self.testvalue = None + signals.setting_changed.connect(self.signal_callback) + + def tearDown(self): + signals.setting_changed.disconnect(self.signal_callback) + + def signal_callback(self, sender, setting, value, **kwargs): + if setting == 'TEST': + self.testvalue = value def test_override(self): settings.TEST = 'test' @@ -128,12 +130,12 @@ class SettingsTests(TestCase): def test_signal_callback_context_manager(self): self.assertRaises(AttributeError, getattr, settings, 'TEST') with self.settings(TEST='override'): - self.assertEqual(testvalue, 'override') - self.assertEqual(testvalue, None) + self.assertEqual(self.testvalue, 'override') + self.assertEqual(self.testvalue, None) @override_settings(TEST='override') def test_signal_callback_decorator(self): - self.assertEqual(testvalue, 'override') + self.assertEqual(self.testvalue, 'override') # # Regression tests for #10130: deleting settings. diff --git a/tests/regressiontests/signals_regress/tests.py b/tests/regressiontests/signals_regress/tests.py index 4809a1e2a5..8fb3ad5a48 100644 --- a/tests/regressiontests/signals_regress/tests.py +++ b/tests/regressiontests/signals_regress/tests.py @@ -6,31 +6,6 @@ from django.test import TestCase from .models import Author, Book -signal_output = [] - -def pre_save_test(signal, sender, instance, **kwargs): - signal_output.append('pre_save signal, %s' % instance) - if kwargs.get('raw'): - signal_output.append('Is raw') - -def post_save_test(signal, sender, instance, **kwargs): - signal_output.append('post_save signal, %s' % instance) - if 'created' in kwargs: - if kwargs['created']: - signal_output.append('Is created') - else: - signal_output.append('Is updated') - if kwargs.get('raw'): - signal_output.append('Is raw') - -def pre_delete_test(signal, sender, instance, **kwargs): - signal_output.append('pre_save signal, %s' % instance) - signal_output.append('instance.id is not None: %s' % (instance.id != None)) - -def post_delete_test(signal, sender, instance, **kwargs): - signal_output.append('post_delete signal, %s' % instance) - signal_output.append('instance.id is not None: %s' % (instance.id != None)) - class SignalsRegressTests(TestCase): """ Testing signals before/after saving and deleting. @@ -38,12 +13,35 @@ class SignalsRegressTests(TestCase): def get_signal_output(self, fn, *args, **kwargs): # Flush any existing signal output - global signal_output - signal_output = [] + self.signal_output = [] fn(*args, **kwargs) - return signal_output + return self.signal_output + + def pre_save_test(self, signal, sender, instance, **kwargs): + self.signal_output.append('pre_save signal, %s' % instance) + if kwargs.get('raw'): + self.signal_output.append('Is raw') + + def post_save_test(self, signal, sender, instance, **kwargs): + self.signal_output.append('post_save signal, %s' % instance) + if 'created' in kwargs: + if kwargs['created']: + self.signal_output.append('Is created') + else: + self.signal_output.append('Is updated') + if kwargs.get('raw'): + self.signal_output.append('Is raw') + + def pre_delete_test(self, signal, sender, instance, **kwargs): + self.signal_output.append('pre_save signal, %s' % instance) + self.signal_output.append('instance.id is not None: %s' % (instance.id != None)) + + def post_delete_test(self, signal, sender, instance, **kwargs): + self.signal_output.append('post_delete signal, %s' % instance) + self.signal_output.append('instance.id is not None: %s' % (instance.id != None)) def setUp(self): + self.signal_output = [] # Save up the number of connected signals so that we can check at the end # that all the signals we register get properly unregistered (#9989) self.pre_signals = (len(models.signals.pre_save.receivers), @@ -51,16 +49,16 @@ class SignalsRegressTests(TestCase): len(models.signals.pre_delete.receivers), len(models.signals.post_delete.receivers)) - models.signals.pre_save.connect(pre_save_test) - models.signals.post_save.connect(post_save_test) - models.signals.pre_delete.connect(pre_delete_test) - models.signals.post_delete.connect(post_delete_test) + models.signals.pre_save.connect(self.pre_save_test) + models.signals.post_save.connect(self.post_save_test) + models.signals.pre_delete.connect(self.pre_delete_test) + models.signals.post_delete.connect(self.post_delete_test) def tearDown(self): - models.signals.post_delete.disconnect(post_delete_test) - models.signals.pre_delete.disconnect(pre_delete_test) - models.signals.post_save.disconnect(post_save_test) - models.signals.pre_save.disconnect(pre_save_test) + models.signals.post_delete.disconnect(self.post_delete_test) + models.signals.pre_delete.disconnect(self.pre_delete_test) + models.signals.post_save.disconnect(self.post_save_test) + models.signals.pre_save.disconnect(self.pre_save_test) # Check that all our signals got disconnected properly. post_signals = (len(models.signals.pre_save.receivers), From a92b81b0e8adc47a1357a3fa26324cbda226f211 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 14:01:46 -0400 Subject: [PATCH 18/23] Fixed tests that I broke a few commits ago. --- tests/regressiontests/i18n/commands/compilation.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/regressiontests/i18n/commands/compilation.py b/tests/regressiontests/i18n/commands/compilation.py index 856c9bb687..c6ab77941b 100644 --- a/tests/regressiontests/i18n/commands/compilation.py +++ b/tests/regressiontests/i18n/commands/compilation.py @@ -3,11 +3,12 @@ import os from django.core.management import call_command, CommandError from django.test import TestCase from django.test.utils import override_settings -from django.utils import translation +from django.utils import translation, six from django.utils.six import StringIO test_dir = os.path.abspath(os.path.dirname(__file__)) + class MessageCompilationTests(TestCase): def setUp(self): @@ -19,8 +20,8 @@ class MessageCompilationTests(TestCase): class PoFileTests(MessageCompilationTests): - LOCALE='es_AR' - MO_FILE='locale/%s/LC_MESSAGES/django.mo' % LOCALE + LOCALE = 'es_AR' + MO_FILE = 'locale/%s/LC_MESSAGES/django.mo' % LOCALE def test_bom_rejection(self): os.chdir(test_dir) From e4ea53677449cfc56a0093bfbd92cb482020bb1e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 14:14:06 -0400 Subject: [PATCH 19/23] Ensued that SQL indexes are alwasy created in the same name. Previous this used Python's builtin hash() function, which has never been guarnteed to be stable across implementations (CPython/Jython/etc.) or 32/64 bitness. However, this in practice it was stable. However, with the impending release of Python 3.3 hash randomizations is enabled by default, which would mean the index name changed between program invocations. --- django/db/backends/creation.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py index 6ac55eb5ff..659d35ace3 100644 --- a/django/db/backends/creation.py +++ b/django/db/backends/creation.py @@ -1,3 +1,4 @@ +import hashlib import sys import time @@ -27,7 +28,10 @@ class BaseDatabaseCreation(object): Generates a 32-bit digest of a set of arguments that can be used to shorten identifying names. """ - return '%x' % (abs(hash(args)) % 4294967296) # 2**32 + h = hashlib.md5() + for arg in args: + h.update(arg) + return h.hexdigest()[:8] def sql_create_model(self, model, style, known_models=set()): """ From 6a5a12ea3e3193b3658b9237b86d98bc37d668d7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 14:37:21 -0400 Subject: [PATCH 20/23] Fixed #17888 -- no longer silence exceptions inside of check_test. Thanks to brutasse for the patch. --- django/forms/widgets.py | 8 ++------ docs/ref/forms/widgets.txt | 4 ++++ tests/regressiontests/forms/tests/widgets.py | 10 +++------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/django/forms/widgets.py b/django/forms/widgets.py index fdb9f50688..7651efccd0 100644 --- a/django/forms/widgets.py +++ b/django/forms/widgets.py @@ -507,11 +507,7 @@ class CheckboxInput(Widget): def render(self, name, value, attrs=None): final_attrs = self.build_attrs(attrs, type='checkbox', name=name) - try: - result = self.check_test(value) - except: # Silently catch exceptions - result = False - if result: + if self.check_test(value): final_attrs['checked'] = 'checked' if not (value is True or value is False or value is None or value == ''): # Only add the 'value' attribute if a value is non-empty. @@ -525,7 +521,7 @@ class CheckboxInput(Widget): return False value = data.get(name) # Translate true and false strings to boolean values. - values = {'true': True, 'false': False} + values = {'true': True, 'false': False} if isinstance(value, six.string_types): value = values.get(value.lower(), value) return value diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index fb7657349a..eab314a4cd 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -310,6 +310,10 @@ commonly used groups of widgets: A callable that takes the value of the CheckBoxInput and returns ``True`` if the checkbox should be checked for that value. + .. versionchanged:: 1.5 + Exceptions from ``check_test`` used to be silenced by its caller, + this is no longer the case, they will propagate upwards. + ``Select`` ~~~~~~~~~~ diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py index c950aef719..544ca41642 100644 --- a/tests/regressiontests/forms/tests/widgets.py +++ b/tests/regressiontests/forms/tests/widgets.py @@ -216,13 +216,9 @@ class FormsWidgetTestCase(TestCase): self.assertHTMLEqual(w.render('greeting', 'hello there'), '') self.assertHTMLEqual(w.render('greeting', 'hello & goodbye'), '') - # A subtlety: If the 'check_test' argument cannot handle a value and raises any - # exception during its __call__, then the exception will be swallowed and the box - # will not be checked. In this example, the 'check_test' assumes the value has a - # startswith() method, which fails for the values True, False and None. - self.assertHTMLEqual(w.render('greeting', True), '') - self.assertHTMLEqual(w.render('greeting', False), '') - self.assertHTMLEqual(w.render('greeting', None), '') + # Ticket #17888: calling check_test shouldn't swallow exceptions + with self.assertRaises(AttributeError): + w.render('greeting', True) # The CheckboxInput widget will return False if the key is not found in the data # dictionary (because HTML form submission doesn't send any result for unchecked From 335a9f9cf1e2f40679e91cf42cfd0e636885a397 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 15:06:23 -0400 Subject: [PATCH 21/23] Removed many uses of bare "except:", which were either going to a) silence real issues, or b) were impossible to hit. --- django/contrib/localflavor/hr/forms.py | 10 ++++----- django/contrib/localflavor/ro/forms.py | 22 +++++++++---------- django/core/cache/backends/memcached.py | 2 +- django/core/mail/backends/console.py | 2 +- django/db/backends/sqlite3/base.py | 5 +---- django/http/multipartparser.py | 5 ++--- tests/regressiontests/file_uploads/tests.py | 2 +- tests/regressiontests/handlers/tests.py | 4 +--- tests/regressiontests/queries/tests.py | 5 +---- .../transactions_regress/tests.py | 22 ++++++------------- 10 files changed, 31 insertions(+), 48 deletions(-) diff --git a/django/contrib/localflavor/hr/forms.py b/django/contrib/localflavor/hr/forms.py index b935fd8a3a..083b61c49e 100644 --- a/django/contrib/localflavor/hr/forms.py +++ b/django/contrib/localflavor/hr/forms.py @@ -4,6 +4,7 @@ HR-specific Form helpers """ from __future__ import absolute_import, unicode_literals +import datetime import re from django.contrib.localflavor.hr.hr_choices import ( @@ -91,17 +92,16 @@ class HRJMBGField(Field): dd = int(matches.group('dd')) mm = int(matches.group('mm')) yyy = int(matches.group('yyy')) - import datetime try: - datetime.date(yyy,mm,dd) - except: + datetime.date(yyy, mm, dd) + except ValueError: raise ValidationError(self.error_messages['date']) # Validate checksum. k = matches.group('k') checksum = 0 - for i,j in zip(range(7,1,-1),range(6)): - checksum+=i*(int(value[j])+int(value[13-i])) + for i, j in zip(range(7, 1, -1), range(6)): + checksum += i * (int(value[j]) + int(value[13 - i])) m = 11 - checksum % 11 if m == 10: raise ValidationError(self.error_messages['invalid']) diff --git a/django/contrib/localflavor/ro/forms.py b/django/contrib/localflavor/ro/forms.py index bdbed5c476..f6de1534c9 100644 --- a/django/contrib/localflavor/ro/forms.py +++ b/django/contrib/localflavor/ro/forms.py @@ -4,6 +4,8 @@ Romanian specific form helpers. """ from __future__ import absolute_import, unicode_literals +import datetime + from django.contrib.localflavor.ro.ro_counties import COUNTIES_CHOICES from django.core.validators import EMPTY_VALUES from django.forms import ValidationError, Field, RegexField, Select @@ -69,10 +71,9 @@ class ROCNPField(RegexField): if value in EMPTY_VALUES: return '' # check birthdate digits - import datetime try: - datetime.date(int(value[1:3]),int(value[3:5]),int(value[5:7])) - except: + datetime.date(int(value[1:3]), int(value[3:5]), int(value[5:7])) + except ValueError: raise ValidationError(self.error_messages['invalid']) # checksum key = '279146358279' @@ -118,7 +119,7 @@ class ROCountyField(Field): # search for county name normalized_CC = [] for entry in COUNTIES_CHOICES: - normalized_CC.append((entry[0],entry[1].upper())) + normalized_CC.append((entry[0], entry[1].upper())) for entry in normalized_CC: if entry[1] == value: return entry[0] @@ -153,8 +154,8 @@ class ROIBANField(RegexField): value = super(ROIBANField, self).clean(value) if value in EMPTY_VALUES: return '' - value = value.replace('-','') - value = value.replace(' ','') + value = value.replace('-', '') + value = value.replace(' ', '') value = value.upper() if value[0:2] != 'RO': raise ValidationError(self.error_messages['invalid']) @@ -185,10 +186,10 @@ class ROPhoneNumberField(RegexField): value = super(ROPhoneNumberField, self).clean(value) if value in EMPTY_VALUES: return '' - value = value.replace('-','') - value = value.replace('(','') - value = value.replace(')','') - value = value.replace(' ','') + value = value.replace('-', '') + value = value.replace('(', '') + value = value.replace(')', '') + value = value.replace(' ', '') if len(value) != 10: raise ValidationError(self.error_messages['invalid']) return value @@ -202,4 +203,3 @@ class ROPostalCodeField(RegexField): def __init__(self, max_length=6, min_length=6, *args, **kwargs): super(ROPostalCodeField, self).__init__(r'^[0-9][0-8][0-9]{4}$', max_length, min_length, *args, **kwargs) - diff --git a/django/core/cache/backends/memcached.py b/django/core/cache/backends/memcached.py index 426a0a15c0..9bb47c8344 100644 --- a/django/core/cache/backends/memcached.py +++ b/django/core/cache/backends/memcached.py @@ -141,7 +141,7 @@ class CacheClass(BaseMemcachedCache): ) try: import memcache - except: + except ImportError: raise InvalidCacheBackendError( "Memcached cache backend requires either the 'memcache' or 'cmemcache' library" ) diff --git a/django/core/mail/backends/console.py b/django/core/mail/backends/console.py index 0baae0c01e..ea0cb5d9ad 100644 --- a/django/core/mail/backends/console.py +++ b/django/core/mail/backends/console.py @@ -21,7 +21,7 @@ class EmailBackend(BaseEmailBackend): stream_created = self.open() for message in email_messages: self.stream.write('%s\n' % message.message().as_string()) - self.stream.write('-'*79) + self.stream.write('-' * 79) self.stream.write('\n') self.stream.flush() # flush after each message if stream_created: diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index 31a16b6a2b..0f0b6b74e3 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -412,7 +412,4 @@ def _sqlite_format_dtdelta(dt, conn, days, secs, usecs): return str(dt) def _sqlite_regexp(re_pattern, re_string): - try: - return bool(re.search(re_pattern, re_string)) - except: - return False + return bool(re.search(re_pattern, re_string)) diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py index e76a4f4208..40aefd6e9d 100644 --- a/django/http/multipartparser.py +++ b/django/http/multipartparser.py @@ -68,11 +68,10 @@ class MultiPartParser(object): if not boundary or not cgi.valid_boundary(boundary): raise MultiPartParserError('Invalid boundary in multipart: %s' % boundary) - # Content-Length should contain the length of the body we are about # to receive. try: - content_length = int(META.get('HTTP_CONTENT_LENGTH', META.get('CONTENT_LENGTH',0))) + content_length = int(META.get('HTTP_CONTENT_LENGTH', META.get('CONTENT_LENGTH', 0))) except (ValueError, TypeError): content_length = 0 @@ -178,7 +177,7 @@ class MultiPartParser(object): content_type = meta_data.get('content-type', ('',))[0].strip() try: - charset = meta_data.get('content-type', (0,{}))[1].get('charset', None) + charset = meta_data.get('content-type', (0, {}))[1].get('charset', None) except: charset = None diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py index a545ed649e..f28d658f52 100644 --- a/tests/regressiontests/file_uploads/tests.py +++ b/tests/regressiontests/file_uploads/tests.py @@ -100,7 +100,7 @@ class FileUploadTests(TestCase): try: os.unlink(file1.name) - except: + except OSError: pass self.assertEqual(response.status_code, 200) diff --git a/tests/regressiontests/handlers/tests.py b/tests/regressiontests/handlers/tests.py index ae2062c756..34863b6493 100644 --- a/tests/regressiontests/handlers/tests.py +++ b/tests/regressiontests/handlers/tests.py @@ -17,10 +17,8 @@ class HandlerTests(unittest.TestCase): # Try running the handler, it will fail in load_middleware handler = WSGIHandler() self.assertEqual(handler.initLock.locked(), False) - try: + with self.assertRaises(Exception): handler(None, None) - except: - pass self.assertEqual(handler.initLock.locked(), False) # Reset settings settings.MIDDLEWARE_CLASSES = old_middleware_classes diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py index 005aa9650b..71ac107486 100644 --- a/tests/regressiontests/queries/tests.py +++ b/tests/regressiontests/queries/tests.py @@ -1677,10 +1677,7 @@ class CloneTests(TestCase): list(n_list) # Use the note queryset in a query, and evalute # that query in a way that involves cloning. - try: - self.assertEqual(ExtraInfo.objects.filter(note__in=n_list)[0].info, 'good') - except: - self.fail('Query should be clonable') + self.assertEqual(ExtraInfo.objects.filter(note__in=n_list)[0].info, 'good') class EmptyQuerySetTests(TestCase): diff --git a/tests/regressiontests/transactions_regress/tests.py b/tests/regressiontests/transactions_regress/tests.py index 90b3df03d4..472e2aafd9 100644 --- a/tests/regressiontests/transactions_regress/tests.py +++ b/tests/regressiontests/transactions_regress/tests.py @@ -1,7 +1,6 @@ from __future__ import absolute_import -from django.core.exceptions import ImproperlyConfigured -from django.db import connection, connections, transaction, DEFAULT_DB_ALIAS +from django.db import connection, connections, transaction, DEFAULT_DB_ALIAS, DatabaseError from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError from django.test import TransactionTestCase, skipUnlessDBFeature from django.test.utils import override_settings @@ -151,21 +150,14 @@ class TestTransactionClosing(TransactionTestCase): # Create a user create_system_user() - try: - # The second call to create_system_user should fail for violating a unique constraint - # (it's trying to re-create the same user) + with self.assertRaises(DatabaseError): + # The second call to create_system_user should fail for violating + # a unique constraint (it's trying to re-create the same user) create_system_user() - except: - pass - else: - raise ImproperlyConfigured('Unique constraint not enforced on django.contrib.auth.models.User') - try: - # Try to read the database. If the last transaction was indeed closed, - # this should cause no problems - _ = User.objects.all()[0] - except: - self.fail("A transaction consisting of a failed operation was not closed.") + # Try to read the database. If the last transaction was indeed closed, + # this should cause no problems + User.objects.all()[0] @override_settings(DEBUG=True) def test_failing_query_transaction_closed_debug(self): From ad50243cd143906d573b11397fa0fd080c9cd7f1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 15:33:02 -0400 Subject: [PATCH 22/23] [py3k] Fixed the index creation code that I committed a few minutes ago for py3k. --- django/db/backends/creation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py index 659d35ace3..52d5ac0547 100644 --- a/django/db/backends/creation.py +++ b/django/db/backends/creation.py @@ -4,6 +4,7 @@ import time from django.conf import settings from django.db.utils import load_backend +from django.utils.encoding import force_bytes from django.utils.six.moves import input # The prefix to put on the default database name when creating @@ -30,7 +31,7 @@ class BaseDatabaseCreation(object): """ h = hashlib.md5() for arg in args: - h.update(arg) + h.update(force_bytes(arg)) return h.hexdigest()[:8] def sql_create_model(self, model, style, known_models=set()): From 5999eb42eb6dad6a74c43eb6e9d96ac368ad97b4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Sep 2012 15:34:48 -0400 Subject: [PATCH 23/23] Removed another usage of the bear "except:" (rawr!). --- tests/regressiontests/file_uploads/tests.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py index f28d658f52..2a1ec7db21 100644 --- a/tests/regressiontests/file_uploads/tests.py +++ b/tests/regressiontests/file_uploads/tests.py @@ -384,15 +384,13 @@ class DirectoryCreationTests(unittest.TestCase): """The correct IOError is raised when the upload directory name exists but isn't a directory""" # Create a file with the upload directory name open(UPLOAD_TO, 'wb').close() - try: + with self.assertRaises(IOError) as exc_info: self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', b'x')) - except IOError as err: - # The test needs to be done on a specific string as IOError - # is raised even without the patch (just not early enough) - self.assertEqual(err.args[0], - "%s exists and is not a directory." % UPLOAD_TO) - except: - self.fail("IOError not raised") + # The test needs to be done on a specific string as IOError + # is raised even without the patch (just not early enough) + self.assertEqual(exc_info.exception.args[0], + "%s exists and is not a directory." % UPLOAD_TO) + class MultiParserTests(unittest.TestCase):