Skip to content

Commit

Permalink
Add an implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Kroisse committed Apr 9, 2013
1 parent 5e62dc5 commit a89b843
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.egg-info/
*.pyc
*.pyc
.tox/
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: python
python:
- "2.6"
- "2.7"
- "3.3"
- "pypy"
install:
- pip install .
Expand Down
1 change: 1 addition & 0 deletions formencode_jinja2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .formfill import FormFillExtension as formfill # NOQA
46 changes: 46 additions & 0 deletions formencode_jinja2/formfill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import collections
import formencode.htmlfill
import jinja2
import jinja2.ext
from jinja2 import nodes


class FormFillExtension(jinja2.ext.Extension):
"""
"""
tags = frozenset(['formfill'])

def parse(self, parser):
token = next(parser.stream)
defaults = parser.parse_expression()
if parser.stream.skip_if('name:with'):
errors = parser.parse_expression()
else:
errors = nodes.Const({})
if isinstance(defaults, nodes.Name):
defaults = nodes.Getattr(nodes.ContextReference(),
defaults.name, self.environment)
if isinstance(errors, nodes.Name):
errors = nodes.Getattr(nodes.ContextReference(),
errors.name, self.environment)
body = parser.parse_statements(['name:endformfill'], drop_needle=True)
return nodes.CallBlock(
self.call_method('_formfill_support', (defaults, errors)),
(), (), body).set_lineno(token.lineno)

def _formfill_support(self, defaults, errors, caller):
if not isinstance(defaults, collections.Mapping):
raise TypeError("argument 'defaults' should be "
"collections.Mapping, not {0!r}".format(defaults))
if not isinstance(errors, collections.Mapping):
raise TypeError("argument 'errors' should be collections.Mapping, "
"not {0!r}".format(errors))
rv = caller()
return formencode.htmlfill.render(
rv, defaults, errors, error_formatters=self.ERROR_FORMATTERS)

ERROR_FORMATTERS = {
'default': lambda msg: '<span class="error-message">{0}</span>'
.format(msg),
}
92 changes: 92 additions & 0 deletions formencode_jinja2/test_formfill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import pytest
import jinja2
from formfill import FormFillExtension


@pytest.fixture
def jinja_env():
env = jinja2.Environment(extensions=[FormFillExtension])
return env


def test_formfill(jinja_env):
template = u'''
{% formfill {'username': 'john doe'}
with {'username': 'Invalid Username'} -%}
<form action="account/signin" method="POST">
<input type="text" name="username" />
<form:error name="username">
<input type="password" name="password" />
</form>
{%- endformfill %}'''
expected = u'''
<form action="account/signin" method="POST">
<input type="text" name="username" class="error" value="john doe" />
<span class="error-message">Invalid Username</span>
<input type="password" name="password" value="" />
</form>'''
result = jinja_env.from_string(template).render()
assert result == expected


def test_formfill_without_errors(jinja_env):
template = u'''
{% formfill {'username': 'louis'} -%}
<form action="account/signin" method="POST">
<input type="text" name="username" />
<form:error name="username">
<input type="password" name="password" />
</form>
{%- endformfill %}'''
expected = u'''
<form action="account/signin" method="POST">
<input type="text" name="username" value="louis" />
<input type="password" name="password" value="" />
</form>'''
result = jinja_env.from_string(template).render()
assert result == expected


def test_formfill_without_args(jinja_env):
template = u'''
{% formfill -%}
<form action="account/signin" method="POST">
<input type="text" name="username" />
<input type="password" name="password" />
</form>
{%- endformfill %}'''
with pytest.raises(jinja2.TemplateSyntaxError):
jinja_env.from_string(template).render()
template2 = u'''
{% formfill {'username': 'george'} with -%}
<form action="account/signin" method="POST">
<input type="text" name="username" />
<input type="password" name="password" />
</form>
{%- endformfill %}'''
with pytest.raises(jinja2.TemplateSyntaxError):
jinja_env.from_string(template2).render()


def test_formfill_with_wrong_args(jinja_env):
template = u'''
{% formfill 'michile' -%}
<form action="account/signin" method="POST">
<input type="text" name="username" />
<input type="password" name="password" />
</form>
{%- endformfill %}'''
with pytest.raises(TypeError) as exc:
jinja_env.from_string(template).render()
assert "not 'michile'" in str(exc)
template2 = u'''
{% formfill {'username': 'austin'} with ['Invalid Username'] -%}
<form action="account/signin" method="POST">
<input type="text" name="username" />
<input type="password" name="password" />
</form>
{%- endformfill %}'''
with pytest.raises(TypeError) as exc:
jinja_env.from_string(template2).render()
assert "not ['Invalid Username']" in str(exc)
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ def run_tests(self):
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2 :: Only',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development :: Libraries :: Python Modules',
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py27,py33,pypy
envlist = py26,py27,pypy

[testenv]
deps = pytest
Expand Down

0 comments on commit a89b843

Please sign in to comment.