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
8fb76bb2
Commit
8fb76bb2
authored
Jan 11, 2011
by
Carl Whittaker
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First test passing with {{ }}
parent
bb549161
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
52 additions
and
220 deletions
+52
-220
pystache/template.py
+38
-114
pystache/view.py
+4
-106
tests/test_simple.py
+10
-0
No files found.
pystache/template.py
View file @
8fb76bb2
...
...
@@ -17,138 +17,61 @@ def modifier(symbol):
return
func
return
set_modifier
def
get_or_attr
(
obj
,
name
,
default
=
None
):
try
:
return
obj
[
name
]
except
KeyError
:
return
default
except
:
try
:
return
getattr
(
obj
,
name
)
except
AttributeError
:
return
default
class
Template
(
object
):
# The regular expression used to find a #section
section_re
=
None
# The regular expression used to find a tag.
tag_re
=
None
# Opening tag delimiter
otag
=
'{{'
# Closing tag delimiter
ctag
=
'}}'
def
__init__
(
self
,
template
,
context
=
None
):
def
__init__
(
self
,
template
=
None
,
context
=
None
,
**
kwargs
):
from
view
import
View
self
.
template
=
template
self
.
context
=
context
or
{}
self
.
compile_regexps
()
def
render
(
self
,
template
=
None
,
context
=
None
,
encoding
=
None
):
"""Turns a Mustache template into something wonderful."""
template
=
template
or
self
.
template
context
=
context
or
self
.
context
template
=
self
.
render_sections
(
template
,
context
)
result
=
self
.
render_tags
(
template
,
context
)
if
encoding
is
not
None
:
result
=
result
.
encode
(
encoding
)
return
result
def
compile_regexps
(
self
):
"""Compiles our section and tag regular expressions."""
tags
=
{
'otag'
:
re
.
escape
(
self
.
otag
),
'ctag'
:
re
.
escape
(
self
.
ctag
)
}
section
=
r"
%(otag)
s[\#|^]([^\}]*)
%(ctag)
s\s*(.+?)\s*
%(otag)
s/\1
%(ctag)
s"
self
.
section_re
=
re
.
compile
(
section
%
tags
,
re
.
M
|
re
.
S
)
if
kwargs
:
context
.
update
(
kwargs
)
self
.
view
=
context
if
isinstance
(
context
,
View
)
else
View
(
context
=
context
)
self
.
_compile_regexps
()
def
_compile_regexps
(
self
):
tags
=
{
'otag'
:
re
.
escape
(
self
.
otag
),
'ctag'
:
re
.
escape
(
self
.
ctag
)
}
tag
=
r"
%(otag)
s(#|=|&|!|>|\{)?(.+?)\1?
%(ctag)
s+"
self
.
tag_re
=
re
.
compile
(
tag
%
tags
)
def
render_sections
(
self
,
template
,
context
):
"""Expands sections."""
while
1
:
match
=
self
.
section_re
.
search
(
template
)
if
match
is
None
:
break
section
,
section_name
,
inner
=
match
.
group
(
0
,
1
,
2
)
section_name
=
section_name
.
strip
()
it
=
get_or_attr
(
context
,
section_name
,
None
)
replacer
=
''
if
it
and
isinstance
(
it
,
collections
.
Callable
):
replacer
=
it
(
inner
)
elif
it
and
not
hasattr
(
it
,
'__iter__'
):
if
section
[
2
]
!=
'^'
:
replacer
=
inner
elif
it
and
hasattr
(
it
,
'keys'
)
and
hasattr
(
it
,
'__getitem__'
):
if
section
[
2
]
!=
'^'
:
replacer
=
self
.
render
(
inner
,
it
)
elif
it
:
insides
=
[]
for
item
in
it
:
insides
.
append
(
self
.
render
(
inner
,
item
))
replacer
=
''
.
join
(
insides
)
elif
not
it
and
section
[
2
]
==
'^'
:
replacer
=
inner
template
=
template
.
replace
(
section
,
replacer
)
def
_render_sections
(
self
,
template
,
view
):
return
template
def
render_tags
(
self
,
template
,
context
):
"""Renders all the tags in a template for a context."""
while
1
:
def
_render_tags
(
self
,
template
,
view
):
while
True
:
match
=
self
.
tag_re
.
search
(
template
)
if
match
is
None
:
break
tag
,
tag_type
,
tag_name
=
match
.
group
(
0
,
1
,
2
)
tag_name
=
tag_name
.
strip
()
func
=
modifiers
[
tag_type
]
replacement
=
func
(
self
,
tag_name
,
context
)
replacement
=
func
(
self
,
tag_name
,
view
)
template
=
template
.
replace
(
tag
,
replacement
)
return
template
@modifier
(
None
)
def
render_tag
(
self
,
tag_name
,
context
):
"""Given a tag name and context, finds, escapes, and renders the tag."""
raw
=
get_or_attr
(
context
,
tag_name
,
''
)
if
not
raw
and
raw
is
not
0
:
return
''
def
_render_tag
(
self
,
tag_name
,
view
):
raw
=
view
.
get
(
tag_name
,
''
)
return
cgi
.
escape
(
unicode
(
raw
))
@modifier
(
'!'
)
def
render_comment
(
self
,
tag_name
=
None
,
context
=
None
):
"""Rendering a comment always returns nothing."""
return
''
@modifier
(
'{'
)
@modifier
(
'&'
)
def
render_unescaped
(
self
,
tag_name
=
None
,
context
=
None
):
"""Render a tag without escaping it."""
return
unicode
(
get_or_attr
(
context
,
tag_name
,
''
))
@modifier
(
'>'
)
def
render_partial
(
self
,
tag_name
=
None
,
context
=
None
):
"""Renders a partial within the current context."""
# Import view here to avoid import loop
from
pystache.view
import
View
view
=
View
(
context
=
context
)
view
.
template_name
=
tag_name
return
view
.
render
()
@modifier
(
'='
)
def
render_delimiter
(
self
,
tag_name
=
None
,
context
=
None
):
"""Changes the Mustache delimiter."""
self
.
otag
,
self
.
ctag
=
tag_name
.
split
(
' '
)
self
.
compile_regexps
()
return
''
def
render
(
self
):
template
=
self
.
_render_sections
(
self
.
template
,
self
.
view
)
result
=
self
.
_render_tags
(
template
,
self
.
view
)
return
result
\ No newline at end of file
pystache/view.py
View file @
8fb76bb2
...
...
@@ -4,114 +4,11 @@ import re
from
types
import
*
class
View
(
object
):
# Path where this view's template(s) live
template_path
=
'.'
# Extension for templates
template_extension
=
'mustache'
# The name of this template. If none is given the View will try
# to infer it based on the class name.
template_name
=
None
# Absolute path to the template itself. Pystache will try to guess
# if it's not provided.
template_file
=
None
# Contents of the template.
template
=
None
# Character encoding of the template file. If None, Pystache will not
# do any decoding of the template.
template_encoding
=
None
def
__init__
(
self
,
template
=
None
,
context
=
None
,
**
kwargs
):
self
.
template
=
template
self
.
context
=
context
or
{}
# If the context we're handed is a View, we want to inherit
# its settings.
if
isinstance
(
context
,
View
):
self
.
inherit_settings
(
context
)
if
kwargs
:
self
.
context
.
update
(
kwargs
)
def
inherit_settings
(
self
,
view
):
"""Given another View, copies its settings."""
if
view
.
template_path
:
self
.
template_path
=
view
.
template_path
if
view
.
template_name
:
self
.
template_name
=
view
.
template_name
def
load_template
(
self
):
if
self
.
template
:
return
self
.
template
if
self
.
template_file
:
return
self
.
_load_template
()
name
=
self
.
get_template_name
()
+
'.'
+
self
.
template_extension
if
isinstance
(
self
.
template_path
,
basestring
):
self
.
template_file
=
os
.
path
.
join
(
self
.
template_path
,
name
)
return
self
.
_load_template
()
self
.
context
.
update
(
**
kwargs
)
for
path
in
self
.
template_path
:
self
.
template_file
=
os
.
path
.
join
(
path
,
name
)
if
os
.
path
.
exists
(
self
.
template_file
):
return
self
.
_load_template
()
raise
IOError
(
'"
%
s" not found in "
%
s"'
%
(
name
,
':'
.
join
(
self
.
template_path
),))
def
_load_template
(
self
):
f
=
open
(
self
.
template_file
,
'r'
)
try
:
template
=
f
.
read
()
if
self
.
template_encoding
:
template
=
unicode
(
template
,
self
.
template_encoding
)
finally
:
f
.
close
()
return
template
def
get_template_name
(
self
,
name
=
None
):
"""TemplatePartial => template_partial
Takes a string but defaults to using the current class' name or
the `template_name` attribute
"""
if
self
.
template_name
:
return
self
.
template_name
if
not
name
:
name
=
self
.
__class__
.
__name__
def
repl
(
match
):
return
'_'
+
match
.
group
(
0
)
.
lower
()
return
re
.
sub
(
'[A-Z]'
,
repl
,
name
)[
1
:]
def
__contains__
(
self
,
needle
):
return
needle
in
self
.
context
or
hasattr
(
self
,
needle
)
def
__getitem__
(
self
,
attr
):
val
=
self
.
get
(
attr
,
None
)
if
not
val
:
raise
KeyError
(
"No such key."
)
return
val
def
get
(
self
,
attr
,
default
):
attr
=
self
.
context
.
get
(
attr
,
getattr
(
self
,
attr
,
default
))
if
hasattr
(
attr
,
'__call__'
)
and
type
(
attr
)
is
UnboundMethodType
:
return
attr
()
else
:
return
attr
def
render
(
self
,
encoding
=
None
):
template
=
self
.
load_template
()
return
Template
(
template
,
self
)
.
render
(
encoding
=
encoding
)
def
__str__
(
self
):
return
self
.
render
()
def
get
(
self
,
attr
,
default
=
None
):
return
self
.
context
.
get
(
attr
,
getattr
(
self
,
attr
,
default
))
\ No newline at end of file
tests/test_simple.py
0 → 100644
View file @
8fb76bb2
import
unittest
import
pystache
class
TestSimple
(
unittest
.
TestCase
):
def
test_simple_render
(
self
):
tmpl
=
'{{derp}}'
self
.
assertEqual
(
'herp'
,
pystache
.
Template
(
tmpl
,
{
'derp'
:
'herp'
})
.
render
())
\ No newline at end of file
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