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
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
506 additions
and
180 deletions
+506
-180
examples/nested_context.py
+4
-4
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
...
@@ -11,9 +11,9 @@ class NestedContext(pystache.View):
...
@@ -11,9 +11,9 @@ class NestedContext(pystache.View):
def
derp
(
self
):
def
derp
(
self
):
return
[{
'inner'
:
'car'
}]
return
[{
'inner'
:
'car'
}]
def
herp
(
self
):
def
herp
(
self
):
return
[{
'outer'
:
'car'
}]
return
[{
'outer'
:
'car'
}]
def
nested_context_in_view
(
self
):
def
nested_context_in_view
(
self
):
return
'it works!'
if
self
.
get
(
'outer'
)
==
self
.
get
(
'inner'
)
else
''
return
'it works!'
if
self
.
context
.
get
(
'outer'
)
==
self
.
context
.
get
(
'inner'
)
else
''
\ No newline at end of file
\ No newline at end of file
examples/template_partial.py
View file @
3cd84e99
...
@@ -13,4 +13,4 @@ class TemplatePartial(pystache.View):
...
@@ -13,4 +13,4 @@ class TemplatePartial(pystache.View):
return
[{
'item'
:
'one'
},
{
'item'
:
'two'
},
{
'item'
:
'three'
}]
return
[{
'item'
:
'one'
},
{
'item'
:
'two'
},
{
'item'
:
'three'
}]
def
thing
(
self
):
def
thing
(
self
):
return
self
.
get
(
'prop'
)
return
self
.
context
.
get
(
'prop'
)
\ No newline at end of file
\ No newline at end of file
pystache/locator.py
View file @
3cd84e99
...
@@ -30,20 +30,6 @@ class Locator(object):
...
@@ -30,20 +30,6 @@ class Locator(object):
self
.
template_extension
=
extension
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
):
def
get_object_directory
(
self
,
obj
):
"""
"""
Return the directory containing an object's defining class.
Return the directory containing an object's defining class.
...
@@ -53,6 +39,9 @@ class Locator(object):
...
@@ -53,6 +39,9 @@ class Locator(object):
doctest that appears in a text file (rather than a Python file).
doctest that appears in a text file (rather than a Python file).
"""
"""
if
not
hasattr
(
obj
,
'__module__'
):
return
None
module
=
sys
.
modules
[
obj
.
__module__
]
module
=
sys
.
modules
[
obj
.
__module__
]
if
not
hasattr
(
module
,
'__file__'
):
if
not
hasattr
(
module
,
'__file__'
):
...
@@ -63,13 +52,6 @@ class Locator(object):
...
@@ -63,13 +52,6 @@ class Locator(object):
return
os
.
path
.
dirname
(
path
)
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
):
def
make_template_name
(
self
,
obj
):
"""
"""
Return the canonical template name for an object instance.
Return the canonical template name for an object instance.
...
@@ -94,17 +76,77 @@ class Locator(object):
...
@@ -94,17 +76,77 @@ class Locator(object):
return
re
.
sub
(
'[A-Z]'
,
repl
,
template_name
)[
1
:]
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
):
"""
Generate and return the file name for the given template name.
Arguments:
template_extension: defaults to the instance's extension.
"""
"""
Find and return the path to the template with the given name.
file_name
=
template_name
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 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
)
file_name
=
self
.
make_file_name
(
template_name
)
path
=
self
.
_find_path
(
file_name
,
search_dirs
)
if
path
is
not
None
:
return
self
.
_find_path_required
(
search_dirs
,
file_name
)
return
path
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
)
# TODO: we should probably raise an exception of our own type.
return
path
raise
IOError
(
'Template
%
s not found in directories:
%
s'
%
(
repr
(
template_name
),
repr
(
search_dirs
)))
pystache/reader.py
View file @
3cd84e99
...
@@ -42,7 +42,13 @@ class Reader(object):
...
@@ -42,7 +42,13 @@ class Reader(object):
self
.
decode_errors
=
decode_errors
self
.
decode_errors
=
decode_errors
self
.
encoding
=
encoding
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.
Read the template at the given path, and return it as a unicode string.
...
@@ -50,6 +56,4 @@ class Reader(object):
...
@@ -50,6 +56,4 @@ class Reader(object):
with
open
(
path
,
'r'
)
as
f
:
with
open
(
path
,
'r'
)
as
f
:
text
=
f
.
read
()
text
=
f
.
read
()
text
=
unicode
(
text
,
self
.
encoding
,
self
.
decode_errors
)
return
self
.
unicode
(
text
,
encoding
)
return
text
pystache/renderer.py
View file @
3cd84e99
...
@@ -190,8 +190,9 @@ class Renderer(object):
...
@@ -190,8 +190,9 @@ class Renderer(object):
locator
=
self
.
make_locator
()
locator
=
self
.
make_locator
()
def
load_template
(
template_name
):
def
load_template
(
template_name
):
path
=
locator
.
locate_path
(
template_name
=
template_name
,
search_dirs
=
self
.
search_dirs
)
template_path
=
locator
.
find_path_by_name
(
self
.
search_dirs
,
template_name
)
return
reader
.
read
(
path
)
return
reader
.
read
(
template_path
)
return
load_template
return
load_template
...
@@ -263,19 +264,10 @@ class Renderer(object):
...
@@ -263,19 +264,10 @@ class Renderer(object):
class definition.
class definition.
"""
"""
search_dirs
=
self
.
search_dirs
locator
=
self
.
make_locator
()
locator
=
self
.
make_locator
()
template_path
=
locator
.
find_path_by_object
(
self
.
search_dirs
,
obj
)
template_name
=
locator
.
make_template_name
(
obj
)
return
self
.
read
(
template_path
)
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
)
def
_render_string
(
self
,
template
,
*
context
,
**
kwargs
):
def
_render_string
(
self
,
template
,
*
context
,
**
kwargs
):
"""
"""
...
...
pystache/view.py
View file @
3cd84e99
...
@@ -5,43 +5,59 @@ This module provides a View class.
...
@@ -5,43 +5,59 @@ This module provides a View class.
"""
"""
import
os.path
from
.context
import
Context
from
.context
import
Context
from
.locator
import
Locator
from
.locator
import
Locator
as
TemplateLocator
from
.reader
import
Reader
from
.renderer
import
Renderer
from
.renderer
import
Renderer
# TODO: rename this class to something else (e.g. ITemplateInfo)
class
View
(
object
):
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
=
None
template_encoding
=
None
template_path
=
None
template_directory
=
None
template_name
=
None
template_extension
=
None
template_extension
=
None
template_encoding
=
None
_renderer
=
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.
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
:
context
=
Context
.
create
(
self
,
context
)
self
.
template
=
template
context
=
Context
.
create
(
self
,
context
,
**
kwargs
)
self
.
_partials
=
partials
self
.
context
=
context
self
.
context
=
context
...
@@ -52,8 +68,7 @@ class View(object):
...
@@ -52,8 +68,7 @@ class View(object):
# instantiation some of the attributes on which the Renderer
# instantiation some of the attributes on which the Renderer
# depends. This lets users set the template_extension attribute,
# depends. This lets users set the template_extension attribute,
# etc. after View.__init__() has already been called.
# etc. after View.__init__() has already been called.
renderer
=
Renderer
(
partials
=
self
.
_partials
,
renderer
=
Renderer
(
file_encoding
=
self
.
template_encoding
,
file_encoding
=
self
.
template_encoding
,
search_dirs
=
self
.
template_path
,
search_dirs
=
self
.
template_path
,
file_extension
=
self
.
template_extension
)
file_extension
=
self
.
template_extension
)
self
.
_renderer
=
renderer
self
.
_renderer
=
renderer
...
@@ -98,8 +113,69 @@ class View(object):
...
@@ -98,8 +113,69 @@ class View(object):
renderer
=
self
.
_get_renderer
()
renderer
=
self
.
_get_renderer
()
return
renderer
.
render
(
template
,
self
.
context
)
return
renderer
.
render
(
template
,
self
.
context
)
def
get
(
self
,
key
,
default
=
None
):
return
self
.
context
.
get
(
key
,
default
)
def
__str__
(
self
):
class
Locator
(
object
):
return
self
.
render
()
"""
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):
...
@@ -27,3 +27,11 @@ def assert_strings(test_case, actual, expected):
test_case
.
assertEquals
(
actual
,
expected
,
message
)
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
# coding: utf-8
from
pystache.view
import
View
class
SayHello
(
object
):
class
SayHello
(
object
):
def
to
(
self
):
def
to
(
self
):
return
"World"
return
"World"
class
SampleView
(
View
):
pass
class
NonAscii
(
View
):
pass
tests/test_context.py
View file @
3cd84e99
...
@@ -11,7 +11,7 @@ import unittest
...
@@ -11,7 +11,7 @@ import unittest
from
pystache.context
import
_NOT_FOUND
from
pystache.context
import
_NOT_FOUND
from
pystache.context
import
_get_value
from
pystache.context
import
_get_value
from
pystache.context
import
Context
from
pystache.context
import
Context
from
tests.common
import
AssertIsMixin
class
SimpleObject
(
object
):
class
SimpleObject
(
object
):
...
@@ -39,16 +39,6 @@ class DictLike(object):
...
@@ -39,16 +39,6 @@ class DictLike(object):
return
self
.
_dict
[
key
]
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
):
class
GetValueTests
(
unittest
.
TestCase
,
AssertIsMixin
):
"""Test context._get_value()."""
"""Test context._get_value()."""
...
...
tests/test_examples.py
View file @
3cd84e99
...
@@ -37,12 +37,6 @@ class TestView(unittest.TestCase):
...
@@ -37,12 +37,6 @@ class TestView(unittest.TestCase):
def
test_literal
(
self
):
def
test_literal
(
self
):
self
.
assertEquals
(
Unescaped
()
.
render
(),
"<h1>Bear > Shark</h1>"
)
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
):
def
test_template_partial
(
self
):
self
.
assertEquals
(
TemplatePartial
()
.
render
(),
"""<h1>Welcome</h1>
self
.
assertEquals
(
TemplatePartial
()
.
render
(),
"""<h1>Welcome</h1>
Again, Welcome!"""
)
Again, Welcome!"""
)
...
...
tests/test_locator.py
View file @
3cd84e99
...
@@ -5,6 +5,7 @@ Contains locator.py unit tests.
...
@@ -5,6 +5,7 @@ Contains locator.py unit tests.
"""
"""
from
datetime
import
datetime
import
os
import
os
import
sys
import
sys
import
unittest
import
unittest
...
@@ -13,12 +14,11 @@ from pystache.locator import Locator
...
@@ -13,12 +14,11 @@ from pystache.locator import Locator
from
pystache.reader
import
Reader
from
pystache.reader
import
Reader
from
.common
import
DATA_DIR
from
.common
import
DATA_DIR
from
data.views
import
SayHello
class
LocatorTests
(
unittest
.
TestCase
):
class
LocatorTests
(
unittest
.
TestCase
):
search_dirs
=
'examples'
def
_locator
(
self
):
def
_locator
(
self
):
return
Locator
(
search_dirs
=
DATA_DIR
)
return
Locator
(
search_dirs
=
DATA_DIR
)
...
@@ -36,12 +36,20 @@ class LocatorTests(unittest.TestCase):
...
@@ -36,12 +36,20 @@ class LocatorTests(unittest.TestCase):
def
test_get_object_directory
(
self
):
def
test_get_object_directory
(
self
):
locator
=
Locator
()
locator
=
Locator
()
reader
=
Reader
()
obj
=
SayHello
()
actual
=
locator
.
get_object_directory
(
reader
)
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
):
def
test_make_file_name
(
self
):
locator
=
Locator
()
locator
=
Locator
()
...
@@ -55,21 +63,26 @@ class LocatorTests(unittest.TestCase):
...
@@ -55,21 +63,26 @@ class LocatorTests(unittest.TestCase):
locator
.
template_extension
=
''
locator
.
template_extension
=
''
self
.
assertEquals
(
locator
.
make_file_name
(
'foo'
),
'foo.'
)
self
.
assertEquals
(
locator
.
make_file_name
(
'foo'
),
'foo.'
)
def
test_
locate_path
(
self
):
def
test_
make_file_name__template_extension_argument
(
self
):
locator
=
Locator
()
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'
)
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
()
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
)
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
()
locator
=
Locator
()
...
@@ -77,19 +90,50 @@ class LocatorTests(unittest.TestCase):
...
@@ -77,19 +90,50 @@ class LocatorTests(unittest.TestCase):
dir1
=
DATA_DIR
dir1
=
DATA_DIR
dir2
=
os
.
path
.
join
(
DATA_DIR
,
'locator'
)
dir2
=
os
.
path
.
join
(
DATA_DIR
,
'locator'
)
self
.
assertTrue
(
locator
.
locate_path
(
'duplicate'
,
search_dirs
=
[
dir1
]
))
self
.
assertTrue
(
locator
.
find_path_by_name
(
search_dirs
=
[
dir1
],
template_name
=
'duplicate'
))
self
.
assertTrue
(
locator
.
locate_path
(
'duplicate'
,
search_dirs
=
[
dir2
]
))
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
)
dirpath
=
os
.
path
.
dirname
(
path
)
dirname
=
os
.
path
.
split
(
dirpath
)[
-
1
]
dirname
=
os
.
path
.
split
(
dirpath
)[
-
1
]
self
.
assertEquals
(
dirname
,
'locator'
)
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
()
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
):
def
test_make_template_name
(
self
):
"""
"""
...
...
tests/test_reader.py
View file @
3cd84e99
...
@@ -36,6 +36,45 @@ class ReaderTestCase(unittest.TestCase):
...
@@ -36,6 +36,45 @@ class ReaderTestCase(unittest.TestCase):
reader
=
Reader
(
encoding
=
'foo'
)
reader
=
Reader
(
encoding
=
'foo'
)
self
.
assertEquals
(
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
):
def
test_read
(
self
):
"""
"""
Test read().
Test read().
...
@@ -55,25 +94,36 @@ class ReaderTestCase(unittest.TestCase):
...
@@ -55,25 +94,36 @@ class ReaderTestCase(unittest.TestCase):
contents
=
reader
.
read
(
path
)
contents
=
reader
.
read
(
path
)
self
.
assertEqual
(
type
(
contents
),
unicode
)
self
.
assertEqual
(
type
(
contents
),
unicode
)
def
test_read__encoding
(
self
):
def
test_read__encoding
__attribute
(
self
):
"""
"""
Test read(): encoding attribute respected.
Test read(): encoding attribute respected.
"""
"""
reader
=
Reader
()
reader
=
Reader
()
path
=
self
.
_get_path
(
'nonascii.mustache'
)
path
=
self
.
_get_path
(
'non
_
ascii.mustache'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
reader
.
encoding
=
'utf-8'
reader
.
encoding
=
'utf-8'
self
.
assertEquals
(
reader
.
read
(
path
),
u'non-ascii: é'
)
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
):
def
test_get__decode_errors
(
self
):
"""
"""
Test get(): decode_errors attribute.
Test get(): decode_errors attribute.
"""
"""
reader
=
Reader
()
reader
=
Reader
()
path
=
self
.
_get_path
(
'nonascii.mustache'
)
path
=
self
.
_get_path
(
'non
_
ascii.mustache'
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
self
.
assertRaises
(
UnicodeDecodeError
,
reader
.
read
,
path
)
reader
.
decode_errors
=
'replace'
reader
.
decode_errors
=
'replace'
...
...
tests/test_renderengine.py
View file @
3cd84e99
...
@@ -92,6 +92,14 @@ class RenderTests(unittest.TestCase):
...
@@ -92,6 +92,14 @@ class RenderTests(unittest.TestCase):
self
.
_assert_render
(
'BAR'
,
'{{{foo}}}'
,
{
'foo'
:
'bar'
},
engine
=
engine
)
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
):
def
test__escape
(
self
):
"""
"""
Test that render() uses the escape attribute.
Test that render() uses the escape attribute.
...
...
tests/test_renderer.py
View file @
3cd84e99
...
@@ -16,7 +16,7 @@ from pystache.renderer import Renderer
...
@@ -16,7 +16,7 @@ from pystache.renderer import Renderer
from
pystache.locator
import
Locator
from
pystache.locator
import
Locator
from
.common
import
get_data_path
from
.common
import
get_data_path
from
.data.
template
s
import
SayHello
from
.data.
view
s
import
SayHello
class
RendererInitTestCase
(
unittest
.
TestCase
):
class
RendererInitTestCase
(
unittest
.
TestCase
):
...
@@ -200,7 +200,7 @@ class RendererTestCase(unittest.TestCase):
...
@@ -200,7 +200,7 @@ class RendererTestCase(unittest.TestCase):
self
.
assertEquals
(
type
(
actual
),
unicode
)
self
.
assertEquals
(
type
(
actual
),
unicode
)
def
test_read__file_encoding
(
self
):
def
test_read__file_encoding
(
self
):
filename
=
'nonascii.mustache'
filename
=
'non
_
ascii.mustache'
renderer
=
Renderer
()
renderer
=
Renderer
()
renderer
.
file_encoding
=
'ascii'
renderer
.
file_encoding
=
'ascii'
...
@@ -211,7 +211,7 @@ class RendererTestCase(unittest.TestCase):
...
@@ -211,7 +211,7 @@ class RendererTestCase(unittest.TestCase):
self
.
assertEquals
(
actual
,
u'non-ascii: é'
)
self
.
assertEquals
(
actual
,
u'non-ascii: é'
)
def
test_read__decode_errors
(
self
):
def
test_read__decode_errors
(
self
):
filename
=
'nonascii.mustache'
filename
=
'non
_
ascii.mustache'
renderer
=
Renderer
()
renderer
=
Renderer
()
self
.
assertRaises
(
UnicodeDecodeError
,
self
.
_read
,
renderer
,
filename
)
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
unittest
import
pystache
from
examples.simple
import
Simple
from
examples.simple
import
Simple
from
examples.complex_view
import
ComplexView
from
examples.complex_view
import
ComplexView
from
examples.lambdas
import
Lambdas
from
examples.lambdas
import
Lambdas
from
examples.inverted
import
Inverted
,
InvertedLists
from
examples.inverted
import
Inverted
,
InvertedLists
from
pystache.reader
import
Reader
from
pystache.view
import
View
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
):
class
Thing
(
object
):
...
@@ -25,39 +38,6 @@ class ViewTestCase(unittest.TestCase):
...
@@ -25,39 +38,6 @@ class ViewTestCase(unittest.TestCase):
view
=
TestView
()
view
=
TestView
()
self
.
assertEquals
(
view
.
template
,
"foo"
)
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
):
def
test_template_path
(
self
):
"""
"""
Test that View.template_path is respected.
Test that View.template_path is respected.
...
@@ -88,24 +68,6 @@ class ViewTestCase(unittest.TestCase):
...
@@ -88,24 +68,6 @@ class ViewTestCase(unittest.TestCase):
view
.
template_path
=
"examples"
view
.
template_path
=
"examples"
self
.
assertEquals
(
view
.
render
(),
"Partial: No tags..."
)
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
):
def
test_basic_method_calls
(
self
):
view
=
Simple
()
view
=
Simple
()
self
.
assertEquals
(
view
.
render
(),
"Hi pizza!"
)
self
.
assertEquals
(
view
.
render
(),
"Hi pizza!"
)
...
@@ -115,13 +77,6 @@ class ViewTestCase(unittest.TestCase):
...
@@ -115,13 +77,6 @@ class ViewTestCase(unittest.TestCase):
view
.
thing
=
'Chris'
view
.
thing
=
'Chris'
self
.
assertEquals
(
view
.
render
(),
"Hi 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
):
def
test_complex
(
self
):
self
.
assertEquals
(
ComplexView
()
.
render
(),
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>"""
)
"""<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):
...
@@ -168,5 +123,157 @@ class ViewTestCase(unittest.TestCase):
view
=
InvertedLists
()
view
=
InvertedLists
()
self
.
assertEquals
(
view
.
render
(),
"""one, two, three, empty list"""
)
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