Commit ee579e21 by Chris Jerdonek

Addresses issue #81: not to call methods on instances of built-in types.

parent 4b8a6952
......@@ -5,23 +5,14 @@ Unit tests of context.py.
"""
from datetime import datetime
import unittest
from pystache.context import _NOT_FOUND
from pystache.context import _get_item
from pystache.context import _get_value
from pystache.context import Context
class AssertIsMixin:
"""A mixin for adding assertIs() to a unittest.TestCase."""
# unittest.assertIs() is not available until Python 2.7:
# http://docs.python.org/library/unittest.html#unittest.TestCase.assertIsNone
def assertIs(self, first, second):
self.assertTrue(first is second, msg="%s is not %s" % (repr(first), repr(second)))
class SimpleObject(object):
"""A sample class that does not define __getitem__()."""
......@@ -33,7 +24,7 @@ class SimpleObject(object):
return "called..."
class MappingObject(object):
class DictLike(object):
"""A sample class that implements __getitem__() and __contains__()."""
......@@ -48,26 +39,36 @@ class MappingObject(object):
return self._dict[key]
class GetItemTestCase(unittest.TestCase, AssertIsMixin):
class AssertIsMixin:
"""A mixin for adding assertIs() to a unittest.TestCase."""
# unittest.assertIs() is not available until Python 2.7:
# http://docs.python.org/library/unittest.html#unittest.TestCase.assertIsNone
def assertIs(self, first, second):
self.assertTrue(first is second, msg="%s is not %s" % (repr(first), repr(second)))
"""Test context._get_item()."""
class GetValueTests(unittest.TestCase, AssertIsMixin):
def assertNotFound(self, obj, key):
"""Test context._get_value()."""
def assertNotFound(self, item, key):
"""
Assert that a call to _get_item() returns _NOT_FOUND.
Assert that a call to _get_value() returns _NOT_FOUND.
"""
self.assertIs(_get_item(obj, key), _NOT_FOUND)
self.assertIs(_get_value(item, key), _NOT_FOUND)
### Case: obj is a dictionary.
### Case: the item is a dictionary.
def test_dictionary__key_present(self):
"""
Test getting a key from a dictionary.
"""
obj = {"foo": "bar"}
self.assertEquals(_get_item(obj, "foo"), "bar")
item = {"foo": "bar"}
self.assertEquals(_get_value(item, "foo"), "bar")
def test_dictionary__callable_not_called(self):
"""
......@@ -77,95 +78,132 @@ class GetItemTestCase(unittest.TestCase, AssertIsMixin):
def foo_callable(self):
return "bar"
obj = {"foo": foo_callable}
self.assertNotEquals(_get_item(obj, "foo"), "bar")
self.assertTrue(_get_item(obj, "foo") is foo_callable)
item = {"foo": foo_callable}
self.assertNotEquals(_get_value(item, "foo"), "bar")
self.assertTrue(_get_value(item, "foo") is foo_callable)
def test_dictionary__key_missing(self):
"""
Test getting a missing key from a dictionary.
"""
obj = {}
self.assertNotFound(obj, "missing")
item = {}
self.assertNotFound(item, "missing")
def test_dictionary__attributes_not_checked(self):
"""
Test that dictionary attributes are not checked.
"""
obj = {}
item = {}
attr_name = "keys"
self.assertEquals(getattr(obj, attr_name)(), [])
self.assertNotFound(obj, attr_name)
self.assertEquals(getattr(item, attr_name)(), [])
self.assertNotFound(item, attr_name)
def test_dictionary__dict_subclass(self):
"""
Test that subclasses of dict are treated as dictionaries.
"""
class DictSubclass(dict): pass
### Case: obj does not implement __getitem__().
item = DictSubclass()
item["foo"] = "bar"
self.assertEquals(_get_value(item, "foo"), "bar")
### Case: the item is an object.
def test_object__attribute_present(self):
"""
Test getting an attribute from an object.
"""
obj = SimpleObject()
self.assertEquals(_get_item(obj, "foo"), "bar")
item = SimpleObject()
self.assertEquals(_get_value(item, "foo"), "bar")
def test_object__attribute_missing(self):
"""
Test getting a missing attribute from an object.
"""
obj = SimpleObject()
self.assertNotFound(obj, "missing")
item = SimpleObject()
self.assertNotFound(item, "missing")
def test_object__attribute_is_callable(self):
"""
Test getting a callable attribute from an object.
"""
obj = SimpleObject()
self.assertEquals(_get_item(obj, "foo_callable"), "called...")
item = SimpleObject()
self.assertEquals(_get_value(item, "foo_callable"), "called...")
def test_object__non_built_in_type(self):
"""
Test getting an attribute from an instance of a type that isn't built-in.
### Case: obj implements __getitem__() (i.e. a "mapping object").
"""
item = datetime(2012, 1, 2)
self.assertEquals(_get_value(item, "day"), 2)
def test_mapping__key_present(self):
def test_object__dict_like(self):
"""
Test getting a key from a mapping object.
Test getting a key from a dict-like object (an object that implements '__getitem__').
"""
obj = MappingObject()
self.assertEquals(_get_item(obj, "foo"), "bar")
item = DictLike()
self.assertEquals(item["foo"], "bar")
self.assertNotFound(item, "foo")
### Case: the item is an instance of a built-in type.
def test_mapping__key_missing(self):
def test_built_in_type__integer(self):
"""
Test getting a missing key from a mapping object.
Test getting from an integer.
"""
obj = MappingObject()
self.assertNotFound(obj, "missing")
class MyInt(int): pass
item1 = MyInt(10)
item2 = 10
self.assertEquals(item1.real, 10)
self.assertEquals(item2.real, 10)
self.assertEquals(_get_value(item1, 'real'), 10)
self.assertNotFound(item2, 'real')
def test_mapping__get_attribute(self):
def test_built_in_type__string(self):
"""
Test getting an attribute from a mapping object.
Test getting from a string.
"""
obj = MappingObject()
key = "fuzz"
self.assertEquals(getattr(obj, key), "buzz")
# As desired, __getitem__()'s presence causes obj.fuzz not to be checked.
self.assertNotFound(obj, key)
class MyStr(str): pass
def test_mapping_object__not_implementing_contains(self):
item1 = MyStr('abc')
item2 = 'abc'
self.assertEquals(item1.upper(), 'ABC')
self.assertEquals(item2.upper(), 'ABC')
self.assertEquals(_get_value(item1, 'upper'), 'ABC')
self.assertNotFound(item2, 'upper')
def test_built_in_type__list(self):
"""
Test querying a mapping object that doesn't define __contains__().
Test getting from a list.
"""
class Sample(object):
class MyList(list): pass
item1 = MyList([1, 2, 3])
item2 = [1, 2, 3]
def __getitem__(self, key):
return "bar"
self.assertEquals(item1.pop(), 3)
self.assertEquals(item2.pop(), 3)
obj = Sample()
self.assertRaises(AttributeError, _get_item, obj, "foo")
self.assertEquals(_get_value(item1, 'pop'), 2)
self.assertNotFound(item2, 'pop')
class ContextTests(unittest.TestCase, AssertIsMixin):
......
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