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
3cd84e99
Commit
3cd84e99
authored
Mar 17, 2012
by
Chris Jerdonek
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'view-simplification' into development
parents
cae37b1f
638cbc1f
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
504 additions
and
178 deletions
+504
-178
examples/nested_context.py
+2
-2
examples/template_partial.py
+2
-2
pystache/locator.py
+71
-29
pystache/reader.py
+8
-4
pystache/renderer.py
+5
-13
pystache/view.py
+103
-27
tests/common.py
+8
-0
tests/data/non_ascii.mustache
+0
-0
tests/data/sample_view.mustache
+2
-0
tests/data/views.py
+9
-0
tests/test_context.py
+1
-11
tests/test_examples.py
+0
-6
tests/test_locator.py
+61
-17
tests/test_reader.py
+53
-3
tests/test_renderengine.py
+8
-0
tests/test_renderer.py
+3
-3
tests/test_view.py
+168
-61
No files found.
examples/nested_context.py
View file @
3cd84e99
...
...
@@ -16,4 +16,4 @@ class NestedContext(pystache.View):
return
[{
'outer'
:
'car'
}]
def
nested_context_in_view
(
self
):
return
'it works!'
if
self
.
get
(
'outer'
)
==
self
.
get
(
'inner'
)
else
''
\ No newline at end of file
return
'it works!'
if
self
.
context
.
get
(
'outer'
)
==
self
.
context
.
get
(
'inner'
)
else
''
\ No newline at end of file
examples/template_partial.py
View file @
3cd84e99
...
...
@@ -13,4 +13,4 @@ class TemplatePartial(pystache.View):
return
[{
'item'
:
'one'
},
{
'item'
:
'two'
},
{
'item'
:
'three'
}]
def
thing
(
self
):
return
self
.
get
(
'prop'
)
\ No newline at end of file
return
self
.
context
.
get
(
'prop'
)
\ No newline at end of file
pystache/locator.py
View file @
3cd84e99
...
...
@@ -30,20 +30,6 @@ class Locator(object):
self
.
template_extension
=
extension
def
_find_path
(
self
,
file_name
,
search_dirs
):
"""
Search for the given file, and return the path.
Returns None if the file is not found.
"""
for
dir_path
in
search_dirs
:
file_path
=
os
.
path
.
join
(
dir_path
,
file_name
)
if
os
.
path
.
exists
(
file_path
):
return
file_path
return
None
def
get_object_directory
(
self
,
obj
):
"""
Return the directory containing an object's defining class.
...
...
@@ -53,6 +39,9 @@ class Locator(object):
doctest that appears in a text file (rather than a Python file).
"""
if
not
hasattr
(
obj
,
'__module__'
):
return
None
module
=
sys
.
modules
[
obj
.
__module__
]
if
not
hasattr
(
module
,
'__file__'
):
...
...
@@ -63,13 +52,6 @@ class Locator(object):
return
os
.
path
.
dirname
(
path
)
def
make_file_name
(
self
,
template_name
):
file_name
=
template_name
if
self
.
template_extension
is
not
False
:
file_name
+=
os
.
path
.
extsep
+
self
.
template_extension
return
file_name
def
make_template_name
(
self
,
obj
):
"""
Return the canonical template name for an object instance.
...
...
@@ -94,17 +76,77 @@ class Locator(object):
return
re
.
sub
(
'[A-Z]'
,
repl
,
template_name
)[
1
:]
def
locate_path
(
self
,
template_name
,
search_dirs
):
def
make_file_name
(
self
,
template_name
,
template_extension
=
None
):
"""
Find and return the path to the template with the given name.
Generate and return the file name for the given template name.
Arguments:
template_extension: defaults to the instance's extension.
"""
file_name
=
self
.
make_file_name
(
template_name
)
path
=
self
.
_find_path
(
file_name
,
search_dirs
)
file_name
=
template_name
if
path
is
not
None
:
return
path
if
template_extension
is
None
:
template_extension
=
self
.
template_extension
if
template_extension
is
not
False
:
file_name
+=
os
.
path
.
extsep
+
template_extension
return
file_name
def
_find_path
(
self
,
search_dirs
,
file_name
):
"""
Search for the given file, and return the path.
Returns None if the file is not found.
"""
for
dir_path
in
search_dirs
:
file_path
=
os
.
path
.
join
(
dir_path
,
file_name
)
if
os
.
path
.
exists
(
file_path
):
return
file_path
return
None
def
_find_path_required
(
self
,
search_dirs
,
file_name
):
"""
Return the path to a template with the given file name.
"""
path
=
self
.
_find_path
(
search_dirs
,
file_name
)
if
path
is
None
:
# TODO: we should probably raise an exception of our own type.
raise
IOError
(
'Template
%
s not found in directories:
%
s'
%
(
repr
(
template_name
),
repr
(
search_dirs
)))
raise
IOError
(
'Template file
%
s not found in directories:
%
s'
%
(
repr
(
file_name
),
repr
(
search_dirs
)))
return
path
def
find_path_by_name
(
self
,
search_dirs
,
template_name
):
"""
Return the path to a template with the given name.
"""
file_name
=
self
.
make_file_name
(
template_name
)
return
self
.
_find_path_required
(
search_dirs
,
file_name
)
def
find_path_by_object
(
self
,
search_dirs
,
obj
,
file_name
=
None
):
"""
Return the path to a template associated with the given object.
"""
if
file_name
is
None
:
# TODO: should we define a make_file_name() method?
template_name
=
self
.
make_template_name
(
obj
)
file_name
=
self
.
make_file_name
(
template_name
)
dir_path
=
self
.
get_object_directory
(
obj
)
if
dir_path
is
not
None
:
search_dirs
=
[
dir_path
]
+
search_dirs
path
=
self
.
_find_path_required
(
search_dirs
,
file_name
)
return
path
pystache/reader.py
View file @
3cd84e99
...
...
@@ -42,7 +42,13 @@ class Reader(object):
self
.
decode_errors
=
decode_errors
self
.
encoding
=
encoding
def
read
(
self
,
path
):
def
unicode
(
self
,
text
,
encoding
=
None
):
if
encoding
is
None
:
encoding
=
self
.
encoding
return
unicode
(
text
,
encoding
,
self
.
decode_errors
)
def
read
(
self
,
path
,
encoding
=
None
):
"""
Read the template at the given path, and return it as a unicode string.
...
...
@@ -50,6 +56,4 @@ class Reader(object):
with
open
(
path
,
'r'
)
as
f
:
text
=
f
.
read
()
text
=
unicode
(
text
,
self
.
encoding
,
self
.
decode_errors
)
return
text
return
self
.
unicode
(
text
,
encoding
)
pystache/renderer.py
View file @
3cd84e99
...
...
@@ -190,8 +190,9 @@ class Renderer(object):
locator
=
self
.
make_locator
()
def
load_template
(
template_name
):
path
=
locator
.
locate_path
(
template_name
=
template_name
,
search_dirs
=
self
.
search_dirs
)
return
reader
.
read
(
path
)
template_path
=
locator
.
find_path_by_name
(
self
.
search_dirs
,
template_name
)
return
reader
.
read
(
template_path
)
return
load_template
...
...
@@ -263,19 +264,10 @@ class Renderer(object):
class definition.
"""
search_dirs
=
self
.
search_dirs
locator
=
self
.
make_locator
()
template_path
=
locator
.
find_path_by_object
(
self
.
search_dirs
,
obj
)
template_name
=
locator
.
make_template_name
(
obj
)
directory
=
locator
.
get_object_directory
(
obj
)
# TODO: add a unit test for the case of a None return value.
if
directory
is
not
None
:
search_dirs
=
[
directory
]
+
self
.
search_dirs
path
=
locator
.
locate_path
(
template_name
=
template_name
,
search_dirs
=
search_dirs
)
return
self
.
read
(
path
)
return
self
.
read
(
template_path
)
def
_render_string
(
self
,
template
,
*
context
,
**
kwargs
):
"""
...
...
pystache/view.py
View file @
3cd84e99
...
...
@@ -5,43 +5,59 @@ This module provides a View class.
"""
import
os.path
from
.context
import
Context
from
.locator
import
Locator
from
.locator
import
Locator
as
TemplateLocator
from
.reader
import
Reader
from
.renderer
import
Renderer
# TODO: rename this class to something else (e.g. ITemplateInfo)
class
View
(
object
):
template_name
=
None
template_path
=
None
"""
Subclass this class only if template customizations are needed.
The following attributes allow one to customize/override template
information on a per View basis. A None value means to use default
behavior and perform no customization. All attributes are initially
set to None.
Attributes:
template: the template to use, as a unicode string.
template_path: the path to the template file, relative to the
directory containing the module defining the class.
template_dir: the directory containing the template file, relative
to the directory containing the module defining the class.
template_extension: the template file extension. Defaults to "mustache".
Pass False for no extension (i.e. extensionless template files).
"""
template
=
None
template_encoding
=
None
template_path
=
None
template_directory
=
None
template_name
=
None
template_extension
=
None
template_encoding
=
None
_renderer
=
None
locator
=
Locator
()
locator
=
Template
Locator
()
def
__init__
(
self
,
template
=
None
,
context
=
None
,
partials
=
None
,
**
kwargs
):
def
__init__
(
self
,
context
=
None
):
"""
Construct a View instance.
Arguments:
partials: a custom object (e.g. dictionary) responsible for
loading partials during the rendering process. The object
should have a get() method that accepts a string and returns
the corresponding template as a string, preferably as a
unicode string. The method should return None if there is
no template with that name, or raise an exception.
"""
if
template
is
not
None
:
self
.
template
=
template
context
=
Context
.
create
(
self
,
context
,
**
kwargs
)
self
.
_partials
=
partials
context
=
Context
.
create
(
self
,
context
)
self
.
context
=
context
...
...
@@ -52,8 +68,7 @@ class View(object):
# instantiation some of the attributes on which the Renderer
# depends. This lets users set the template_extension attribute,
# etc. after View.__init__() has already been called.
renderer
=
Renderer
(
partials
=
self
.
_partials
,
file_encoding
=
self
.
template_encoding
,
renderer
=
Renderer
(
file_encoding
=
self
.
template_encoding
,
search_dirs
=
self
.
template_path
,
file_extension
=
self
.
template_extension
)
self
.
_renderer
=
renderer
...
...
@@ -98,8 +113,69 @@ class View(object):
renderer
=
self
.
_get_renderer
()
return
renderer
.
render
(
template
,
self
.
context
)
def
get
(
self
,
key
,
default
=
None
):
return
self
.
context
.
get
(
key
,
default
)
def
__str__
(
self
):
return
self
.
render
()
class
Locator
(
object
):
"""
A class for finding the template associated to a View instance.
"""
# TODO: unit test this.
def
__init__
(
self
,
search_dirs
,
template_locator
=
None
,
reader
=
None
):
if
reader
is
None
:
reader
=
Reader
()
if
template_locator
is
None
:
template_locator
=
TemplateLocator
()
self
.
reader
=
reader
self
.
search_dirs
=
search_dirs
self
.
template_locator
=
template_locator
def
get_relative_template_location
(
self
,
view
):
"""
Return the relative template path as a (dir, file_name) pair.
"""
if
view
.
template_path
is
not
None
:
return
os
.
path
.
split
(
view
.
template_path
)
template_dir
=
view
.
template_directory
# Otherwise, we don't know the directory.
template_name
=
(
view
.
template_name
if
view
.
template_name
is
not
None
else
self
.
template_locator
.
make_template_name
(
view
))
file_name
=
self
.
template_locator
.
make_file_name
(
template_name
,
view
.
template_extension
)
return
(
template_dir
,
file_name
)
def
get_template_path
(
self
,
view
):
"""
Return the path to the view's associated template.
"""
dir_path
,
file_name
=
self
.
get_relative_template_location
(
view
)
if
dir_path
is
None
:
# Then we need to search for the path.
path
=
self
.
template_locator
.
find_path_by_object
(
self
.
search_dirs
,
view
,
file_name
=
file_name
)
else
:
obj_dir
=
self
.
template_locator
.
get_object_directory
(
view
)
path
=
os
.
path
.
join
(
obj_dir
,
dir_path
,
file_name
)
return
path
def
get_template
(
self
,
view
):
"""
Return the unicode template string associated with a view.
"""
if
view
.
template
is
not
None
:
return
self
.
reader
.
unicode
(
view
.
template
,
view
.
template_encoding
)
path
=
self
.
get_template_path
(
view
)
return
self
.
reader
.
read
(
path
,
view
.
template_encoding
)
tests/common.py
View file @
3cd84e99
...
...
@@ -27,3 +27,11 @@ def assert_strings(test_case, actual, expected):
test_case
.
assertEquals
(
actual
,
expected
,
message
)
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
)))
tests/data/nonascii.mustache
→
tests/data/non
_
ascii.mustache
View file @
3cd84e99
File moved
tests/data/sample_view.mustache
0 → 100644
View file @
3cd84e99
ascii: abc
\ No newline at end of file
tests/data/
template
s.py
→
tests/data/
view
s.py
View file @
3cd84e99
# coding: utf-8
from
pystache.view
import
View
class
SayHello
(
object
):
def
to
(
self
):
return
"World"
class
SampleView
(
View
):
pass
class
NonAscii
(
View
):
pass
tests/test_context.py
View file @
3cd84e99
...
...
@@ -11,7 +11,7 @@ import unittest
from
pystache.context
import
_NOT_FOUND
from
pystache.context
import
_get_value
from
pystache.context
import
Context
from
tests.common
import
AssertIsMixin
class
SimpleObject
(
object
):
...
...
@@ -39,16 +39,6 @@ class DictLike(object):
return
self
.
_dict
[
key
]
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
GetValueTests
(
unittest
.
TestCase
,
AssertIsMixin
):
"""Test context._get_value()."""
...
...
tests/test_examples.py
View file @
3cd84e99
...
...
@@ -37,12 +37,6 @@ class TestView(unittest.TestCase):
def
test_literal
(
self
):
self
.
assertEquals
(
Unescaped
()
.
render
(),
"<h1>Bear > Shark</h1>"
)
def
test_literal_sigil
(
self
):
view
=
Escaped
(
template
=
"<h1>{{& thing}}</h1>"
,
context
=
{
'thing'
:
'Bear > Giraffe'
})
self
.
assertEquals
(
view
.
render
(),
"<h1>Bear > Giraffe</h1>"
)
def
test_template_partial
(
self
):
self
.
assertEquals
(
TemplatePartial
()
.
render
(),
"""<h1>Welcome</h1>
Again, Welcome!"""
)
...
...
tests/test_locator.py
View file @
3cd84e99
...
...
@@ -5,6 +5,7 @@ Contains locator.py unit tests.
"""
from
datetime
import
datetime
import
os
import
sys
import
unittest
...
...
@@ -13,12 +14,11 @@ from pystache.locator import Locator
from
pystache.reader
import
Reader
from
.common
import
DATA_DIR
from
data.views
import
SayHello
class
LocatorTests
(
unittest
.
TestCase
):
search_dirs
=
'examples'
def
_locator
(
self
):
return
Locator
(
search_dirs
=
DATA_DIR
)
...
...
@@ -36,12 +36,20 @@ class LocatorTests(unittest.TestCase):
def
test_get_object_directory
(
self
):
locator
=
Locator
()
reader
=
Reader
()
actual
=
locator
.
get_object_directory
(
reader
)
obj
=
SayHello
()
actual
=
locator
.
get_object_directory
(
obj
)
self
.
assertEquals
(
actual
,
os
.
path
.
abspath
(
DATA_DIR
))
def
test_get_object_directory__not_hasattr_module
(
self
):
locator
=
Locator
()
expected
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
os
.
pardir
,
'pystache'
)
obj
=
datetime
(
2000
,
1
,
1
)
self
.
assertFalse
(
hasattr
(
obj
,
'__module__'
))
self
.
assertEquals
(
locator
.
get_object_directory
(
obj
),
None
)
self
.
assertEquals
(
os
.
path
.
normpath
(
actual
),
os
.
path
.
normpath
(
expected
))
self
.
assertFalse
(
hasattr
(
None
,
'__module__'
))
self
.
assertEquals
(
locator
.
get_object_directory
(
None
),
None
)
def
test_make_file_name
(
self
):
locator
=
Locator
()
...
...
@@ -55,21 +63,26 @@ class LocatorTests(unittest.TestCase):
locator
.
template_extension
=
''
self
.
assertEquals
(
locator
.
make_file_name
(
'foo'
),
'foo.'
)
def
test_
locate_path
(
self
):
def
test_
make_file_name__template_extension_argument
(
self
):
locator
=
Locator
()
path
=
locator
.
locate_path
(
'simple'
,
search_dirs
=
[
'examples'
])
self
.
assertEquals
(
locator
.
make_file_name
(
'foo'
,
template_extension
=
'bar'
),
'foo.bar'
)
def
test_find_path_by_name
(
self
):
locator
=
Locator
()
path
=
locator
.
find_path_by_name
(
search_dirs
=
[
'examples'
],
template_name
=
'simple'
)
self
.
assertEquals
(
os
.
path
.
basename
(
path
),
'simple.mustache'
)
def
test_
locate_path
__using_list_of_paths
(
self
):
def
test_
find_path_by_name
__using_list_of_paths
(
self
):
locator
=
Locator
()
path
=
locator
.
locate_path
(
'simple'
,
search_dirs
=
[
'doesnt_exist'
,
'examples'
]
)
path
=
locator
.
find_path_by_name
(
search_dirs
=
[
'doesnt_exist'
,
'examples'
],
template_name
=
'simple'
)
self
.
assertTrue
(
path
)
def
test_
locate_path
__precedence
(
self
):
def
test_
find_path_by_name
__precedence
(
self
):
"""
Test the order in which
locate_path
() searches directories.
Test the order in which
find_path_by_name
() searches directories.
"""
locator
=
Locator
()
...
...
@@ -77,19 +90,50 @@ class LocatorTests(unittest.TestCase):
dir1
=
DATA_DIR
dir2
=
os
.
path
.
join
(
DATA_DIR
,
'locator'
)
self
.
assertTrue
(
locator
.
locate_path
(
'duplicate'
,
search_dirs
=
[
dir1
]
))
self
.
assertTrue
(
locator
.
locate_path
(
'duplicate'
,
search_dirs
=
[
dir2
]
))
self
.
assertTrue
(
locator
.
find_path_by_name
(
search_dirs
=
[
dir1
],
template_name
=
'duplicate'
))
self
.
assertTrue
(
locator
.
find_path_by_name
(
search_dirs
=
[
dir2
],
template_name
=
'duplicate'
))
path
=
locator
.
locate_path
(
'duplicate'
,
search_dirs
=
[
dir2
,
dir1
]
)
path
=
locator
.
find_path_by_name
(
search_dirs
=
[
dir2
,
dir1
],
template_name
=
'duplicate'
)
dirpath
=
os
.
path
.
dirname
(
path
)
dirname
=
os
.
path
.
split
(
dirpath
)[
-
1
]
self
.
assertEquals
(
dirname
,
'locator'
)
def
test_locate_path__non_existent_template_fails
(
self
):
def
test_find_path_by_name__non_existent_template_fails
(
self
):
locator
=
Locator
()
self
.
assertRaises
(
IOError
,
locator
.
find_path_by_name
,
search_dirs
=
[],
template_name
=
'doesnt_exist'
)
def
test_find_path_by_object
(
self
):
locator
=
Locator
()
obj
=
SayHello
()
actual
=
locator
.
find_path_by_object
(
search_dirs
=
[],
obj
=
obj
,
file_name
=
'sample_view.mustache'
)
expected
=
os
.
path
.
abspath
(
os
.
path
.
join
(
DATA_DIR
,
'sample_view.mustache'
))
self
.
assertEquals
(
actual
,
expected
)
def
test_find_path_by_object__none_file_name
(
self
):
locator
=
Locator
()
self
.
assertRaises
(
IOError
,
locator
.
locate_path
,
'doesnt_exist'
,
search_dirs
=
[])
obj
=
SayHello
()
actual
=
locator
.
find_path_by_object
(
search_dirs
=
[],
obj
=
obj
)
expected
=
os
.
path
.
abspath
(
os
.
path
.
join
(
DATA_DIR
,
'say_hello.mustache'
))
self
.
assertEquals
(
actual
,
expected
)
def
test_find_path_by_object__none_object_directory
(
self
):
locator
=
Locator
()
obj
=
None
self
.
assertEquals
(
None
,
locator
.
get_object_directory
(
obj
))
actual
=
locator
.
find_path_by_object
(
search_dirs
=
[
DATA_DIR
],
obj
=
obj
,
file_name
=
'say_hello.mustache'
)
expected
=
os
.
path
.
join
(
DATA_DIR
,
'say_hello.mustache'
)
self
.
assertEquals
(
actual
,
expected
)
def
test_make_template_name
(
self
):
"""
...
...
tests/test_reader.py
View file @
3cd84e99
...
...
@@ -36,6 +36,45 @@ class ReaderTestCase(unittest.TestCase):
reader
=
Reader
(
encoding
=
'foo'
)
self
.
assertEquals
(
reader
.
encoding
,
'foo'
)
def
test_unicode
(
self
):
"""
Test unicode(): default values.
"""
reader
=
Reader
()
actual
=
reader
.
unicode
(
"foo"
)
self
.
assertEquals
(
type
(
actual
),
unicode
)
self
.
assertEquals
(
actual
,
u"foo"
)
def
test_unicode__encoding_attribute
(
self
):
"""
Test unicode(): encoding attribute.
"""
reader
=
Reader
()
non_ascii
=
u'é'
.
encode
(
'utf-8'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
unicode
,
non_ascii
)
reader
.
encoding
=
'utf-8'
self
.
assertEquals
(
reader
.
unicode
(
non_ascii
),
u"é"
)
def
test_unicode__encoding_argument
(
self
):
"""
Test unicode(): encoding argument.
"""
reader
=
Reader
()
non_ascii
=
u'é'
.
encode
(
'utf-8'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
unicode
,
non_ascii
)
self
.
assertEquals
(
reader
.
unicode
(
non_ascii
,
encoding
=
'utf-8'
),
u'é'
)
def
test_read
(
self
):
"""
Test read().
...
...
@@ -55,25 +94,36 @@ class ReaderTestCase(unittest.TestCase):
contents
=
reader
.
read
(
path
)
self
.
assertEqual
(
type
(
contents
),
unicode
)
def
test_read__encoding
(
self
):
def
test_read__encoding
__attribute
(
self
):
"""
Test read(): encoding attribute respected.
"""
reader
=
Reader
()
path
=
self
.
_get_path
(
'nonascii.mustache'
)
path
=
self
.
_get_path
(
'non
_
ascii.mustache'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
reader
.
encoding
=
'utf-8'
self
.
assertEquals
(
reader
.
read
(
path
),
u'non-ascii: é'
)
def
test_read__encoding__argument
(
self
):
"""
Test read(): encoding argument respected.
"""
reader
=
Reader
()
path
=
self
.
_get_path
(
'non_ascii.mustache'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
self
.
assertEquals
(
reader
.
read
(
path
,
encoding
=
'utf-8'
),
u'non-ascii: é'
)
def
test_get__decode_errors
(
self
):
"""
Test get(): decode_errors attribute.
"""
reader
=
Reader
()
path
=
self
.
_get_path
(
'nonascii.mustache'
)
path
=
self
.
_get_path
(
'non
_
ascii.mustache'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
reader
.
decode_errors
=
'replace'
...
...
tests/test_renderengine.py
View file @
3cd84e99
...
...
@@ -92,6 +92,14 @@ class RenderTests(unittest.TestCase):
self
.
_assert_render
(
'BAR'
,
'{{{foo}}}'
,
{
'foo'
:
'bar'
},
engine
=
engine
)
def
test_literal__sigil
(
self
):
template
=
"<h1>{{& thing}}</h1>"
context
=
{
'thing'
:
'Bear > Giraffe'
}
expected
=
"<h1>Bear > Giraffe</h1>"
self
.
_assert_render
(
expected
,
template
,
context
)
def
test__escape
(
self
):
"""
Test that render() uses the escape attribute.
...
...
tests/test_renderer.py
View file @
3cd84e99
...
...
@@ -16,7 +16,7 @@ from pystache.renderer import Renderer
from
pystache.locator
import
Locator
from
.common
import
get_data_path
from
.data.
template
s
import
SayHello
from
.data.
view
s
import
SayHello
class
RendererInitTestCase
(
unittest
.
TestCase
):
...
...
@@ -200,7 +200,7 @@ class RendererTestCase(unittest.TestCase):
self
.
assertEquals
(
type
(
actual
),
unicode
)
def
test_read__file_encoding
(
self
):
filename
=
'nonascii.mustache'
filename
=
'non
_
ascii.mustache'
renderer
=
Renderer
()
renderer
.
file_encoding
=
'ascii'
...
...
@@ -211,7 +211,7 @@ class RendererTestCase(unittest.TestCase):
self
.
assertEquals
(
actual
,
u'non-ascii: é'
)
def
test_read__decode_errors
(
self
):
filename
=
'nonascii.mustache'
filename
=
'non
_
ascii.mustache'
renderer
=
Renderer
()
self
.
assertRaises
(
UnicodeDecodeError
,
self
.
_read
,
renderer
,
filename
)
...
...
tests/test_view.py
View file @
3cd84e99
# coding: utf-8
"""
Unit tests of view.py.
"""
import
os.path
import
unittest
import
pystache
from
examples.simple
import
Simple
from
examples.complex_view
import
ComplexView
from
examples.lambdas
import
Lambdas
from
examples.inverted
import
Inverted
,
InvertedLists
from
pystache.reader
import
Reader
from
pystache.view
import
View
from
pystache.view
import
Locator
as
ViewLocator
from
.common
import
AssertIsMixin
from
.common
import
DATA_DIR
from
.data.views
import
SampleView
from
.data.views
import
NonAscii
class
Thing
(
object
):
...
...
@@ -25,39 +38,6 @@ class ViewTestCase(unittest.TestCase):
view
=
TestView
()
self
.
assertEquals
(
view
.
template
,
"foo"
)
def
test_init__kwargs_does_not_modify_context
(
self
):
"""
Test that passing **kwargs does not modify the passed context.
"""
context
=
{
"foo"
:
"bar"
}
view
=
View
(
context
=
context
,
fuzz
=
"buzz"
)
self
.
assertEquals
(
context
,
{
"foo"
:
"bar"
})
def
test_basic
(
self
):
view
=
Simple
(
"Hi {{thing}}!"
,
{
'thing'
:
'world'
})
self
.
assertEquals
(
view
.
render
(),
"Hi world!"
)
def
test_kwargs
(
self
):
view
=
Simple
(
"Hi {{thing}}!"
,
thing
=
'world'
)
self
.
assertEquals
(
view
.
render
(),
"Hi world!"
)
def
test_render
(
self
):
view
=
Simple
(
thing
=
'world'
)
self
.
assertEquals
(
view
.
render
(),
"Hi world!"
)
def
test_render__partials
(
self
):
"""
Test passing partials to View.__init__().
"""
template
=
"{{>partial}}"
partials
=
{
"partial"
:
"Loaded from dictionary"
}
view
=
Simple
(
template
=
template
,
partials
=
partials
)
actual
=
view
.
render
()
self
.
assertEquals
(
actual
,
"Loaded from dictionary"
)
def
test_template_path
(
self
):
"""
Test that View.template_path is respected.
...
...
@@ -88,24 +68,6 @@ class ViewTestCase(unittest.TestCase):
view
.
template_path
=
"examples"
self
.
assertEquals
(
view
.
render
(),
"Partial: No tags..."
)
def
test_template_load_from_multiple_path
(
self
):
path
=
Simple
.
template_path
Simple
.
template_path
=
(
'examples/nowhere'
,
'examples'
,)
try
:
view
=
Simple
(
thing
=
'world'
)
self
.
assertEquals
(
view
.
render
(),
"Hi world!"
)
finally
:
Simple
.
template_path
=
path
def
test_template_load_from_multiple_path_fail
(
self
):
path
=
Simple
.
template_path
Simple
.
template_path
=
(
'examples/nowhere'
,)
try
:
view
=
Simple
(
thing
=
'world'
)
self
.
assertRaises
(
IOError
,
view
.
render
)
finally
:
Simple
.
template_path
=
path
def
test_basic_method_calls
(
self
):
view
=
Simple
()
self
.
assertEquals
(
view
.
render
(),
"Hi pizza!"
)
...
...
@@ -115,13 +77,6 @@ class ViewTestCase(unittest.TestCase):
view
.
thing
=
'Chris'
self
.
assertEquals
(
view
.
render
(),
"Hi Chris!"
)
def
test_view_instances_as_attributes
(
self
):
other
=
Simple
(
name
=
'chris'
)
other
.
template
=
'{{name}}'
view
=
Simple
()
view
.
thing
=
other
self
.
assertEquals
(
view
.
render
(),
"Hi chris!"
)
def
test_complex
(
self
):
self
.
assertEquals
(
ComplexView
()
.
render
(),
"""<h1>Colors</h1><ul><li><strong>red</strong></li><li><a href="#Green">green</a></li><li><a href="#Blue">blue</a></li></ul>"""
)
...
...
@@ -168,5 +123,157 @@ class ViewTestCase(unittest.TestCase):
view
=
InvertedLists
()
self
.
assertEquals
(
view
.
render
(),
"""one, two, three, empty list"""
)
if
__name__
==
'__main__'
:
unittest
.
main
()
class
LocatorTests
(
unittest
.
TestCase
,
AssertIsMixin
):
def
_make_locator
(
self
):
locator
=
ViewLocator
(
search_dirs
=
[
DATA_DIR
])
return
locator
# TODO: fully test constructor.
def
test_init__reader
(
self
):
reader
=
"reader"
# in practice, this is a reader instance.
locator
=
ViewLocator
(
search_dirs
=
None
,
template_locator
=
None
,
reader
=
reader
)
self
.
assertIs
(
locator
.
reader
,
reader
)
def
_assert_template_location
(
self
,
view
,
expected
):
locator
=
self
.
_make_locator
()
actual
=
locator
.
get_relative_template_location
(
view
)
self
.
assertEquals
(
actual
,
expected
)
def
test_get_relative_template_location
(
self
):
"""
Test get_relative_template_location(): default behavior (no attributes set).
"""
view
=
SampleView
()
self
.
_assert_template_location
(
view
,
(
None
,
'sample_view.mustache'
))
def
test_get_relative_template_location__template_path__file_name_only
(
self
):
"""
Test get_relative_template_location(): template_path attribute.
"""
view
=
SampleView
()
view
.
template_path
=
'template.txt'
self
.
_assert_template_location
(
view
,
(
''
,
'template.txt'
))
def
test_get_relative_template_location__template_path__file_name_with_directory
(
self
):
"""
Test get_relative_template_location(): template_path attribute.
"""
view
=
SampleView
()
view
.
template_path
=
'foo/bar/template.txt'
self
.
_assert_template_location
(
view
,
(
'foo/bar'
,
'template.txt'
))
def
test_get_relative_template_location__template_directory
(
self
):
"""
Test get_relative_template_location(): template_directory attribute.
"""
view
=
SampleView
()
view
.
template_directory
=
'foo'
self
.
_assert_template_location
(
view
,
(
'foo'
,
'sample_view.mustache'
))
def
test_get_relative_template_location__template_name
(
self
):
"""
Test get_relative_template_location(): template_name attribute.
"""
view
=
SampleView
()
view
.
template_name
=
'new_name'
self
.
_assert_template_location
(
view
,
(
None
,
'new_name.mustache'
))
def
test_get_relative_template_location__template_extension
(
self
):
"""
Test get_relative_template_location(): template_extension attribute.
"""
view
=
SampleView
()
view
.
template_extension
=
'txt'
self
.
_assert_template_location
(
view
,
(
None
,
'sample_view.txt'
))
def
test_get_template_path__with_directory
(
self
):
"""
Test get_template_path() with a view that has a directory specified.
"""
locator
=
self
.
_make_locator
()
view
=
SampleView
()
view
.
template_path
=
'foo/bar.txt'
self
.
assertTrue
(
locator
.
get_relative_template_location
(
view
)[
0
]
is
not
None
)
actual
=
locator
.
get_template_path
(
view
)
expected
=
os
.
path
.
abspath
(
os
.
path
.
join
(
DATA_DIR
,
'foo/bar.txt'
))
self
.
assertEquals
(
actual
,
expected
)
def
test_get_template_path__without_directory
(
self
):
"""
Test get_template_path() with a view that doesn't have a directory specified.
"""
locator
=
self
.
_make_locator
()
view
=
SampleView
()
self
.
assertTrue
(
locator
.
get_relative_template_location
(
view
)[
0
]
is
None
)
actual
=
locator
.
get_template_path
(
view
)
expected
=
os
.
path
.
abspath
(
os
.
path
.
join
(
DATA_DIR
,
'sample_view.mustache'
))
self
.
assertEquals
(
actual
,
expected
)
def
_assert_get_template
(
self
,
view
,
expected
):
locator
=
self
.
_make_locator
()
actual
=
locator
.
get_template
(
view
)
self
.
assertEquals
(
type
(
actual
),
unicode
)
self
.
assertEquals
(
actual
,
expected
)
def
test_get_template
(
self
):
"""
Test get_template(): default behavior (no attributes set).
"""
view
=
SampleView
()
self
.
_assert_get_template
(
view
,
u"ascii: abc"
)
def
test_get_template__template
(
self
):
"""
Test get_template(): template attribute.
"""
view
=
SampleView
()
view
.
template
=
'foo'
self
.
_assert_get_template
(
view
,
'foo'
)
def
test_get_template__template__template_encoding
(
self
):
"""
Test get_template(): template attribute with template encoding attribute.
"""
view
=
SampleView
()
view
.
template
=
u'é'
.
encode
(
'utf-8'
)
self
.
assertRaises
(
UnicodeDecodeError
,
self
.
_assert_get_template
,
view
,
'foo'
)
view
.
template_encoding
=
'utf-8'
self
.
_assert_get_template
(
view
,
u'é'
)
def
test_get_template__template_encoding
(
self
):
"""
Test get_template(): template_encoding attribute.
"""
view
=
NonAscii
()
self
.
assertRaises
(
UnicodeDecodeError
,
self
.
_assert_get_template
,
view
,
'foo'
)
view
.
template_encoding
=
'utf-8'
self
.
_assert_get_template
(
view
,
u"non-ascii: é"
)
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