From 3bbebd06adc36f31877a9c0af6c20c5b5a71a900 Mon Sep 17 00:00:00 2001
From: Tim Graham <timograham@gmail.com>
Date: Tue, 18 Aug 2015 12:25:38 -0400
Subject: [PATCH] Refs #13408 -- Made unpacking mismatch an exception in {% for
 %} tag per deprecation timeline.

---
 django/template/defaulttags.py                |  6 +--
 tests/template_tests/syntax_tests/test_for.py | 52 +++++++------------
 2 files changed, 20 insertions(+), 38 deletions(-)

diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index 540d6c578a..9f0389c0e4 100644
--- a/django/template/defaulttags.py
+++ b/django/template/defaulttags.py
@@ -9,7 +9,6 @@ from itertools import cycle as itertools_cycle, groupby
 
 from django.conf import settings
 from django.utils import six, timezone
-from django.utils.deprecation import RemovedInDjango110Warning
 from django.utils.encoding import force_text, smart_text
 from django.utils.html import conditional_escape, format_html
 from django.utils.lorem_ipsum import paragraphs, words
@@ -200,11 +199,10 @@ class ForNode(Node):
                         len_item = len(item)
                     # Check loop variable count before unpacking
                     if num_loopvars != len_item:
-                        warnings.warn(
+                        raise ValueError(
                             "Need {} values to unpack in for loop; got {}. "
-                            "This will raise an exception in Django 1.10."
                             .format(num_loopvars, len_item),
-                            RemovedInDjango110Warning)
+                        )
                     try:
                         unpacked_vars = dict(zip(self.loopvars, item))
                     except TypeError:
diff --git a/tests/template_tests/syntax_tests/test_for.py b/tests/template_tests/syntax_tests/test_for.py
index f3d571cff1..ff92c09369 100644
--- a/tests/template_tests/syntax_tests/test_for.py
+++ b/tests/template_tests/syntax_tests/test_for.py
@@ -1,6 +1,5 @@
 from django.template import TemplateSyntaxError
-from django.test import SimpleTestCase, ignore_warnings
-from django.utils.deprecation import RemovedInDjango110Warning
+from django.test import SimpleTestCase
 
 from ..utils import setup
 
@@ -130,46 +129,31 @@ class ForTagTests(SimpleTestCase):
     # These tests raise deprecation warnings and will raise an exception
     # in Django 1.10. The existing behavior is silent truncation if the
     # length of loopvars differs to the length of each set of items.
-    @ignore_warnings(category=RemovedInDjango110Warning)
     @setup({'for-tag-unpack10': '{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}'})
     def test_for_tag_unpack10(self):
-        output = self.engine.render_to_string(
-            'for-tag-unpack10',
-            {'items': (('one', 1, 'carrot'), ('two', 2, 'orange'))},
-        )
-        self.assertEqual(output, 'one:1/two:2/')
+        with self.assertRaisesMessage(ValueError, 'Need 2 values to unpack in for loop; got 3.'):
+            self.engine.render_to_string(
+                'for-tag-unpack10',
+                {'items': (('one', 1, 'carrot'), ('two', 2, 'orange'))},
+            )
 
-    @ignore_warnings(category=RemovedInDjango110Warning)
     @setup({'for-tag-unpack11': '{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}'})
     def test_for_tag_unpack11(self):
-        output = self.engine.render_to_string(
-            'for-tag-unpack11',
-            {'items': (('one', 1), ('two', 2))},
-        )
+        with self.assertRaisesMessage(ValueError, 'Need 3 values to unpack in for loop; got 2.'):
+            self.engine.render_to_string(
+                'for-tag-unpack11',
+                {'items': (('one', 1), ('two', 2))},
+            )
 
-        if self.engine.string_if_invalid:
-            self.assertEqual(output, 'one:1,INVALID/two:2,INVALID/')
-        else:
-            self.assertEqual(output, 'one:1,/two:2,/')
-
-    @ignore_warnings(category=RemovedInDjango110Warning)
     @setup({'for-tag-unpack12': '{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}'})
     def test_for_tag_unpack12(self):
-        output = self.engine.render_to_string(
-            'for-tag-unpack12',
-            {'items': (('one', 1, 'carrot'), ('two', 2))}
-        )
-        if self.engine.string_if_invalid:
-            self.assertEqual(output, 'one:1,carrot/two:2,INVALID/')
-        else:
-            self.assertEqual(output, 'one:1,carrot/two:2,/')
+        with self.assertRaisesMessage(ValueError, 'Need 3 values to unpack in for loop; got 2.'):
+            self.engine.render_to_string(
+                'for-tag-unpack12',
+                {'items': (('one', 1, 'carrot'), ('two', 2))}
+            )
 
-    @ignore_warnings(category=RemovedInDjango110Warning)
     @setup({'for-tag-unpack14': '{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}'})
     def test_for_tag_unpack14(self):
-        output = self.engine.render_to_string('for-tag-unpack14', {'items': (1, 2)})
-
-        if self.engine.string_if_invalid:
-            self.assertEqual(output, 'INVALID:INVALID/INVALID:INVALID/')
-        else:
-            self.assertEqual(output, ':/:/')
+        with self.assertRaisesMessage(ValueError, 'Need 2 values to unpack in for loop; got 1.'):
+            self.engine.render_to_string('for-tag-unpack14', {'items': (1, 2)})