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
e4108154
Commit
e4108154
authored
12 years ago
by
Chris Jerdonek
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Parser no longer requires a RenderEngine instance to parse.
parent
a3999641
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
93 additions
and
95 deletions
+93
-95
pystache/parsed.py
+1
-3
pystache/parser.py
+55
-17
pystache/renderengine.py
+37
-75
No files found.
pystache/parsed.py
View file @
e4108154
...
@@ -45,9 +45,7 @@ class ParsedTemplate(object):
...
@@ -45,9 +45,7 @@ class ParsedTemplate(object):
"""
"""
# We avoid use of the ternary operator for Python 2.4 support.
# We avoid use of the ternary operator for Python 2.4 support.
def
get_unicode
(
val
):
def
get_unicode
(
val
):
if
callable
(
val
):
if
type
(
val
)
is
unicode
:
return
val
(
context
)
if
isinstance
(
val
,
basestring
):
return
val
return
val
return
val
.
render
(
engine
,
context
)
return
val
.
render
(
engine
,
context
)
parts
=
map
(
get_unicode
,
self
.
_parse_tree
)
parts
=
map
(
get_unicode
,
self
.
_parse_tree
)
...
...
This diff is collapsed.
Click to expand it.
pystache/parser.py
View file @
e4108154
...
@@ -71,7 +71,7 @@ class ChangeNode(object):
...
@@ -71,7 +71,7 @@ class ChangeNode(object):
return
u''
return
u''
class
VariableNode
(
object
):
class
Tag
(
object
):
def
__init__
(
self
,
key
):
def
__init__
(
self
,
key
):
self
.
key
=
key
self
.
key
=
key
...
@@ -119,28 +119,65 @@ class InvertedNode(object):
...
@@ -119,28 +119,65 @@ class InvertedNode(object):
# per the spec.
# per the spec.
if
data
:
if
data
:
return
u''
return
u''
return
engine
.
_
render_parsed
(
self
.
parsed_section
,
context
)
return
engine
.
render_parsed
(
self
.
parsed_section
,
context
)
class
Parser
(
object
):
class
SectionNode
(
object
):
_delimiters
=
None
# TODO: the template_ and parsed_template_ arguments don't both seem
_template_re
=
None
# to be necessary. Can we remove one of them? For example, if
# callable(data) is True, then the initial parsed_template isn't used.
def
__init__
(
self
,
key
,
parsed_contents
,
delimiters
,
template
,
section_begin_index
,
section_end_index
):
self
.
delimiters
=
delimiters
self
.
key
=
key
self
.
parsed_contents
=
parsed_contents
self
.
template
=
template
self
.
section_begin_index
=
section_begin_index
self
.
section_end_index
=
section_end_index
def
__init__
(
self
,
engine
,
delimiters
=
None
):
def
render
(
self
,
engine
,
context
):
"""
data
=
engine
.
fetch_section_data
(
context
,
self
.
key
)
Construct an instance.
parts
=
[]
for
val
in
data
:
if
callable
(
val
):
# Lambdas special case section rendering and bypass pushing
# the data value onto the context stack. From the spec--
#
# When used as the data value for a Section tag, the
# lambda MUST be treatable as an arity 1 function, and
# invoked as such (passing a String containing the
# unprocessed section contents). The returned value
# MUST be rendered against the current delimiters, then
# interpolated in place of the section.
#
# Also see--
#
# https://github.com/defunkt/pystache/issues/113
#
# TODO: should we check the arity?
val
=
val
(
self
.
template
[
self
.
section_begin_index
:
self
.
section_end_index
])
val
=
engine
.
_render_value
(
val
,
context
,
delimiters
=
self
.
delimiters
)
parts
.
append
(
val
)
continue
Arguments:
context
.
push
(
val
)
parts
.
append
(
engine
.
render_parsed
(
self
.
parsed_contents
,
context
))
context
.
pop
()
engine: a RenderEngine instance.
return
unicode
(
''
.
join
(
parts
))
"""
class
Parser
(
object
):
_delimiters
=
None
_template_re
=
None
def
__init__
(
self
,
delimiters
=
None
):
if
delimiters
is
None
:
if
delimiters
is
None
:
delimiters
=
DEFAULT_DELIMITERS
delimiters
=
DEFAULT_DELIMITERS
self
.
_delimiters
=
delimiters
self
.
_delimiters
=
delimiters
self
.
engine
=
engine
def
_compile_delimiters
(
self
):
def
_compile_delimiters
(
self
):
self
.
_template_re
=
_compile_template_re
(
self
.
_delimiters
)
self
.
_template_re
=
_compile_template_re
(
self
.
_delimiters
)
...
@@ -242,8 +279,9 @@ class Parser(object):
...
@@ -242,8 +279,9 @@ class Parser(object):
parsed_template
.
add
(
node
)
parsed_template
.
add
(
node
)
# Add the remainder of the template.
# Avoid adding spurious empty strings to the parse tree.
parsed_template
.
add
(
template
[
start_index
:])
if
start_index
!=
len
(
template
):
parsed_template
.
add
(
template
[
start_index
:])
return
parsed_template
return
parsed_template
...
@@ -262,7 +300,7 @@ class Parser(object):
...
@@ -262,7 +300,7 @@ class Parser(object):
return
ChangeNode
(
delimiters
)
return
ChangeNode
(
delimiters
)
if
tag_type
==
''
:
if
tag_type
==
''
:
return
VariableNode
(
tag_key
)
return
Tag
(
tag_key
)
if
tag_type
==
'&'
:
if
tag_type
==
'&'
:
return
LiteralNode
(
tag_key
)
return
LiteralNode
(
tag_key
)
...
@@ -279,8 +317,8 @@ class Parser(object):
...
@@ -279,8 +317,8 @@ class Parser(object):
"""
"""
if
tag_type
==
'#'
:
if
tag_type
==
'#'
:
return
self
.
engine
.
_make_get_section
(
tag_key
,
parsed_section
,
self
.
_delimiters
,
return
SectionNode
(
tag_key
,
parsed_section
,
self
.
_delimiters
,
template
,
section_start_index
,
section_end_index
)
template
,
section_start_index
,
section_end_index
)
if
tag_type
==
'^'
:
if
tag_type
==
'^'
:
return
InvertedNode
(
tag_key
,
parsed_section
)
return
InvertedNode
(
tag_key
,
parsed_section
)
...
...
This diff is collapsed.
Click to expand it.
pystache/renderengine.py
View file @
e4108154
...
@@ -87,12 +87,12 @@ class RenderEngine(object):
...
@@ -87,12 +87,12 @@ class RenderEngine(object):
# The returned value MUST be rendered against the default delimiters,
# The returned value MUST be rendered against the default delimiters,
# then interpolated in place of the lambda.
# then interpolated in place of the lambda.
#
#
def
fetch_string
(
self
,
context
,
tag_
name
):
def
fetch_string
(
self
,
context
,
name
):
"""
"""
Get a value from the given context as a basestring instance.
Get a value from the given context as a basestring instance.
"""
"""
val
=
self
.
resolve_context
(
context
,
tag_
name
)
val
=
self
.
resolve_context
(
context
,
name
)
if
callable
(
val
):
if
callable
(
val
):
# Return because _render_value() is already a string.
# Return because _render_value() is already a string.
...
@@ -103,81 +103,40 @@ class RenderEngine(object):
...
@@ -103,81 +103,40 @@ class RenderEngine(object):
return
val
return
val
# TODO: the template_ and parsed_template_ arguments don't both seem
def
fetch_section_data
(
self
,
context
,
name
):
# to be necessary. Can we remove one of them? For example, if
data
=
self
.
resolve_context
(
context
,
name
)
# callable(data) is True, then the initial parsed_template isn't used.
def
_make_get_section
(
self
,
name
,
parsed_template
,
delims
,
# From the spec:
template
,
section_start_index
,
section_end_index
):
#
def
get_section_value
(
context
):
# If the data is not of a list type, it is coerced into a list
"""
# as follows: if the data is truthy (e.g. `!!data == true`),
Returns: a string of type unicode.
# use a single-element list containing the data, otherwise use
# an empty list.
"""
#
data
=
self
.
resolve_context
(
context
,
name
)
if
not
data
:
data
=
[]
# From the spec:
else
:
# The least brittle way to determine whether something
# supports iteration is by trying to call iter() on it:
#
#
# If the data is not of a list type, it is coerced into a list
# http://docs.python.org/library/functions.html#iter
# as follows: if the data is truthy (e.g. `!!data == true`),
# use a single-element list containing the data, otherwise use
# an empty list.
#
#
if
not
data
:
# It is not sufficient, for example, to check whether the item
data
=
[]
# implements __iter__ () (the iteration protocol). There is
# also __getitem__() (the sequence protocol). In Python 2,
# strings do not implement __iter__(), but in Python 3 they do.
try
:
iter
(
data
)
except
TypeError
:
# Then the value does not support iteration.
data
=
[
data
]
else
:
else
:
# The least brittle way to determine whether something
if
is_string
(
data
)
or
isinstance
(
data
,
dict
):
# supports iteration is by trying to call iter() on it:
# Do not treat strings and dicts (which are iterable) as lists.
#
# http://docs.python.org/library/functions.html#iter
#
# It is not sufficient, for example, to check whether the item
# implements __iter__ () (the iteration protocol). There is
# also __getitem__() (the sequence protocol). In Python 2,
# strings do not implement __iter__(), but in Python 3 they do.
try
:
iter
(
data
)
except
TypeError
:
# Then the value does not support iteration.
data
=
[
data
]
data
=
[
data
]
else
:
# Otherwise, treat the value as a list.
if
is_string
(
data
)
or
isinstance
(
data
,
dict
):
# Do not treat strings and dicts (which are iterable) as lists.
return
data
data
=
[
data
]
# Otherwise, treat the value as a list.
parts
=
[]
for
val
in
data
:
if
callable
(
val
):
# Lambdas special case section rendering and bypass pushing
# the data value onto the context stack. From the spec--
#
# When used as the data value for a Section tag, the
# lambda MUST be treatable as an arity 1 function, and
# invoked as such (passing a String containing the
# unprocessed section contents). The returned value
# MUST be rendered against the current delimiters, then
# interpolated in place of the section.
#
# Also see--
#
# https://github.com/defunkt/pystache/issues/113
#
# TODO: should we check the arity?
val
=
val
(
template
[
section_start_index
:
section_end_index
])
val
=
self
.
_render_value
(
val
,
context
,
delimiters
=
delims
)
parts
.
append
(
val
)
continue
context
.
push
(
val
)
parts
.
append
(
self
.
_render_parsed
(
parsed_template
,
context
))
context
.
pop
()
return
unicode
(
''
.
join
(
parts
))
return
get_section_value
def
_render_parsed
(
self
,
parsed_template
,
context_stack
):
return
parsed_template
.
render
(
self
,
context_stack
)
def
_render_value
(
self
,
val
,
context
,
delimiters
=
None
):
def
_render_value
(
self
,
val
,
context
,
delimiters
=
None
):
"""
"""
...
@@ -191,6 +150,9 @@ class RenderEngine(object):
...
@@ -191,6 +150,9 @@ class RenderEngine(object):
val
=
self
.
literal
(
val
)
val
=
self
.
literal
(
val
)
return
self
.
render
(
val
,
context
,
delimiters
)
return
self
.
render
(
val
,
context
,
delimiters
)
def
render_parsed
(
self
,
parsed_template
,
context_stack
):
return
parsed_template
.
render
(
self
,
context_stack
)
def
render
(
self
,
template
,
context_stack
,
delimiters
=
None
):
def
render
(
self
,
template
,
context_stack
,
delimiters
=
None
):
"""
"""
Render a unicode template string, and return as unicode.
Render a unicode template string, and return as unicode.
...
@@ -203,7 +165,7 @@ class RenderEngine(object):
...
@@ -203,7 +165,7 @@ class RenderEngine(object):
context_stack: a ContextStack instance.
context_stack: a ContextStack instance.
"""
"""
parser
=
Parser
(
self
,
delimiters
=
delimiters
)
parser
=
Parser
(
delimiters
=
delimiters
)
parsed_template
=
parser
.
parse
(
template
)
parsed_template
=
parser
.
parse
(
template
)
return
self
.
_
render_parsed
(
parsed_template
,
context_stack
)
return
self
.
render_parsed
(
parsed_template
,
context_stack
)
This diff is collapsed.
Click to expand it.
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