Просмотр исходного кода

Finishing tests for Templates; some fixes.

tags/v0.2
Ben Kurtovic 11 лет назад
Родитель
Сommit
81849013bc
2 измененных файлов: 220 добавлений и 63 удалений
  1. +14
    -7
      mwparserfromhell/nodes/template.py
  2. +206
    -56
      tests/test_template.py

+ 14
- 7
mwparserfromhell/nodes/template.py Просмотреть файл

@@ -81,7 +81,7 @@ class Template(Node):
in parameter names or values so they are not mistaken for new in parameter names or values so they are not mistaken for new
parameters. parameters.
""" """
replacement = HTMLEntity(value=ord(char))
replacement = str(HTMLEntity(value=ord(char)))
for node in code.filter_text(recursive=False): for node in code.filter_text(recursive=False):
if char in node: if char in node:
code.replace(node, node.replace(char, replacement)) code.replace(node, node.replace(char, replacement))
@@ -107,7 +107,7 @@ class Template(Node):
values = tuple(theories.values()) values = tuple(theories.values())
best = max(values) best = max(values)
confidence = float(best) / sum(values) confidence = float(best) / sum(values)
if confidence > 0.75:
if confidence >= 0.75:
return tuple(theories.keys())[values.index(best)] return tuple(theories.keys())[values.index(best)]


def _get_spacing_conventions(self, use_names): def _get_spacing_conventions(self, use_names):
@@ -205,15 +205,19 @@ class Template(Node):
If *showkey* is given, this will determine whether or not to show the If *showkey* is given, this will determine whether or not to show the
parameter's name (e.g., ``{{foo|bar}}``'s parameter has a name of parameter's name (e.g., ``{{foo|bar}}``'s parameter has a name of
``"1"`` but it is hidden); otherwise, we'll make a safe and intelligent ``"1"`` but it is hidden); otherwise, we'll make a safe and intelligent
guess. If *name* is already a parameter, we'll replace its value while
keeping the same spacing rules. We will also try to guess the dominant
spacing convention when adding a new parameter using
guess.

If *name* is already a parameter in the template, we'll replace its
value while keeping the same whitespace around it. We will also try to
guess the dominant spacing convention when adding a new parameter using
:py:meth:`_get_spacing_conventions`. :py:meth:`_get_spacing_conventions`.


If *before* is given (either a :py:class:`~.Parameter` object or a If *before* is given (either a :py:class:`~.Parameter` object or a
name), then we will place the parameter immediately before this one. name), then we will place the parameter immediately before this one.
Otherwise, it will be added at the end. This is ignored if the
parameter already exists.
Otherwise, it will be added at the end. If *before* is a name and
exists multiple times in the template, we will place it before the last
occurance. If *before* is not in the template, :py:exc:`ValueError` is
raised. The argument is ignored if the new parameter already exists.


If *preserve_spacing* is ``False``, we will avoid preserving spacing If *preserve_spacing* is ``False``, we will avoid preserving spacing
conventions when changing the value of an existing parameter or when conventions when changing the value of an existing parameter or when
@@ -231,6 +235,9 @@ class Template(Node):
self._surface_escape(value, "=") self._surface_escape(value, "=")
nodes = existing.value.nodes nodes = existing.value.nodes
if preserve_spacing: if preserve_spacing:
for i in range(2): # Ignore empty text nodes
if not nodes[i]:
nodes[i] = None
existing.value = parse_anything([nodes[0], value, nodes[1]]) existing.value = parse_anything([nodes[0], value, nodes[1]])
else: else:
existing.value = value existing.value = value


+ 206
- 56
tests/test_template.py Просмотреть файл

@@ -24,31 +24,32 @@ from __future__ import unicode_literals
import unittest import unittest


from mwparserfromhell.compat import str from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Template, Text
from mwparserfromhell.nodes import HTMLEntity, Template, Text
from mwparserfromhell.nodes.extras import Parameter from mwparserfromhell.nodes.extras import Parameter
from mwparserfromhell.smart_list import SmartList from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.wikicode import Wikicode from mwparserfromhell.wikicode import Wikicode
from ._test_tree_equality import TreeEqualityTestCase from ._test_tree_equality import TreeEqualityTestCase


wrap = lambda L: Wikicode(SmartList(L)) wrap = lambda L: Wikicode(SmartList(L))
pgens = lambda k, v: Parameter(wrap([Text(k)]), wrap([Text(v)]), True)
pgenh = lambda k, v: Parameter(wrap([Text(k)]), wrap([Text(v)]), False)
wraptext = lambda t: wrap([Text(t)])
pgens = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=True)
pgenh = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=False)


class TestTemplate(TreeEqualityTestCase): class TestTemplate(TreeEqualityTestCase):
"""Test cases for the Template node.""" """Test cases for the Template node."""


def test_unicode(self): def test_unicode(self):
"""test Template.__unicode__()""" """test Template.__unicode__()"""
node = Template(wrap([Text("foobar")]))
node = Template(wraptext("foobar"))
self.assertEqual("{{foobar}}", str(node)) self.assertEqual("{{foobar}}", str(node))
node2 = Template(wrap([Text("foo")]),
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("abc", "def")]) [pgenh("1", "bar"), pgens("abc", "def")])
self.assertEqual("{{foo|bar|abc=def}}", str(node2)) self.assertEqual("{{foo|bar|abc=def}}", str(node2))


def test_strip(self): def test_strip(self):
"""test Template.__strip__()""" """test Template.__strip__()"""
node1 = Template(wrap([Text("foobar")]))
node2 = Template(wrap([Text("foo")]),
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("abc", "def")]) [pgenh("1", "bar"), pgens("abc", "def")])
for a in (True, False): for a in (True, False):
for b in (True, False): for b in (True, False):
@@ -61,8 +62,8 @@ class TestTemplate(TreeEqualityTestCase):
getter, marker = object(), object() getter, marker = object(), object()
get = lambda code: output.append((getter, code)) get = lambda code: output.append((getter, code))
mark = lambda: output.append(marker) mark = lambda: output.append(marker)
node1 = Template(wrap([Text("foobar")]))
node2 = Template(wrap([Text("foo")]),
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("abc", "def")]) [pgenh("1", "bar"), pgens("abc", "def")])
node1.__showtree__(output.append, get, mark) node1.__showtree__(output.append, get, mark)
node2.__showtree__(output.append, get, mark) node2.__showtree__(output.append, get, mark)
@@ -76,33 +77,32 @@ class TestTemplate(TreeEqualityTestCase):


def test_name(self): def test_name(self):
"""test getter/setter for the name attribute""" """test getter/setter for the name attribute"""
name = wrap([Text("foobar")])
name = wraptext("foobar")
node1 = Template(name) node1 = Template(name)
node2 = Template(name, [pgenh("1", "bar")]) node2 = Template(name, [pgenh("1", "bar")])
self.assertIs(name, node1.name) self.assertIs(name, node1.name)
self.assertIs(name, node2.name) self.assertIs(name, node2.name)
node1.name = "asdf" node1.name = "asdf"
node2.name = "téstïng" node2.name = "téstïng"
self.assertWikicodeEqual(wrap([Text("asdf")]), node1.name)
self.assertWikicodeEqual(wrap([Text("téstïng")]), node2.name)
self.assertWikicodeEqual(wraptext("asdf"), node1.name)
self.assertWikicodeEqual(wraptext("téstïng"), node2.name)


def test_params(self): def test_params(self):
"""test getter for the params attribute""" """test getter for the params attribute"""
node1 = Template(wrap([Text("foobar")]))
node1 = Template(wraptext("foobar"))
plist = [pgenh("1", "bar"), pgens("abc", "def")] plist = [pgenh("1", "bar"), pgens("abc", "def")]
node2 = Template(wrap([Text("foo")]), plist)
node2 = Template(wraptext("foo"), plist)
self.assertEqual([], node1.params) self.assertEqual([], node1.params)
self.assertIs(plist, node2.params) self.assertIs(plist, node2.params)


def test_has_param(self): def test_has_param(self):
"""test Template.has_param()""" """test Template.has_param()"""
node1 = Template(wrap([Text("foobar")]))
node2 = Template(wrap([Text("foo")]),
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("\nabc ", "def")]) [pgenh("1", "bar"), pgens("\nabc ", "def")])
node3 = Template(wrap([Text("foo")]),
node3 = Template(wraptext("foo"),
[pgenh("1", "a"), pgens("b", "c"), pgens("1", "d")]) [pgenh("1", "a"), pgens("b", "c"), pgens("1", "d")])
node4 = Template(wrap([Text("foo")]),
[pgenh("1", "a"), pgens("b", " ")])
node4 = Template(wraptext("foo"), [pgenh("1", "a"), pgens("b", " ")])
self.assertFalse(node1.has_param("foobar")) self.assertFalse(node1.has_param("foobar"))
self.assertTrue(node2.has_param(1)) self.assertTrue(node2.has_param(1))
self.assertTrue(node2.has_param("abc")) self.assertTrue(node2.has_param("abc"))
@@ -115,16 +115,15 @@ class TestTemplate(TreeEqualityTestCase):


def test_get(self): def test_get(self):
"""test Template.get()""" """test Template.get()"""
node1 = Template(wrap([Text("foobar")]))
node1 = Template(wraptext("foobar"))
node2p1 = pgenh("1", "bar") node2p1 = pgenh("1", "bar")
node2p2 = pgens("abc", "def") node2p2 = pgens("abc", "def")
node2 = Template(wrap([Text("foo")]), [node2p1, node2p2])
node2 = Template(wraptext("foo"), [node2p1, node2p2])
node3p1 = pgens("b", "c") node3p1 = pgens("b", "c")
node3p2 = pgens("1", "d") node3p2 = pgens("1", "d")
node3 = Template(wrap([Text("foo")]),
[pgenh("1", "a"), node3p1, node3p2])
node3 = Template(wraptext("foo"), [pgenh("1", "a"), node3p1, node3p2])
node4p1 = pgens(" b", " ") node4p1 = pgens(" b", " ")
node4 = Template(wrap([Text("foo")]), [pgenh("1", "a"), node4p1])
node4 = Template(wraptext("foo"), [pgenh("1", "a"), node4p1])
self.assertRaises(ValueError, node1.get, "foobar") self.assertRaises(ValueError, node1.get, "foobar")
self.assertIs(node2p1, node2.get(1)) self.assertIs(node2p1, node2.get(1))
self.assertIs(node2p2, node2.get("abc")) self.assertIs(node2p2, node2.get("abc"))
@@ -135,46 +134,197 @@ class TestTemplate(TreeEqualityTestCase):


def test_add(self): def test_add(self):
"""test Template.add()""" """test Template.add()"""
# add new param with showkey to end
# add new param without showkey to end
# add new param to end with an escapable |
# add new param with showkey to end with an escapable =
# add new param without showkey to end with an escapable =
# add new param with showkey to end preserving spacing (x3)
# add new param without showkey to end not preserving spacing
# add new param guessing showkey where key is to be shown
# add new param guessing showkey where key is to be shown with an escapable =
# add new param guessing showkey where key is not to be shown
# add new param guessing showkey where key is not to be shown with an escapable =
# add existing parameter without modifying showkey
# add existing parameter without modifying showkey with an escapable =
# add existing parameter with modifying showkey
# add existing parameter with modifying showkey with an escapable =
# add existing parameter preserving spacing (x3)
# add existing parameter not preserving spacing
# add existing parameter when there are multiple params involved
# add existing parameter when there are multiple params involved; params with dependencies
node1 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
node2 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
node3 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
node4 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
node5 = Template(wraptext("a"), [pgens("b", "c"),
pgens(" d ", "e")])
node6 = Template(wraptext("a"), [pgens("b", "c"), pgens("b", "d"),
pgens("b", "e")])
node7 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
node8p = pgenh("1", "d")
node8 = Template(wraptext("a"), [pgens("b", "c"), node8p])
node9 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "d")])
node10 = Template(wraptext("a"), [pgens("b", "c"), pgenh("1", "e")])
node11 = Template(wraptext("a"), [pgens("b", "c")])
node12 = Template(wraptext("a"), [pgens("b", "c")])
node13 = Template(wraptext("a"), [pgens("\nb ", " c"),
pgens("\nd ", " e"),
pgens("\nf ", " g")])
node14 = Template(wraptext("a\n"), [pgens("b ", "c\n"),
pgens("d ", " e"),
pgens("f ", "g\n"),
pgens("h ", " i\n")])
node15 = Template(wraptext("a"), [pgens("b ", " c\n"),
pgens("\nd ", " e"),
pgens("\nf ", "g ")])
node16 = Template(wraptext("a"), [pgens("\nb ", " c"),
pgens("\nd ", " e"),
pgens("\nf ", " g")])
node17 = Template(wraptext("a"), [pgens("\nb ", " c"),
pgens("\nd ", " e"),
pgens("\nf ", " g")])
node18 = Template(wraptext("a\n"), [pgens("b ", "c\n"),
pgens("d ", " e"),
pgens("f ", "g\n"),
pgens("h ", " i\n")])
node19 = Template(wraptext("a"), [pgens("b ", " c\n"),
pgens("\nd ", " e"),
pgens("\nf ", "g ")])
node20 = Template(wraptext("a"), [pgens("\nb ", " c"),
pgens("\nd ", " e"),
pgens("\nf ", " g")])
node21 = Template(wraptext("a"), [pgenh("1", "b")])
node22 = Template(wraptext("a"), [pgenh("1", "b")])
node23 = Template(wraptext("a"), [pgenh("1", "b")])
node24 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
pgenh("3", "d"), pgenh("4", "e")])
node25 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
pgens("4", "d"), pgens("5", "e")])
node26 = Template(wraptext("a"), [pgenh("1", "b"), pgenh("2", "c"),
pgens("4", "d"), pgens("5", "e")])
node27 = Template(wraptext("a"), [pgenh("1", "b")])
node28 = Template(wraptext("a"), [pgenh("1", "b")])
node29 = Template(wraptext("a"), [pgens("b", "c")])
node30 = Template(wraptext("a"), [pgenh("1", "b")])
node31 = Template(wraptext("a"), [pgenh("1", "b")])
node32 = Template(wraptext("a"), [pgens("1", "b")])
node33 = Template(wraptext("a"), [pgens("\nb ", " c"),
pgens("\nd ", " e"),
pgens("\nf ", " g")])
node34 = Template(wraptext("a\n"), [pgens("b ", "c\n"),
pgens("d ", " e"),
pgens("f ", "g\n"),
pgens("h ", " i\n")])
node35 = Template(wraptext("a"), [pgens("b ", " c\n"),
pgens("\nd ", " e"),
pgens("\nf ", "g ")])
node36 = Template(wraptext("a"), [pgens("\nb ", " c "),
pgens("\nd ", " e "),
pgens("\nf ", " g ")])
node37 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
pgens("b", "f"), pgens("b", "h"),
pgens("i", "j")])
node37 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
pgens("b", "f"), pgens("b", "h"),
pgens("i", "j")])
node38 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
pgens("1", "c"), pgens("2", "d")])
node39 = Template(wraptext("a"), [pgens("1", "b"), pgens("x", "y"),
pgenh("1", "c"), pgenh("2", "d")])
node40 = Template(wraptext("a"), [pgens("b", "c"), pgens("d", "e"),
pgens("f", "g")])

node1.add("e", "f", showkey=True)
node2.add(2, "g", showkey=False)
node3.add("e", "foo|bar", showkey=True)
node4.add("e", "f", showkey=True, before="b")
node5.add("f", "g", showkey=True, before=" d ")
node6.add("f", "g", showkey=True, before="b")
self.assertRaises(ValueError, node7.add, "e", "f", showkey=True,
before="q")
node8.add("e", "f", showkey=True, before=node8p)
node9.add("e", "f", showkey=True, before=pgenh("1", "d"))
self.assertRaises(ValueError, node10.add, "e", "f", showkey=True,
before=pgenh("1", "d"))
node11.add("d", "foo=bar", showkey=True)
node12.add("1", "foo=bar", showkey=False)
node13.add("h", "i", showkey=True)
node14.add("j", "k", showkey=True)
node15.add("h", "i", showkey=True)
node16.add("h", "i", showkey=True, preserve_spacing=False)
node17.add("h", "i", showkey=False)
node18.add("j", "k", showkey=False)
node19.add("h", "i", showkey=False)
node20.add("h", "i", showkey=False, preserve_spacing=False)
node21.add("2", "c")
node22.add("3", "c")
node23.add("c", "d")
node24.add("5", "f")
node25.add("3", "f")
node26.add("6", "f")
node27.add("c", "foo=bar")
node28.add("2", "foo=bar")
node29.add("b", "d")
node30.add("1", "foo=bar")
node31.add("1", "foo=bar", showkey=True)
node32.add("1", "foo=bar", showkey=False)
node33.add("d", "foo")
node34.add("f", "foo")
node35.add("f", "foo")
node36.add("d", "foo", preserve_spacing=False)
node37.add("b", "k")
node38.add("1", "e")
node39.add("1", "e")
node40.add("d", "h", before="b")

self.assertEquals("{{a|b=c|d|e=f}}", node1)
self.assertEquals("{{a|b=c|d|g}}", node2)
self.assertEquals("{{a|b=c|d|e=foo|bar}}", node3)
self.assertIsInstance(node3.params[2].value.get(1), HTMLEntity)
self.assertEquals("{{a|e=f|b=c|d}}", node4)
self.assertEquals("{{a|b=c|f=g| d =e}}", node5)
self.assertEquals("{{a|b=c|b=d|f=g|b=e}}", node6)
self.assertEquals("{{a|b=c|d}}", node7)
self.assertEquals("{{a|b=c|e=f|d}}", node8)
self.assertEquals("{{a|b=c|e=f|d}}", node9)
self.assertEquals("{{a|b=c|e}}", node10)
self.assertEquals("{{a|b=c|d=foo=bar}}", node11)
self.assertEquals("{{a|b=c|foo=bar}}", node12)
self.assertIsInstance(node12.params[1].value.get(1), HTMLEntity)
self.assertEquals("{{a|\nb = c|\nd = e|\nf = g|\nh = i}}", node13)
self.assertEquals("{{a\n|b =c\n|d = e|f =g\n|h = i\n|j =k\n}}", node14)
self.assertEquals("{{a|b = c\n|\nd = e|\nf =g |h =i}}", node15)
self.assertEquals("{{a|\nb = c|\nd = e|\nf = g|h=i}}", node16)
self.assertEquals("{{a|\nb = c|\nd = e|\nf = g| i}}", node17)
self.assertEquals("{{a\n|b =c\n|d = e|f =g\n|h = i\n|k\n}}", node18)
self.assertEquals("{{a|b = c\n|\nd = e|\nf =g |i}}", node19)
self.assertEquals("{{a|\nb = c|\nd = e|\nf = g|i}}", node20)
self.assertEquals("{{a|b|c}}", node21)
self.assertEquals("{{a|b|3=c}}", node22)
self.assertEquals("{{a|b|c=d}}", node23)
self.assertEquals("{{a|b|c|d|e|f}}", node24)
self.assertEquals("{{a|b|c|4=d|5=e|f}}", node25)
self.assertEquals("{{a|b|c|4=d|5=e|6=f}}", node26)
self.assertEquals("{{a|b|c=foo=bar}}", node27)
self.assertEquals("{{a|b|foo=bar}}", node28)
self.assertIsInstance(node28.params[1].value.get(1), HTMLEntity)
self.assertEquals("{{a|b=d}}", node29)
self.assertEquals("{{a|foo=bar}}", node30)
self.assertIsInstance(node30.params[0].value.get(1), HTMLEntity)
self.assertEquals("{{a|1=foo=bar}}", node31)
self.assertEquals("{{a|foo=bar}}", node32)
self.assertIsInstance(node32.params[0].value.get(1), HTMLEntity)
self.assertEquals("{{a|\nb = c|\nd = foo|\nf = g}}", node33)
self.assertEquals("{{a\n|b =c\n|d = e|f =foo\n|h = i\n}}", node34)
self.assertEquals("{{a|b = c\n|\nd = e|\nf =foo }}", node35)
self.assertEquals("{{a|\nb = c |\nd =foo|\nf = g }}", node36)
self.assertEquals("{{a|b=k|d=e|i=j}}", node37)
self.assertEquals("{{a|1=e|x=y|2=d}}", node38)
self.assertEquals("{{a|x=y|e|d}}", node39)
self.assertEquals("{{a|b=c|d=h|f=g}}", node40)


def test_remove(self): def test_remove(self):
"""test Template.remove()""" """test Template.remove()"""
node1 = Template(wrap([Text("foobar")]))
node2 = Template(wrap([Text("foo")]), [pgenh("1", "bar"),
pgens("abc", "def")])
node3 = Template(wrap([Text("foo")]), [pgenh("1", "bar"),
pgens("abc", "def")])
node4 = Template(wrap([Text("foo")]), [pgenh("1", "bar"),
pgenh("2", "baz")])
node5 = Template(wrap([Text("foo")]), [
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"), [pgenh("1", "bar"),
pgens("abc", "def")])
node3 = Template(wraptext("foo"), [pgenh("1", "bar"),
pgens("abc", "def")])
node4 = Template(wraptext("foo"), [pgenh("1", "bar"),
pgenh("2", "baz")])
node5 = Template(wraptext("foo"), [
pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")]) pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
node6 = Template(wrap([Text("foo")]), [
node6 = Template(wraptext("foo"), [
pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")]) pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
node7 = Template(wrap([Text("foo")]), [
node7 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")]) pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
node8 = Template(wrap([Text("foo")]), [
node8 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")]) pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
node9 = Template(wrap([Text("foo")]), [
node9 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")]) pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
node10 = Template(wrap([Text("foo")]), [
node10 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")]) pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])


node2.remove("1") node2.remove("1")


Загрузка…
Отмена
Сохранить