Skip to content
This repository has been archived by the owner on Aug 17, 2023. It is now read-only.

Commit

Permalink
Test coverage and tweak element parsing so same compiler is reused fo…
Browse files Browse the repository at this point in the history
…r parsing attribute values which are Haml
  • Loading branch information
rowanseymour committed Mar 14, 2017
1 parent 1de5961 commit e302feb
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 32 deletions.
5 changes: 1 addition & 4 deletions hamlpy/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,7 @@ class Compiler:
}

def __init__(self, options=None):
if isinstance(options, Options):
self.options = options
else:
self.options = Options(**(options or {}))
self.options = Options(**(options or {}))

tag_config = self.TAG_CONFIGS[self.options.tag_config]
self.self_closing_tags = tag_config['self_closing']
Expand Down
35 changes: 17 additions & 18 deletions hamlpy/parser/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
ATTRIBUTE_VALUE_KEYWORDS = {'none': None, 'true': True, 'false': False}


def read_attribute_value(stream, options):
def read_attribute_value(stream, compiler):
"""
Reads an attribute's value which may be a string, a number or None
"""
Expand All @@ -25,7 +25,7 @@ def read_attribute_value(stream, options):
if ch in STRING_LITERALS:
value = read_quoted_string(stream)

if options.escape_attrs:
if compiler.options.escape_attrs:
# TODO handle escape_attrs=once
value = html_escape(value)

Expand All @@ -44,7 +44,7 @@ def read_attribute_value(stream, options):
return value


def read_attribute_value_list(stream, options):
def read_attribute_value_list(stream, compiler):
"""
Reads an attribute value which is a list of other values
"""
Expand All @@ -65,7 +65,7 @@ def read_attribute_value_list(stream, options):
if stream.text[stream.ptr] == close_literal:
break

data.append(read_attribute_value(stream, options))
data.append(read_attribute_value(stream, compiler))

read_whitespace(stream)

Expand All @@ -77,7 +77,7 @@ def read_attribute_value_list(stream, options):
return data


def read_attribute_value_haml(stream, options):
def read_attribute_value_haml(stream, compiler):
"""
Reads an attribute value which is a block of indented Haml
"""
Expand All @@ -101,15 +101,14 @@ def read_attribute_value_haml(stream, options):

stream.ptr -= 1 # un-consume final newline which will act as separator between this and next entry

from ..compiler import Compiler
haml = '\n'.join(haml_lines)
html = Compiler(options).process(haml)
html = compiler.process(haml)

# un-format into single line
return LEADING_SPACES_REGEX.sub(' ', html).replace('\n', '').strip()


def read_ruby_attribute(stream, options):
def read_ruby_attribute(stream, compiler):
"""
Reads a Ruby style attribute, e.g. :foo => "bar" or foo: "bar"
"""
Expand Down Expand Up @@ -144,18 +143,18 @@ def read_ruby_attribute(stream, options):
if stream.text[stream.ptr] == '\n':
stream.ptr += 1

value = read_attribute_value_haml(stream, options)
value = read_attribute_value_haml(stream, compiler)
elif stream.text[stream.ptr] in ('(', '['):
value = read_attribute_value_list(stream, options)
value = read_attribute_value_list(stream, compiler)
else:
value = read_attribute_value(stream, options)
value = read_attribute_value(stream, compiler)
else:
value = True

return key, value


def read_html_attribute(stream, options):
def read_html_attribute(stream, compiler):
"""
Reads an HTML style attribute, e.g. foo="bar"
"""
Expand All @@ -178,18 +177,18 @@ def read_html_attribute(stream, options):
if stream.text[stream.ptr] == '\n':
stream.ptr += 1

value = read_attribute_value_haml(stream, options)
value = read_attribute_value_haml(stream, compiler)
elif stream.text[stream.ptr] == '[':
value = read_attribute_value_list(stream, options)
value = read_attribute_value_list(stream, compiler)
else:
value = read_attribute_value(stream, options)
value = read_attribute_value(stream, compiler)
else:
value = True

return key, value


def read_attribute_dict(stream, options):
def read_attribute_dict(stream, compiler):
"""
Reads an attribute dictionary which may use one of 3 syntaxes:
1. {:foo => "bar", :a => 3} (old Ruby)
Expand Down Expand Up @@ -228,7 +227,7 @@ def record_value(key, value):

# (foo = "bar" a=3)
if html_style:
record_value(*read_html_attribute(stream, options))
record_value(*read_html_attribute(stream, compiler))

read_whitespace(stream)

Expand All @@ -237,7 +236,7 @@ def record_value(key, value):

# {:foo => "bar", :a=>3} or {foo: "bar", a: 3}
else:
record_value(*read_ruby_attribute(stream, options))
record_value(*read_ruby_attribute(stream, compiler))

read_whitespace(stream)

Expand Down
4 changes: 2 additions & 2 deletions hamlpy/parser/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def read_tag(stream):
return (part1 + ':' + part2) if part2 else part1


def read_element(stream, options):
def read_element(stream, compiler):
"""
Reads an element, e.g. %span, #banner{style:"width: 100px"}, .ng-hide(foo=1)
"""
Expand Down Expand Up @@ -63,7 +63,7 @@ def read_element(stream, options):

attributes = OrderedDict()
while stream.ptr < stream.length and stream.text[stream.ptr] in ('{', '('):
attributes.update(read_attribute_dict(stream, options))
attributes.update(read_attribute_dict(stream, compiler))

if stream.ptr < stream.length and stream.text[stream.ptr] == '>':
stream.ptr += 1
Expand Down
2 changes: 1 addition & 1 deletion hamlpy/parser/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def read_node(stream, prev, compiler):

# peek ahead to so we don't try to parse an element from a variable node starting #{ or a Django tag ending %}
if stream.text[stream.ptr] in ELEMENT_PREFIXES and stream.text[stream.ptr:stream.ptr+2] not in ('#{', '%}'):
element = read_element(stream, compiler.options)
element = read_element(stream, compiler)
return ElementNode(element, indent, compiler)

# all other nodes are single line
Expand Down
6 changes: 3 additions & 3 deletions hamlpy/test/test_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from collections import OrderedDict

from hamlpy.compiler import Options
from hamlpy.compiler import Compiler
from hamlpy.parser.attributes import read_attribute_dict
from hamlpy.parser.core import Stream, ParseException

Expand All @@ -13,12 +13,12 @@ class AttributeDictParserTest(unittest.TestCase):

@staticmethod
def _parse(text):
return read_attribute_dict(Stream(text), Options())
return read_attribute_dict(Stream(text), Compiler())

def test_read_ruby_style_attribute_dict(self):
# empty dict
stream = Stream("{}><")
assert dict(read_attribute_dict(stream, Options())) == {}
assert dict(read_attribute_dict(stream, Compiler())) == {}
assert stream.text[stream.ptr:] == '><'

# string values
Expand Down
3 changes: 3 additions & 0 deletions hamlpy/test/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ def test_attribute_dictionaries(self):
# multiple dicts
self._test('%a(a="b"){:c => "d"} Stuff', "<a a='b' c='d'>Stuff</a>")

self._test_error('%a(b=)', "Unexpected \")\". @ \"%a(b=)\" <-")

def test_boolean_attributes(self):
self._test("%input{required}", "<input required>")
self._test("%input{required, a: 'b'}", "<input required a='b'>")
self._test("%input{a: 'b', required, b: 'c'}", "<input a='b' required b='c'>")
self._test("%input{a: 'b', required}", "<input a='b' required>")
self._test("%input{checked, required, visible}", "<input checked required visible>")
self._test("%input(checked=true)", "<input checked>")
self._test("%input(checked=true)", "<input checked='checked' />", compiler_options={'format': 'xhtml'})

def test_attribute_values_as_tuples_and_lists(self):
# id attribute as tuple
Expand Down
8 changes: 4 additions & 4 deletions hamlpy/test/test_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from collections import OrderedDict

from hamlpy.compiler import Options
from hamlpy.compiler import Compiler
from hamlpy.parser.core import Stream
from hamlpy.parser.elements import Element, read_tag, read_element

Expand All @@ -18,7 +18,7 @@ def test_read_tag(self):

def test_read_element(self):
stream = Stream('%angular:ng-repeat.my-class#my-id(class="test")></= Hello \n.next-element')
element = read_element(stream, Options())
element = read_element(stream, Compiler())
self.assertEqual(element.tag, 'angular:ng-repeat')
self.assertEqual(element.id, 'my-id')
self.assertEqual(element.classes, ['test', 'my-class'])
Expand All @@ -31,7 +31,7 @@ def test_read_element(self):
self.assertEqual(stream.text[stream.ptr:], '.next-element')

stream = Stream('%input{required} ')
element = read_element(stream, Options())
element = read_element(stream, Compiler())
self.assertEqual(element.tag, 'input')
self.assertEqual(element.id, None)
self.assertEqual(element.classes, [])
Expand Down Expand Up @@ -152,4 +152,4 @@ def test_multiline_attributes(self):

@staticmethod
def _read_element(text):
return read_element(Stream(text), Options())
return read_element(Stream(text), Compiler())

0 comments on commit e302feb

Please sign in to comment.