Skip to content
This repository has been archived by the owner on Sep 5, 2019. It is now read-only.

Commit

Permalink
Support nested values (Nesting can't go deeper than one)
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Krienbühl committed May 14, 2015
1 parent d413405 commit 23d0d39
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 4 deletions.
37 changes: 33 additions & 4 deletions onegov/form/parser/grammar.py
Expand Up @@ -3,7 +3,10 @@
from pyparsing import (
nums,
Combine,
Empty,
Forward,
Group,
indentedBlock,
LineEnd,
Literal,
OneOrMore,
Expand All @@ -12,7 +15,8 @@
MatchFirst,
Suppress,
Word,
White
White,
Token,
)


Expand All @@ -22,6 +26,12 @@
text = Word(unicode_characters)
numeric = Word(nums)

# shortcut
indented = indentedBlock


block = Forward()


def text_without(characters):
""" Returns all printable text without the given characters. """
Expand Down Expand Up @@ -147,7 +157,14 @@ def password():
return Suppress('***').setParseAction(tag(type='password'))


def marker_box(characters):
class Stack(list):

def init(self, initial_value):
if not len(self):
self[:] = [initial_value]


def marker_box(characters, indent_stack=None):
""" Returns a marker box:
Example:
Expand All @@ -159,7 +176,13 @@ def marker_box(characters):
check = mark_enclosed_in(characters)('checked')
label = with_whitespace_inside(text_without(characters))('label')

return Group(check + label)
stack = Stack()
label.setParseAction(lambda s, l, t: stack.init(l - 1))

dependencies = Group(indented(block, stack))('dependencies')
dependencies.setParseAction(unwrap)

return Group(check + label + Optional(dependencies))


def radios():
Expand All @@ -179,7 +202,10 @@ def checkboxes():
[] Android [x] iPhone [x] Dumb Phone
"""
return OneOrMore(marker_box('[]')).setParseAction(tag(type='checkbox'))
boxes = OneOrMore(marker_box('[]'))
boxes.setParseAction(tag(type='checkbox'))

return boxes


def custom():
Expand Down Expand Up @@ -287,3 +313,6 @@ def block_content():
def document():
""" Returns a form document. """
return OneOrMore(block_content())


block << block_content()
53 changes: 53 additions & 0 deletions onegov/form/tests/test_grammar.py
Expand Up @@ -273,3 +273,56 @@ def test_multiline_checkboxes():
assert result[1]['parts'][2].asDict() == {
'checked': True, 'label': 'Travel Insurance'
}


def test_nested_blocks():
form = textwrap.dedent("""
Payment = (x) Bill
( ) Credit Card
Address = ___
""")
result = document().searchString(form)

assert len(result) == 1
assert result[0].parts[1].dependencies[0].asDict() == {
'required': False, 'label': 'Address', 'type': 'text'
}


def test_doubly_nested():
form = textwrap.dedent("""
Payment = (x) Bill
Address = ___
Comment = ...
( ) Credit Card
Type = (x) Visa
( ) Mastercard
Store = [ ] Address
[x] Card
""")
result = document().searchString(form)

assert len(result) == 1
assert result[0].parts[0].dependencies[0].asDict() == {
'label': 'Address', 'required': False, 'type': 'text'
}
assert result[0].parts[0].dependencies[1].asDict() == {
'label': 'Comment', 'required': False, 'type': 'textarea'
}
assert result[0].parts[1].dependencies[0].label == 'Type'
assert result[0].parts[1].dependencies[0].type == 'radio'
assert result[0].parts[1].dependencies[0].parts[0].asDict() == {
'checked': True, 'label': 'Visa'
}
assert result[0].parts[1].dependencies[0].parts[1].asDict() == {
'checked': False, 'label': 'Mastercard'
}
assert result[0].parts[1].dependencies[1].parts[0].asDict() == {
'checked': False, 'label': 'Address'
}
assert result[0].parts[1].dependencies[1].parts[1].asDict() == {
'checked': True, 'label': 'Card'
}

0 comments on commit 23d0d39

Please sign in to comment.