Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pystache_custom
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
pystache_custom
Commits
4121be33
Commit
4121be33
authored
Dec 16, 2011
by
Chris Jerdonek
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More progress on context module: defined and tested context._get_item().
parent
eb736a1c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
215 additions
and
6 deletions
+215
-6
pystache/context.py
+68
-4
tests/test_context.py
+147
-2
No files found.
pystache/context.py
View file @
4121be33
...
...
@@ -5,6 +5,55 @@ Defines a Context class to represent mustache(5)'s notion of context.
"""
# We use this private global variable as a return value to represent a key
# not being found on lookup. This lets us distinguish the case of a key's
# value being None with the case of a key not being found -- without having
# to rely on exceptions (e.g. KeyError) for flow control.
_NOT_FOUND
=
object
()
# TODO: share code with template.check_callable().
def
_is_callable
(
obj
):
return
hasattr
(
obj
,
'__call__'
)
def
_get_item
(
obj
,
key
):
"""
Look up the given key in the given object, and return the value.
The obj argument should satisfy the same conditions as those described
in Context.__init__'s() docstring. The behavior of this method is
undefined if obj is None.
The rules for querying are the same as the rules described in
Context.get()'s docstring for a single item.
Returns _NOT_FOUND if the key is not found.
"""
if
hasattr
(
obj
,
'__getitem__'
):
# We do a membership test to avoid using exceptions for flow
# control. In addition, we call __contains__() explicitly as
# opposed to using the membership operator "in" to avoid
# triggering the following Python fallback behavior:
#
# For objects that don’t define __contains__(), the membership test
# first tries iteration via __iter__(), then the old sequence
# iteration protocol via __getitem__()....
#
# (from http://docs.python.org/reference/datamodel.html#object.__contains__ )
if
obj
.
__contains__
(
key
):
return
obj
[
key
]
elif
hasattr
(
obj
,
key
):
attr
=
getattr
(
obj
,
key
)
if
_is_callable
(
attr
):
return
attr
()
return
attr
return
_NOT_FOUND
class
Context
(
object
):
...
...
@@ -33,6 +82,19 @@ class Context(object):
(2) If they implement __getitem__, a KeyError should be raised
if __getitem__ is called on a missing key.
For efficiency, objects should implement __contains__() for more
efficient membership testing. From the Python documentation--
For objects that don’t define __contains__(), the membership test
first tries iteration via __iter__(), then the old sequence
iteration protocol via __getitem__()....
(from http://docs.python.org/reference/datamodel.html#object.__contains__ )
Failing to implement __contains__() will cause undefined behavior.
on any key for which __getitem__() raises an exception [TODO:
also need to take __iter__() into account]....
"""
self
.
stack
=
list
(
obj
)
...
...
@@ -51,10 +113,12 @@ class Context(object):
"""
for
obj
in
reversed
(
self
.
stack
):
try
:
return
obj
[
key
]
except
KeyError
:
pass
val
=
_get_item
(
obj
,
key
)
if
val
is
_NOT_FOUND
:
continue
# Otherwise, the key was found.
return
val
# Otherwise, no item in the stack contained the key.
return
default
...
...
tests/test_context.py
View file @
4121be33
...
...
@@ -7,10 +7,131 @@ Unit tests of context.py.
import
unittest
from
pystache.context
import
_NOT_FOUND
from
pystache.context
import
_get_item
from
pystache.context
import
Context
class
ContextTestCase
(
unittest
.
TestCase
):
class
TestCase
(
unittest
.
TestCase
):
"""A TestCase class with support for assertIs()."""
# 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__()."""
def
__init__
(
self
):
self
.
foo
=
"bar"
def
foo_callable
(
self
):
return
"called..."
class
MappingObject
(
object
):
"""A sample class that implements __getitem__() and __contains__()."""
def
__init__
(
self
):
self
.
_dict
=
{
'foo'
:
'bar'
}
self
.
fuzz
=
'buzz'
def
__contains__
(
self
,
key
):
return
key
in
self
.
_dict
def
__getitem__
(
self
,
key
):
return
self
.
_dict
[
key
]
class
GetItemTestCase
(
TestCase
):
"""Test context._get_item()."""
def
assertNotFound
(
self
,
obj
,
key
):
self
.
assertIs
(
_get_item
(
obj
,
key
),
_NOT_FOUND
)
### Case: obj 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"
)
def
test_dictionary__key_missing
(
self
):
"""
Test getting a missing key from a dictionary.
"""
obj
=
{}
self
.
assertNotFound
(
obj
,
"missing"
)
### Case: obj does not implement __getitem__().
def
test_object__attribute_present
(
self
):
"""
Test getting an attribute from an object.
"""
obj
=
SimpleObject
()
self
.
assertEquals
(
_get_item
(
obj
,
"foo"
),
"bar"
)
def
test_object__attribute_missing
(
self
):
"""
Test getting a missing attribute from an object.
"""
obj
=
SimpleObject
()
self
.
assertNotFound
(
obj
,
"missing"
)
### Case: obj implements __getitem__() (i.e. a "mapping object").
def
test_mapping__key_present
(
self
):
"""
Test getting a key from a mapping object.
"""
obj
=
MappingObject
()
self
.
assertEquals
(
_get_item
(
obj
,
"foo"
),
"bar"
)
def
test_mapping__key_missing
(
self
):
"""
Test getting a missing key from a mapping object.
"""
obj
=
MappingObject
()
self
.
assertNotFound
(
obj
,
"missing"
)
def
test_mapping__get_attribute
(
self
):
"""
Test getting an attribute from a mapping object.
"""
obj
=
MappingObject
()
self
.
assertEquals
(
obj
.
fuzz
,
"buzz"
)
self
.
assertNotFound
(
obj
,
"fuzz"
)
def
test_mapping_object__not_implementing_contains
(
self
):
"""
Test querying a mapping object that doesn't define __contains__().
"""
class
Sample
(
object
):
def
__getitem__
(
self
,
key
):
return
"bar"
obj
=
Sample
()
self
.
assertRaises
(
AttributeError
,
_get_item
,
obj
,
"foo"
)
class
ContextTestCase
(
TestCase
):
"""
Test the Context class.
...
...
@@ -24,7 +145,7 @@ class ContextTestCase(unittest.TestCase):
"""
context
=
Context
()
def
test_init__
no
_elements
(
self
):
def
test_init__
many
_elements
(
self
):
"""
Check that passing more than two items to __init__() raises no exception.
...
...
@@ -39,6 +160,14 @@ class ContextTestCase(unittest.TestCase):
context
=
Context
()
self
.
assertTrue
(
context
.
get
(
"foo"
)
is
None
)
def
test_get__dictionary_methods_not_queried
(
self
):
"""
Test getting a missing key.
"""
context
=
Context
()
#self.assertEquals(context.get("keys"), 2)
def
test_get__default
(
self
):
"""
Test that get() respects the default value .
...
...
@@ -71,3 +200,19 @@ class ContextTestCase(unittest.TestCase):
context
=
Context
({
"fuzz"
:
"buzz"
},
{
"foo"
:
"bar"
})
self
.
assertEquals
(
context
.
get
(
"fuzz"
),
"buzz"
)
def
test_get__object_attribute
(
self
):
"""
Test that object attributes are queried.
"""
context
=
Context
(
SimpleObject
())
self
.
assertEquals
(
context
.
get
(
"foo"
),
"bar"
)
def
test_get__object_callable
(
self
):
"""
Test that object callables are queried.
"""
context
=
Context
(
SimpleObject
())
#self.assertEquals(context.get("foo_callable"), "called...")
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment