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
d4181510
Commit
d4181510
authored
Dec 23, 2011
by
Chris Jerdonek
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished issue #64: "Change Renderer to accept a loader implementing get()"
parent
abe5700e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
124 additions
and
44 deletions
+124
-44
pystache/renderer.py
+38
-16
pystache/view.py
+25
-13
tests/test_renderer.py
+57
-9
tests/test_view.py
+4
-6
No files found.
pystache/renderer.py
View file @
d4181510
...
...
@@ -22,13 +22,41 @@ except ImportError:
class
Renderer
(
object
):
def
__init__
(
self
,
output_encoding
=
None
,
escape
=
None
,
default_encoding
=
None
,
decode_errors
=
'strict'
,
load_template
=
None
):
"""
A class for rendering mustache templates.
This class supports several rendering options which are described in
the constructor's docstring. Among these, the constructor supports
passing a custom template loader.
Here is an example of passing a custom template loader to render a
template using partials loaded from a string-string dictionary.
>>> partials = {'partial': 'Hello, {{thing}}!'}
>>> renderer = Renderer(loader=partials)
>>> renderer.render('{{>partial}}', {'thing': 'world'})
u'Hello, world!'
"""
def
__init__
(
self
,
loader
=
None
,
default_encoding
=
None
,
decode_errors
=
'strict'
,
output_encoding
=
None
,
escape
=
None
):
"""
Construct an instance.
Arguments:
loader: the object (e.g. pystache.Loader or dictionary) that will
load templates during the rendering process, for example when
loading a partial.
The loader should have a get() method that accepts a string
and returns the corresponding template as a string, preferably
as a unicode string. If there is no template with that name,
the method should either return None (as dict.get() does) or
raise an exception.
Defaults to constructing a Loader instance with
default_encoding passed as the encoding argument.
output_encoding: the encoding to use when rendering to a string.
The argument should be the name of an encoding as a string, for
example "utf-8". See the render() method's documentation for
...
...
@@ -57,11 +85,6 @@ class Renderer(object):
strings of type `str` encountered during the rendering process.
Defaults to "strict".
load_template: a function for loading templates by name, for
example when loading partials. The function should accept a
single template_name parameter and return a template as a string.
Defaults to the default Loader's get() method.
"""
if
default_encoding
is
None
:
default_encoding
=
sys
.
getdefaultencoding
()
...
...
@@ -69,9 +92,8 @@ class Renderer(object):
if
escape
is
None
:
escape
=
markupsafe
.
escape
if
markupsafe
else
cgi
.
escape
if
load_template
is
None
:
loader
=
Loader
()
load_template
=
loader
.
get
if
loader
is
None
:
loader
=
Loader
(
encoding
=
default_encoding
)
literal
=
markupsafe
.
Markup
if
markupsafe
else
unicode
...
...
@@ -80,7 +102,7 @@ class Renderer(object):
self
.
decode_errors
=
decode_errors
self
.
default_encoding
=
default_encoding
self
.
escape
=
escape
self
.
load
_template
=
load_template
self
.
load
er
=
loader
self
.
output_encoding
=
output_encoding
def
_unicode_and_escape
(
self
,
s
):
...
...
@@ -139,11 +161,11 @@ class Renderer(object):
"""
def
load_partial
(
name
):
template
=
self
.
load
_template
(
name
)
# Make sure the return value
of load_template is unicode since
#
RenderEngine requires it. Also, check that the string is not
# a
lready unicode to avoid "double-decoding". Otherwise, we
#
would get the following
error:
template
=
self
.
load
er
.
get
(
name
)
# Make sure the return value
is unicode since RenderEngine requires
#
it. Also, check that the string is not already unicode to
# a
void "double-decoding". Otherwise, we would get the following
# error:
# TypeError: decoding Unicode is not supported
if
not
isinstance
(
template
,
unicode
):
template
=
self
.
unicode
(
template
)
...
...
pystache/view.py
View file @
d4181510
...
...
@@ -21,16 +21,24 @@ class View(object):
template_encoding
=
None
template_extension
=
None
# A function that accepts a single template_name parameter.
_load_template
=
None
_loader
=
None
def
__init__
(
self
,
template
=
None
,
context
=
None
,
load
_template
=
None
,
**
kwargs
):
def
__init__
(
self
,
template
=
None
,
context
=
None
,
load
er
=
None
,
**
kwargs
):
"""
Construct a View instance.
Arguments:
loader: the object (e.g. pystache.Loader or dictionary) responsible
for loading templates during the rendering process, for example
when loading partials. 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.
"""
if
load
_template
is
not
None
:
self
.
_load
_template
=
load_template
if
load
er
is
not
None
:
self
.
_load
er
=
loader
if
template
is
not
None
:
self
.
template
=
template
...
...
@@ -43,17 +51,21 @@ class View(object):
self
.
context
=
_context
def
load_template
(
self
,
template_name
):
if
self
.
_load
_template
is
None
:
# We delay setting self._load
_template until now (in the cas
e
#
that the
user did not supply a load_template to the constructor)
def
get_loader
(
self
):
if
self
.
_load
er
is
None
:
# We delay setting self._load
er until now (in the case that th
e
# user did not supply a load_template to the constructor)
# to let users set the template_extension attribute, etc. after
# View.__init__() has already been called.
loader
=
Loader
(
search_dirs
=
self
.
template_path
,
encoding
=
self
.
template_encoding
,
extension
=
self
.
template_extension
)
self
.
_load
_template
=
loader
.
get
self
.
_load
er
=
loader
return
self
.
_load_template
(
template_name
)
return
self
.
_loader
def
load_template
(
self
,
template_name
):
loader
=
self
.
get_loader
()
return
loader
.
get
(
template_name
)
def
get_template
(
self
):
"""
...
...
@@ -98,9 +110,9 @@ class View(object):
Return the view rendered using the current context.
"""
loader
=
self
.
get_loader
()
template
=
self
.
get_template
()
renderer
=
Renderer
(
output_encoding
=
encoding
,
escape
=
escape
,
load_template
=
self
.
load_template
)
renderer
=
Renderer
(
output_encoding
=
encoding
,
escape
=
escape
,
loader
=
loader
)
return
renderer
.
render
(
template
,
self
.
context
)
def
get
(
self
,
key
,
default
=
None
):
...
...
tests/test_renderer.py
View file @
d4181510
...
...
@@ -11,6 +11,37 @@ import unittest
from
pystache
import
renderer
from
pystache.renderer
import
Renderer
from
pystache.loader
import
Loader
class
RendererInitTestCase
(
unittest
.
TestCase
):
"""A class to test the Renderer.__init__() method."""
def
test_loader
(
self
):
"""Test that the loader attribute is set correctly."""
loader
=
{
'foo'
:
'bar'
}
r
=
Renderer
(
loader
=
loader
)
self
.
assertEquals
(
r
.
loader
,
{
'foo'
:
'bar'
})
def
test_loader__default
(
self
):
"""Test that the default loader is constructed correctly."""
r
=
Renderer
()
actual
=
r
.
loader
expected
=
Loader
()
self
.
assertEquals
(
type
(
actual
),
type
(
expected
))
self
.
assertEquals
(
actual
.
__dict__
,
expected
.
__dict__
)
def
test_loader__default__default_encoding
(
self
):
"""Test that the default loader inherits the default_encoding."""
r
=
Renderer
(
default_encoding
=
'foo'
)
actual
=
r
.
loader
expected
=
Loader
(
encoding
=
'foo'
)
self
.
assertEquals
(
actual
.
template_encoding
,
expected
.
template_encoding
)
# Check all attributes for good measure.
self
.
assertEquals
(
actual
.
__dict__
,
expected
.
__dict__
)
class
RendererTestCase
(
unittest
.
TestCase
):
...
...
@@ -240,19 +271,37 @@ class RendererTestCase(unittest.TestCase):
renderer
.
default_encoding
=
'utf_8'
self
.
assertEquals
(
renderer
.
render
(
template
),
"déf"
)
def
test_make_load_partial
(
self
):
"""
Test the _make_load_partial() method.
"""
partials
=
{
'foo'
:
'bar'
}
renderer
=
Renderer
(
loader
=
partials
)
load_partial
=
renderer
.
_make_load_partial
()
actual
=
load_partial
(
'foo'
)
self
.
assertEquals
(
actual
,
'bar'
)
self
.
assertEquals
(
type
(
actual
),
unicode
,
"RenderEngine requires that "
"load_partial return unicode strings."
)
def
test_make_load_partial__unicode
(
self
):
"""
Test
that the generated load_partial does no
t "double-decode" Unicode.
Test
_make_load_partial(): that load_partial doesn'
t "double-decode" Unicode.
"""
renderer
=
Renderer
()
# In real-life, the partial would be different with each name.
renderer
.
load_template
=
lambda
name
:
u"partial"
renderer
.
loader
=
{
'partial'
:
'foo'
}
load_partial
=
renderer
.
_make_load_partial
()
self
.
assertEquals
(
load_partial
(
"partial"
),
"foo"
)
# This would raise a TypeError exception if we tried to double-decode.
self
.
assertEquals
(
load_partial
(
"test"
),
"partial"
)
# Now with a value that is already unicode.
renderer
.
loader
=
{
'partial'
:
u'foo'
}
load_partial
=
renderer
.
_make_load_partial
()
# If the next line failed, we would get the following error:
# TypeError: decoding Unicode is not supported
self
.
assertEquals
(
load_partial
(
"partial"
),
"foo"
)
# By testing that Renderer.render() constructs the RenderEngine instance
# correctly, we no longer need to test the rendering code paths through
...
...
@@ -263,14 +312,13 @@ class RendererTestCase(unittest.TestCase):
Test that _make_render_engine() constructs and passes load_partial correctly.
"""
renderer
=
Renderer
()
partials
=
{
'partial'
:
'foo'
}
renderer
=
Renderer
(
loader
=
partials
)
renderer
.
unicode
=
lambda
s
:
s
.
upper
()
# a test version.
# In real-life, the partial would be different with each name.
renderer
.
load_template
=
lambda
name
:
"partial"
engine
=
renderer
.
_make_render_engine
()
# Make sure it calls unicode.
self
.
assertEquals
(
engine
.
load_partial
(
'
name'
),
"PARTIAL
"
)
self
.
assertEquals
(
engine
.
load_partial
(
'
partial'
),
"FOO
"
)
def
test_make_render_engine__literal
(
self
):
"""
...
...
tests/test_view.py
View file @
d4181510
...
...
@@ -60,15 +60,13 @@ class ViewTestCase(unittest.TestCase):
template
=
view
.
load_template
(
'extensionless'
)
self
.
assertEquals
(
template
,
"No file extension: {{foo}}"
)
def
test_
custom_load_template
(
self
):
def
test_
load_template__custom_loader
(
self
):
"""
Test passing a custom load
_template
to View.__init__().
Test passing a custom load
er
to View.__init__().
"""
partials_dict
=
{
"partial"
:
"Loaded from dictionary"
}
load_template
=
lambda
template_name
:
partials_dict
[
template_name
]
view
=
Simple
(
load_template
=
load_template
)
partials
=
{
"partial"
:
"Loaded from dictionary"
}
view
=
Simple
(
loader
=
partials
)
actual
=
view
.
load_template
(
"partial"
)
self
.
assertEquals
(
actual
,
"Loaded from dictionary"
)
...
...
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