Commit 340c2991 by Chris Jerdonek

Renamed Context to ContextStack.

parent 780cf29c
# coding: utf-8
"""
Exposes a context class and functions to retrieve names from context.
Exposes a ContextStack class and functions to retrieve names from context.
"""
......@@ -33,7 +33,7 @@ def _get_value(item, key):
Returns _NOT_FOUND if the key does not exist.
The Context.get() docstring documents this function's intended behavior.
The ContextStack.get() docstring documents this function's intended behavior.
"""
if isinstance(item, dict):
......@@ -79,7 +79,7 @@ def resolve(context, name):
return context.get(name, '')
class Context(object):
class ContextStack(object):
"""
Provides dictionary-like access to a stack of zero or more items.
......@@ -94,7 +94,7 @@ class Context(object):
(last in, first out).
Caution: this class does not currently support recursive nesting in
that items in the stack cannot themselves be Context instances.
that items in the stack cannot themselves be ContextStack instances.
See the docstrings of the methods of this class for more details.
......@@ -111,7 +111,7 @@ class Context(object):
stack in order so that, in particular, items at the end of
the argument list are queried first when querying the stack.
Caution: items should not themselves be Context instances, as
Caution: items should not themselves be ContextStack instances, as
recursive nesting does not behave as one might expect.
"""
......@@ -123,9 +123,9 @@ class Context(object):
For example--
>>> context = Context({'alpha': 'abc'}, {'numeric': 123})
>>> context = ContextStack({'alpha': 'abc'}, {'numeric': 123})
>>> repr(context)
"Context({'alpha': 'abc'}, {'numeric': 123})"
"ContextStack({'alpha': 'abc'}, {'numeric': 123})"
"""
return "%s%s" % (self.__class__.__name__, tuple(self._stack))
......@@ -133,18 +133,18 @@ class Context(object):
@staticmethod
def create(*context, **kwargs):
"""
Build a Context instance from a sequence of context-like items.
Build a ContextStack instance from a sequence of context-like items.
This factory-style method is more general than the Context class's
This factory-style method is more general than the ContextStack class's
constructor in that, unlike the constructor, the argument list
can itself contain Context instances.
can itself contain ContextStack instances.
Here is an example illustrating various aspects of this method:
>>> obj1 = {'animal': 'cat', 'vegetable': 'carrot', 'mineral': 'copper'}
>>> obj2 = Context({'vegetable': 'spinach', 'mineral': 'silver'})
>>> obj2 = ContextStack({'vegetable': 'spinach', 'mineral': 'silver'})
>>>
>>> context = Context.create(obj1, None, obj2, mineral='gold')
>>> context = ContextStack.create(obj1, None, obj2, mineral='gold')
>>>
>>> context.get('animal')
'cat'
......@@ -155,7 +155,7 @@ class Context(object):
Arguments:
*context: zero or more dictionaries, Context instances, or objects
*context: zero or more dictionaries, ContextStack instances, or objects
with which to populate the initial context stack. None
arguments will be skipped. Items in the *context list are
added to the stack in order so that later items in the argument
......@@ -171,12 +171,12 @@ class Context(object):
"""
items = context
context = Context()
context = ContextStack()
for item in items:
if item is None:
continue
if isinstance(item, Context):
if isinstance(item, ContextStack):
context._stack.extend(item._stack)
else:
context.push(item)
......@@ -245,9 +245,9 @@ class Context(object):
>>>
>>> dct['greet'] is obj.greet
True
>>> Context(dct).get('greet') #doctest: +ELLIPSIS
>>> ContextStack(dct).get('greet') #doctest: +ELLIPSIS
<function greet at 0x...>
>>> Context(obj).get('greet')
>>> ContextStack(obj).get('greet')
'Hi Bob!'
TODO: explain the rationale for this difference in treatment.
......@@ -289,4 +289,4 @@ class Context(object):
Return a copy of this instance.
"""
return Context(*self._stack)
return ContextStack(*self._stack)
......@@ -17,7 +17,7 @@ class ParsedTemplate(object):
parse_tree: a list, each element of which is either--
(1) a unicode string, or
(2) a "rendering" callable that accepts a Context instance
(2) a "rendering" callable that accepts a ContextStack instance
and returns a unicode string.
The possible rendering callables are the return values of the
......
......@@ -215,7 +215,7 @@ class RenderEngine(object):
Arguments:
template: a template string of type unicode.
context: a Context instance.
context: a ContextStack instance.
"""
# We keep this type-check as an added check because this method is
......@@ -238,7 +238,7 @@ class RenderEngine(object):
template: a template string of type unicode (but not a proper
subclass of unicode).
context: a Context instance.
context: a ContextStack instance.
"""
# Be strict but not too strict. In other words, accept str instead
......
......@@ -8,7 +8,7 @@ This module provides a Renderer class to render templates.
import sys
from pystache import defaults
from pystache.context import Context
from pystache.context import ContextStack
from pystache.loader import Loader
from pystache.renderengine import RenderEngine
from pystache.specloader import SpecLoader
......@@ -277,7 +277,7 @@ class Renderer(object):
# RenderEngine.render() requires that the template string be unicode.
template = self._to_unicode_hard(template)
context = Context.create(*context, **kwargs)
context = ContextStack.create(*context, **kwargs)
self._context = context
engine = self._make_render_engine()
......@@ -338,7 +338,7 @@ class Renderer(object):
uses the passed object as the first element of the context stack
when rendering.
*context: zero or more dictionaries, Context instances, or objects
*context: zero or more dictionaries, ContextStack instances, or objects
with which to populate the initial context stack. None
arguments are skipped. Items in the *context list are added to
the context stack in order so that later items in the argument
......
......@@ -10,7 +10,7 @@ import unittest
from pystache.context import _NOT_FOUND
from pystache.context import _get_value
from pystache.context import Context
from pystache.context import ContextStack
from pystache.tests.common import AssertIsMixin
class SimpleObject(object):
......@@ -204,10 +204,10 @@ class GetValueTests(unittest.TestCase, AssertIsMixin):
self.assertNotFound(item2, 'pop')
class ContextTests(unittest.TestCase, AssertIsMixin):
class ContextStackTests(unittest.TestCase, AssertIsMixin):
"""
Test the Context class.
Test the ContextStack class.
"""
......@@ -216,34 +216,34 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Check that passing nothing to __init__() raises no exception.
"""
context = Context()
context = ContextStack()
def test_init__many_elements(self):
"""
Check that passing more than two items to __init__() raises no exception.
"""
context = Context({}, {}, {})
context = ContextStack({}, {}, {})
def test__repr(self):
context = Context()
self.assertEqual(repr(context), 'Context()')
context = ContextStack()
self.assertEqual(repr(context), 'ContextStack()')
context = Context({'foo': 'bar'})
self.assertEqual(repr(context), "Context({'foo': 'bar'},)")
context = ContextStack({'foo': 'bar'})
self.assertEqual(repr(context), "ContextStack({'foo': 'bar'},)")
context = Context({'foo': 'bar'}, {'abc': 123})
self.assertEqual(repr(context), "Context({'foo': 'bar'}, {'abc': 123})")
context = ContextStack({'foo': 'bar'}, {'abc': 123})
self.assertEqual(repr(context), "ContextStack({'foo': 'bar'}, {'abc': 123})")
def test__str(self):
context = Context()
self.assertEqual(str(context), 'Context()')
context = ContextStack()
self.assertEqual(str(context), 'ContextStack()')
context = Context({'foo': 'bar'})
self.assertEqual(str(context), "Context({'foo': 'bar'},)")
context = ContextStack({'foo': 'bar'})
self.assertEqual(str(context), "ContextStack({'foo': 'bar'},)")
context = Context({'foo': 'bar'}, {'abc': 123})
self.assertEqual(str(context), "Context({'foo': 'bar'}, {'abc': 123})")
context = ContextStack({'foo': 'bar'}, {'abc': 123})
self.assertEqual(str(context), "ContextStack({'foo': 'bar'}, {'abc': 123})")
## Test the static create() method.
......@@ -252,7 +252,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test passing a dictionary.
"""
context = Context.create({'foo': 'bar'})
context = ContextStack.create({'foo': 'bar'})
self.assertEqual(context.get('foo'), 'bar')
def test_create__none(self):
......@@ -260,7 +260,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test passing None.
"""
context = Context.create({'foo': 'bar'}, None)
context = ContextStack.create({'foo': 'bar'}, None)
self.assertEqual(context.get('foo'), 'bar')
def test_create__object(self):
......@@ -270,16 +270,16 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
"""
class Foo(object):
foo = 'bar'
context = Context.create(Foo())
context = ContextStack.create(Foo())
self.assertEqual(context.get('foo'), 'bar')
def test_create__context(self):
"""
Test passing a Context instance.
Test passing a ContextStack instance.
"""
obj = Context({'foo': 'bar'})
context = Context.create(obj)
obj = ContextStack({'foo': 'bar'})
context = ContextStack.create(obj)
self.assertEqual(context.get('foo'), 'bar')
def test_create__kwarg(self):
......@@ -287,7 +287,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test passing a keyword argument.
"""
context = Context.create(foo='bar')
context = ContextStack.create(foo='bar')
self.assertEqual(context.get('foo'), 'bar')
def test_create__precedence_positional(self):
......@@ -295,7 +295,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test precedence of positional arguments.
"""
context = Context.create({'foo': 'bar'}, {'foo': 'buzz'})
context = ContextStack.create({'foo': 'bar'}, {'foo': 'buzz'})
self.assertEqual(context.get('foo'), 'buzz')
def test_create__precedence_keyword(self):
......@@ -303,7 +303,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test precedence of keyword arguments.
"""
context = Context.create({'foo': 'bar'}, foo='buzz')
context = ContextStack.create({'foo': 'bar'}, foo='buzz')
self.assertEqual(context.get('foo'), 'buzz')
def test_get__key_present(self):
......@@ -311,7 +311,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test getting a key.
"""
context = Context({"foo": "bar"})
context = ContextStack({"foo": "bar"})
self.assertEqual(context.get("foo"), "bar")
def test_get__key_missing(self):
......@@ -319,7 +319,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test getting a missing key.
"""
context = Context()
context = ContextStack()
self.assertTrue(context.get("foo") is None)
def test_get__default(self):
......@@ -327,7 +327,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test that get() respects the default value.
"""
context = Context()
context = ContextStack()
self.assertEqual(context.get("foo", "bar"), "bar")
def test_get__precedence(self):
......@@ -335,7 +335,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Test that get() respects the order of precedence (later items first).
"""
context = Context({"foo": "bar"}, {"foo": "buzz"})
context = ContextStack({"foo": "bar"}, {"foo": "buzz"})
self.assertEqual(context.get("foo"), "buzz")
def test_get__fallback(self):
......@@ -343,7 +343,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
Check that first-added stack items are queried on context misses.
"""
context = Context({"fuzz": "buzz"}, {"foo": "bar"})
context = ContextStack({"fuzz": "buzz"}, {"foo": "bar"})
self.assertEqual(context.get("fuzz"), "buzz")
def test_push(self):
......@@ -352,7 +352,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
"""
key = "foo"
context = Context({key: "bar"})
context = ContextStack({key: "bar"})
self.assertEqual(context.get(key), "bar")
context.push({key: "buzz"})
......@@ -364,7 +364,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
"""
key = "foo"
context = Context({key: "bar"}, {key: "buzz"})
context = ContextStack({key: "bar"}, {key: "buzz"})
self.assertEqual(context.get(key), "buzz")
item = context.pop()
......@@ -373,7 +373,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
def test_top(self):
key = "foo"
context = Context({key: "bar"}, {key: "buzz"})
context = ContextStack({key: "bar"}, {key: "buzz"})
self.assertEqual(context.get(key), "buzz")
top = context.top()
......@@ -383,7 +383,7 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
def test_copy(self):
key = "foo"
original = Context({key: "bar"}, {key: "buzz"})
original = ContextStack({key: "bar"}, {key: "buzz"})
self.assertEqual(original.get(key), "buzz")
new = original.copy()
......
......@@ -7,7 +7,7 @@ Unit tests of renderengine.py.
import unittest
from pystache.context import Context
from pystache.context import ContextStack
from pystache import defaults
from pystache.parser import ParsingError
from pystache.renderengine import RenderEngine
......@@ -83,7 +83,7 @@ class RenderTests(unittest.TestCase, AssertStringMixin):
if partials is not None:
engine.load_partial = lambda key: unicode(partials[key])
context = Context(*context)
context = ContextStack(*context)
actual = engine.render(template, context)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment