From 6bfd864ff2a7d4903d485ee40094a1315da8221b Mon Sep 17 00:00:00 2001 From: Tommy Beadle Date: Mon, 13 Apr 2015 10:57:44 -0400 Subject: [PATCH] Fixed #24603 -- Allowed Context.update() to be used as a context manager. --- django/template/context.py | 3 +-- docs/ref/templates/api.txt | 15 +++++++++++++++ docs/releases/1.9.txt | 3 +++ tests/template_tests/test_context.py | 13 +++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/django/template/context.py b/django/template/context.py index 2434b31a683..778a83d7a3e 100644 --- a/django/template/context.py +++ b/django/template/context.py @@ -171,8 +171,7 @@ class Context(BaseContext): "Pushes other_dict to the stack of dictionaries in the Context" if not hasattr(other_dict, '__getitem__'): raise TypeError('other_dict must be a mapping (dictionary-like) object.') - self.dicts.append(other_dict) - return other_dict + return ContextDict(self, other_dict) class RenderContext(BaseContext): diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt index 077330f6ce5..5e56eff1d4f 100644 --- a/docs/ref/templates/api.txt +++ b/docs/ref/templates/api.txt @@ -497,6 +497,21 @@ the stack instead of an empty one. >>> c['foo'] 'first level' +Like ``push()``, you can use ``update()`` as a context manager to ensure a +matching ``pop()`` is called. + + >>> c = Context() + >>> c['foo'] = 'first level' + >>> with c.update({'foo': 'second level'}): + ... c['foo'] + 'second level' + >>> c['foo'] + 'first level' + +.. versionadded:: 1.9 + + The ability to use ``update()`` as a context manager was added. + Using a ``Context`` as a stack comes in handy in :ref:`some custom template tags `. diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index 47c2bc98bc9..25da6978ba8 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -211,6 +211,9 @@ Templates * The :ttag:`firstof` template tag supports storing the output in a variable using 'as'. +* :meth:`Context.update() ` can now be used as + a context manager. + Requests and Responses ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/template_tests/test_context.py b/tests/template_tests/test_context.py index 9c23a38af23..f7959e64158 100644 --- a/tests/template_tests/test_context.py +++ b/tests/template_tests/test_context.py @@ -21,6 +21,8 @@ class ContextTests(SimpleTestCase): self.assertEqual(c["a"], 1) self.assertEqual(c.get("foo", 42), 42) + def test_push_context_manager(self): + c = Context({"a": 1}) with c.push(): c['a'] = 2 self.assertEqual(c['a'], 2) @@ -30,6 +32,17 @@ class ContextTests(SimpleTestCase): self.assertEqual(c['a'], 3) self.assertEqual(c['a'], 1) + def test_update_context_manager(self): + c = Context({"a": 1}) + with c.update({}): + c['a'] = 2 + self.assertEqual(c['a'], 2) + self.assertEqual(c['a'], 1) + + with c.update({'a': 3}): + self.assertEqual(c['a'], 3) + self.assertEqual(c['a'], 1) + def test_setdefault(self): c = Context()