Browse Source

Merge branch 'feature/node_tests' into develop (#7)

tags/v0.2
Ben Kurtovic 11 years ago
parent
commit
419e5af958
16 changed files with 1257 additions and 163 deletions
  1. +63
    -31
      mwparserfromhell/nodes/html_entity.py
  2. +60
    -47
      mwparserfromhell/nodes/template.py
  3. +4
    -1
      mwparserfromhell/nodes/wikilink.py
  4. +1
    -7
      mwparserfromhell/wikicode.py
  5. +13
    -0
      tests/_test_tree_equality.py
  6. +107
    -0
      tests/test_argument.py
  7. +40
    -49
      tests/test_builder.py
  8. +68
    -0
      tests/test_comment.py
  9. +91
    -0
      tests/test_heading.py
  10. +169
    -0
      tests/test_html_entity.py
  11. +75
    -0
      tests/test_parameter.py
  12. +9
    -12
      tests/test_parser.py
  13. +364
    -0
      tests/test_template.py
  14. +75
    -0
      tests/test_text.py
  15. +11
    -16
      tests/test_utils.py
  16. +107
    -0
      tests/test_wikilink.py

+ 63
- 31
mwparserfromhell/nodes/html_entity.py View File

@@ -23,7 +23,7 @@
from __future__ import unicode_literals

from . import Node
from ..compat import htmlentities, str
from ..compat import htmlentities, py3k, str

__all__ = ["HTMLEntity"]

@@ -63,28 +63,31 @@ class HTMLEntity(Node):
return self.normalize()
return self

def _unichr(self, value):
"""Implement the builtin unichr() with support for non-BMP code points.
if not py3k:
@staticmethod
def _unichr(value):
"""Implement builtin unichr() with support for non-BMP code points.

On wide Python builds, this functions like the normal unichr(). On
narrow builds, this returns the value's corresponding surrogate pair.
"""
try:
return unichr(value)
except ValueError:
# Test whether we're on the wide or narrow Python build. Check the
# length of a non-BMP code point (U+1F64A, SPEAK-NO-EVIL MONKEY):
if len("\U0001F64A") == 2:
# Ensure this is within the range we can encode:
if value > 0x10FFFF:
raise ValueError("unichr() arg not in range(0x110000)")
code = value - 0x10000
if value < 0: # Invalid code point
raise
lead = 0xD800 + (code >> 10)
trail = 0xDC00 + (code % (1 << 10))
return unichr(lead) + unichr(trail)
raise
On wide Python builds, this functions like the normal unichr(). On
narrow builds, this returns the value's encoded surrogate pair.
"""
try:
return unichr(value)
except ValueError:
# Test whether we're on the wide or narrow Python build. Check
# the length of a non-BMP code point
# (U+1F64A, SPEAK-NO-EVIL MONKEY):
if len("\U0001F64A") == 2:
# Ensure this is within the range we can encode:
if value > 0x10FFFF:
raise ValueError("unichr() arg not in range(0x110000)")
code = value - 0x10000
if value < 0: # Invalid code point
raise
lead = 0xD800 + (code >> 10)
trail = 0xDC00 + (code % (1 << 10))
return unichr(lead) + unichr(trail)
raise

@property
def value(self):
@@ -119,19 +122,47 @@ class HTMLEntity(Node):
@value.setter
def value(self, newval):
newval = str(newval)
if newval not in htmlentities.entitydefs:
test = int(self.value, 16)
if test < 0 or (test > 0x10FFFF and int(self.value) > 0x10FFFF):
raise ValueError(newval)
try:
int(newval)
except ValueError:
try:
int(newval, 16)
except ValueError:
if newval not in htmlentities.entitydefs:
raise ValueError("entity value is not a valid name")
self._named = True
self._hexadecimal = False
else:
if int(newval, 16) < 0 or int(newval, 16) > 0x10FFFF:
raise ValueError("entity value is not in range(0x110000)")
self._named = False
self._hexadecimal = True
else:
test = int(newval, 16 if self.hexadecimal else 10)
if test < 0 or test > 0x10FFFF:
raise ValueError("entity value is not in range(0x110000)")
self._named = False
self._value = newval

@named.setter
def named(self, newval):
self._named = bool(newval)
newval = bool(newval)
if newval and self.value not in htmlentities.entitydefs:
raise ValueError("entity value is not a valid name")
if not newval:
try:
int(self.value, 16)
except ValueError:
err = "current entity value is not a valid Unicode codepoint"
raise ValueError(err)
self._named = newval

@hexadecimal.setter
def hexadecimal(self, newval):
self._hexadecimal = bool(newval)
newval = bool(newval)
if newval and self.named:
raise ValueError("a named entity cannot be hexadecimal")
self._hexadecimal = newval

@hex_char.setter
def hex_char(self, newval):
@@ -142,8 +173,9 @@ class HTMLEntity(Node):

def normalize(self):
"""Return the unicode character represented by the HTML entity."""
chrfunc = chr if py3k else HTMLEntity._unichr
if self.named:
return unichr(htmlentities.name2codepoint[self.value])
return chrfunc(htmlentities.name2codepoint[self.value])
if self.hexadecimal:
return self._unichr(int(self.value, 16))
return self._unichr(int(self.value))
return chrfunc(int(self.value, 16))
return chrfunc(int(self.value))

+ 60
- 47
mwparserfromhell/nodes/template.py View File

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

def _get_spacing_conventions(self, use_names):
@@ -142,9 +142,9 @@ class Template(Node):
return False
return True

def _remove_without_field(self, param, i, force_no_field):
def _remove_without_field(self, param, i):
"""Return False if a parameter name should be kept, otherwise True."""
if not param.showkey and not force_no_field:
if not param.showkey:
dependents = [not after.showkey for after in self.params[i+1:]]
if any(dependents):
return False
@@ -183,11 +183,10 @@ class Template(Node):
def get(self, name):
"""Get the parameter whose name is *name*.

The returned object is a
:py:class:`~.Parameter` instance. Raises :py:exc:`ValueError` if no
parameter has this name. Since multiple parameters can have the same
name, we'll return the last match, since the last parameter is the only
one read by the MediaWiki parser.
The returned object is a :py:class:`~.Parameter` instance. Raises
:py:exc:`ValueError` if no parameter has this name. Since multiple
parameters can have the same name, we'll return the last match, since
the last parameter is the only one read by the MediaWiki parser.
"""
name = name.strip() if isinstance(name, basestring) else str(name)
for param in reversed(self.params):
@@ -195,20 +194,34 @@ class Template(Node):
return param
raise ValueError(name)

def add(self, name, value, showkey=None, force_nonconformity=False):
def add(self, name, value, showkey=None, before=None,
preserve_spacing=True):
"""Add a parameter to the template with a given *name* and *value*.

*name* and *value* can be anything parasable by
:py:func:`.utils.parse_anything`; pipes (and equal signs, if
appropriate) are automatically escaped from *value* where applicable.
:py:func:`.utils.parse_anything`; pipes and equal signs are
automatically escaped from *value* when appropriate.

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
``"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 unless *force_nonconformity* is
``True``. We will also try to guess the dominant spacing convention
when adding a new parameter using :py:meth:`_get_spacing_conventions`
unless *force_nonconformity* is ``True``.
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`.

If *before* is given (either a :py:class:`~.Parameter` object or a
name), then we will place the parameter immediately before this one.
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
conventions when changing the value of an existing parameter or when
adding a new one.
"""
name, value = parse_anything(name), parse_anything(value)
self._surface_escape(value, "|")
@@ -217,14 +230,17 @@ class Template(Node):
self.remove(name, keep_field=True)
existing = self.get(name)
if showkey is not None:
if not showkey:
self._surface_escape(value, "=")
existing.showkey = showkey
if not existing.showkey:
self._surface_escape(value, "=")
nodes = existing.value.nodes
if force_nonconformity:
existing.value = value
else:
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]])
else:
existing.value = value
return existing

if showkey is None:
@@ -246,43 +262,38 @@ class Template(Node):
if not showkey:
self._surface_escape(value, "=")

if not force_nonconformity:
if preserve_spacing:
before_n, after_n = self._get_spacing_conventions(use_names=True)
if before_n and after_n:
name = parse_anything([before_n, name, after_n])
elif before_n:
name = parse_anything([before_n, name])
elif after_n:
name = parse_anything([name, after_n])

before_v, after_v = self._get_spacing_conventions(use_names=False)
if before_v and after_v:
value = parse_anything([before_v, value, after_v])
elif before_v:
value = parse_anything([before_v, value])
elif after_v:
value = parse_anything([value, after_v])
name = parse_anything([before_n, name, after_n])
value = parse_anything([before_v, value, after_v])

param = Parameter(name, value, showkey)
self.params.append(param)
if before:
if not isinstance(before, Parameter):
before = self.get(before)
self.params.insert(self.params.index(before), param)
else:
self.params.append(param)
return param

def remove(self, name, keep_field=False, force_no_field=False):
def remove(self, name, keep_field=False):
"""Remove a parameter from the template whose name is *name*.

If *keep_field* is ``True``, we will keep the parameter's name, but
blank its value. Otherwise, we will remove the parameter completely
*unless* other parameters are dependent on it (e.g. removing ``bar``
from ``{{foo|bar|baz}}`` is unsafe because ``{{foo|baz}}`` is not what
we expected, so ``{{foo||baz}}`` will be produced instead), unless
*force_no_field* is also ``True``. If the parameter shows up multiple
times in the template, we will remove all instances of it (and keep
one if *keep_field* is ``True`` - that being the first instance if
none of the instances have dependents, otherwise that instance will be
kept).
we expected, so ``{{foo||baz}}`` will be produced instead).
If the parameter shows up multiple times in the template, we will
remove all instances of it (and keep one if *keep_field* is ``True`` -
the first instance if none have dependents, otherwise the one with
dependents will be kept).
"""
name = name.strip() if isinstance(name, basestring) else str(name)
removed = False
to_remove =[]
for i, param in enumerate(self.params):
if param.name.strip() == name:
if keep_field:
@@ -290,13 +301,15 @@ class Template(Node):
self._blank_param_value(param.value)
keep_field = False
else:
self.params.remove(param)
to_remove.append(param)
else:
if self._remove_without_field(param, i, force_no_field):
self.params.remove(param)
if self._remove_without_field(param, i):
to_remove.append(param)
else:
self._blank_param_value(param.value)
if not removed:
removed = True
if not removed:
raise ValueError(name)
for param in to_remove:
self.params.remove(param)

+ 4
- 1
mwparserfromhell/nodes/wikilink.py View File

@@ -79,4 +79,7 @@ class Wikilink(Node):

@text.setter
def text(self, value):
self._text = parse_anything(value)
if value is None:
self._text = None
else:
self._text = parse_anything(value)

+ 1
- 7
mwparserfromhell/wikicode.py View File

@@ -88,13 +88,7 @@ class Wikicode(StringMixIn):
If *obj* is a ``Node``, the function will test whether they are the
same object, otherwise it will compare them with ``==``.
"""
if isinstance(obj, Node):
if node is obj:
return True
else:
if node == obj:
return True
return False
return (node is obj) if isinstance(obj, Node) else (node == obj)

def _contains(self, nodes, obj):
"""Return ``True`` if *obj* is inside of *nodes*, else ``False``.


+ 13
- 0
tests/_test_tree_equality.py View File

@@ -26,8 +26,21 @@ from unittest import TestCase
from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity,
Tag, Template, Text, Wikilink)
from mwparserfromhell.nodes.extras import Attribute, Parameter
from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.wikicode import Wikicode

wrap = lambda L: Wikicode(SmartList(L))
wraptext = lambda *args: wrap([Text(t) for t in args])

def getnodes(code):
"""Iterate over all child nodes of a given parent node.

Imitates Wikicode._get_all_nodes().
"""
for node in code.nodes:
for context, child in node.__iternodes__(getnodes):
yield child

class TreeEqualityTestCase(TestCase):
"""A base test case with support for comparing the equality of node trees.



+ 107
- 0
tests/test_argument.py View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Argument, Text

from ._test_tree_equality import TreeEqualityTestCase, getnodes, wrap, wraptext

class TestArgument(TreeEqualityTestCase):
"""Test cases for the Argument node."""

def test_unicode(self):
"""test Argument.__unicode__()"""
node = Argument(wraptext("foobar"))
self.assertEqual("{{{foobar}}}", str(node))
node2 = Argument(wraptext("foo"), wraptext("bar"))
self.assertEqual("{{{foo|bar}}}", str(node2))

def test_iternodes(self):
"""test Argument.__iternodes__()"""
node1n1 = Text("foobar")
node2n1, node2n2, node2n3 = Text("foo"), Text("bar"), Text("baz")
node1 = Argument(wrap([node1n1]))
node2 = Argument(wrap([node2n1]), wrap([node2n2, node2n3]))
gen1 = node1.__iternodes__(getnodes)
gen2 = node2.__iternodes__(getnodes)
self.assertEqual((None, node1), next(gen1))
self.assertEqual((None, node2), next(gen2))
self.assertEqual((node1.name, node1n1), next(gen1))
self.assertEqual((node2.name, node2n1), next(gen2))
self.assertEqual((node2.default, node2n2), next(gen2))
self.assertEqual((node2.default, node2n3), next(gen2))
self.assertRaises(StopIteration, next, gen1)
self.assertRaises(StopIteration, next, gen2)

def test_strip(self):
"""test Argument.__strip__()"""
node = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foo"), wraptext("bar"))
for a in (True, False):
for b in (True, False):
self.assertIs(None, node.__strip__(a, b))
self.assertEqual("bar", node2.__strip__(a, b))

def test_showtree(self):
"""test Argument.__showtree__()"""
output = []
getter, marker = object(), object()
get = lambda code: output.append((getter, code))
mark = lambda: output.append(marker)
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foo"), wraptext("bar"))
node1.__showtree__(output.append, get, mark)
node2.__showtree__(output.append, get, mark)
valid = [
"{{{", (getter, node1.name), "}}}", "{{{", (getter, node2.name),
" | ", marker, (getter, node2.default), "}}}"]
self.assertEqual(valid, output)

def test_name(self):
"""test getter/setter for the name attribute"""
name = wraptext("foobar")
node1 = Argument(name)
node2 = Argument(name, wraptext("baz"))
self.assertIs(name, node1.name)
self.assertIs(name, node2.name)
node1.name = "héhehé"
node2.name = "héhehé"
self.assertWikicodeEqual(wraptext("héhehé"), node1.name)
self.assertWikicodeEqual(wraptext("héhehé"), node2.name)

def test_default(self):
"""test getter/setter for the default attribute"""
default = wraptext("baz")
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foobar"), default)
self.assertIs(None, node1.default)
self.assertIs(default, node2.default)
node1.default = "buzz"
node2.default = None
self.assertWikicodeEqual(wraptext("buzz"), node1.default)
self.assertIs(None, node2.default)

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 40
- 49
tests/test_builder.py View File

@@ -28,12 +28,8 @@ from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity,
from mwparserfromhell.nodes.extras import Attribute, Parameter
from mwparserfromhell.parser import tokens
from mwparserfromhell.parser.builder import Builder
from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.wikicode import Wikicode

from ._test_tree_equality import TreeEqualityTestCase

wrap = lambda L: Wikicode(SmartList(L))
from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

class TestBuilder(TreeEqualityTestCase):
"""Tests for the builder, which turns tokens into Wikicode objects."""
@@ -44,10 +40,10 @@ class TestBuilder(TreeEqualityTestCase):
def test_text(self):
"""tests for building Text nodes"""
tests = [
([tokens.Text(text="foobar")], wrap([Text("foobar")])),
([tokens.Text(text="fóóbar")], wrap([Text("fóóbar")])),
([tokens.Text(text="foobar")], wraptext("foobar")),
([tokens.Text(text="fóóbar")], wraptext("fóóbar")),
([tokens.Text(text="spam"), tokens.Text(text="eggs")],
wrap([Text("spam"), Text("eggs")])),
wraptext("spam", "eggs")),
]
for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -57,25 +53,24 @@ class TestBuilder(TreeEqualityTestCase):
tests = [
([tokens.TemplateOpen(), tokens.Text(text="foobar"),
tokens.TemplateClose()],
wrap([Template(wrap([Text("foobar")]))])),
wrap([Template(wraptext("foobar"))])),

([tokens.TemplateOpen(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.TemplateClose()],
wrap([Template(wrap([Text("spam"), Text("eggs")]))])),
wrap([Template(wraptext("spam", "eggs"))])),

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateClose()],
wrap([Template(wrap([Text("foo")]), params=[
Parameter(wrap([Text("1")]), wrap([Text("bar")]),
showkey=False)])])),
wrap([Template(wraptext("foo"), params=[
Parameter(wraptext("1"), wraptext("bar"), showkey=False)])])),

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateParamEquals(), tokens.Text(text="baz"),
tokens.TemplateClose()],
wrap([Template(wrap([Text("foo")]), params=[
Parameter(wrap([Text("bar")]), wrap([Text("baz")]))])])),
wrap([Template(wraptext("foo"), params=[
Parameter(wraptext("bar"), wraptext("baz"))])])),

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
@@ -86,14 +81,12 @@ class TestBuilder(TreeEqualityTestCase):
tokens.TemplateParamEquals(), tokens.Text(text="buff"),
tokens.TemplateParamSeparator(), tokens.Text(text="baff"),
tokens.TemplateClose()],
wrap([Template(wrap([Text("foo")]), params=[
Parameter(wrap([Text("bar")]), wrap([Text("baz")])),
Parameter(wrap([Text("1")]), wrap([Text("biz")]),
showkey=False),
Parameter(wrap([Text("2")]), wrap([Text("buzz")]),
showkey=False),
Parameter(wrap([Text("3")]), wrap([Text("buff")])),
Parameter(wrap([Text("3")]), wrap([Text("baff")]),
wrap([Template(wraptext("foo"), params=[
Parameter(wraptext("bar"), wraptext("baz")),
Parameter(wraptext("1"), wraptext("biz"), showkey=False),
Parameter(wraptext("2"), wraptext("buzz"), showkey=False),
Parameter(wraptext("3"), wraptext("buff")),
Parameter(wraptext("3"), wraptext("baff"),
showkey=False)])])),
]
for test, valid in tests:
@@ -104,23 +97,22 @@ class TestBuilder(TreeEqualityTestCase):
tests = [
([tokens.ArgumentOpen(), tokens.Text(text="foobar"),
tokens.ArgumentClose()],
wrap([Argument(wrap([Text("foobar")]))])),
wrap([Argument(wraptext("foobar"))])),

([tokens.ArgumentOpen(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.ArgumentClose()],
wrap([Argument(wrap([Text("spam"), Text("eggs")]))])),
wrap([Argument(wraptext("spam", "eggs"))])),

([tokens.ArgumentOpen(), tokens.Text(text="foo"),
tokens.ArgumentSeparator(), tokens.Text(text="bar"),
tokens.ArgumentClose()],
wrap([Argument(wrap([Text("foo")]), wrap([Text("bar")]))])),
wrap([Argument(wraptext("foo"), wraptext("bar"))])),

([tokens.ArgumentOpen(), tokens.Text(text="foo"),
tokens.Text(text="bar"), tokens.ArgumentSeparator(),
tokens.Text(text="baz"), tokens.Text(text="biz"),
tokens.ArgumentClose()],
wrap([Argument(wrap([Text("foo"), Text("bar")]),
wrap([Text("baz"), Text("biz")]))])),
wrap([Argument(wraptext("foo", "bar"), wraptext("baz", "biz"))])),
]
for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -130,23 +122,22 @@ class TestBuilder(TreeEqualityTestCase):
tests = [
([tokens.WikilinkOpen(), tokens.Text(text="foobar"),
tokens.WikilinkClose()],
wrap([Wikilink(wrap([Text("foobar")]))])),
wrap([Wikilink(wraptext("foobar"))])),

([tokens.WikilinkOpen(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.WikilinkClose()],
wrap([Wikilink(wrap([Text("spam"), Text("eggs")]))])),
wrap([Wikilink(wraptext("spam", "eggs"))])),

([tokens.WikilinkOpen(), tokens.Text(text="foo"),
tokens.WikilinkSeparator(), tokens.Text(text="bar"),
tokens.WikilinkClose()],
wrap([Wikilink(wrap([Text("foo")]), wrap([Text("bar")]))])),
wrap([Wikilink(wraptext("foo"), wraptext("bar"))])),

([tokens.WikilinkOpen(), tokens.Text(text="foo"),
tokens.Text(text="bar"), tokens.WikilinkSeparator(),
tokens.Text(text="baz"), tokens.Text(text="biz"),
tokens.WikilinkClose()],
wrap([Wikilink(wrap([Text("foo"), Text("bar")]),
wrap([Text("baz"), Text("biz")]))])),
wrap([Wikilink(wraptext("foo", "bar"), wraptext("baz", "biz"))])),
]
for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -176,11 +167,11 @@ class TestBuilder(TreeEqualityTestCase):
tests = [
([tokens.HeadingStart(level=2), tokens.Text(text="foobar"),
tokens.HeadingEnd()],
wrap([Heading(wrap([Text("foobar")]), 2)])),
wrap([Heading(wraptext("foobar"), 2)])),

([tokens.HeadingStart(level=4), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.HeadingEnd()],
wrap([Heading(wrap([Text("spam"), Text("eggs")]), 4)])),
wrap([Heading(wraptext("spam", "eggs"), 4)])),
]
for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -190,11 +181,11 @@ class TestBuilder(TreeEqualityTestCase):
tests = [
([tokens.CommentStart(), tokens.Text(text="foobar"),
tokens.CommentEnd()],
wrap([Comment(wrap([Text("foobar")]))])),
wrap([Comment(wraptext("foobar"))])),

([tokens.CommentStart(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.CommentEnd()],
wrap([Comment(wrap([Text("spam"), Text("eggs")]))])),
wrap([Comment(wraptext("spam", "eggs"))])),
]
for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -218,10 +209,10 @@ class TestBuilder(TreeEqualityTestCase):
tokens.TemplateOpen(), tokens.Text(text="bin"),
tokens.TemplateClose(), tokens.TemplateClose()]
valid = wrap(
[Template(wrap([Template(wrap([Template(wrap([Template(wrap([Text(
"foo")])), Text("bar")]), params=[Parameter(wrap([Text("baz")]),
wrap([Text("biz")]))]), Text("buzz")])), Text("usr")]), params=[
Parameter(wrap([Text("1")]), wrap([Template(wrap([Text("bin")]))]),
[Template(wrap([Template(wrap([Template(wrap([Template(wraptext(
"foo")), Text("bar")]), params=[Parameter(wraptext("baz"),
wraptext("biz"))]), Text("buzz")])), Text("usr")]), params=[
Parameter(wraptext("1"), wrap([Template(wraptext("bin"))]),
showkey=False)])])
self.assertWikicodeEqual(valid, self.builder.build(test))

@@ -247,14 +238,14 @@ class TestBuilder(TreeEqualityTestCase):
tokens.Text(text="nbsp"), tokens.HTMLEntityEnd(),
tokens.TemplateClose()]
valid = wrap(
[Template(wrap([Text("a")]), params=[Parameter(wrap([Text("1")]),
wrap([Text("b")]), showkey=False), Parameter(wrap([Text("2")]),
wrap([Template(wrap([Text("c")]), params=[Parameter(wrap([Text("1")
]), wrap([Wikilink(wrap([Text("d")])), Argument(wrap([Text("e")]))]
), showkey=False)])]), showkey=False)]), Wikilink(wrap([Text("f")]
), wrap([Argument(wrap([Text("g")])), Comment(wrap([Text("h")]))])
), Template(wrap([Text("i")]), params=[Parameter(wrap([Text("j")]),
wrap([HTMLEntity("nbsp", named=True)]))])])
[Template(wraptext("a"), params=[Parameter(wraptext("1"), wraptext(
"b"), showkey=False), Parameter(wraptext("2"), wrap([Template(
wraptext("c"), params=[Parameter(wraptext("1"), wrap([Wikilink(
wraptext("d")), Argument(wraptext("e"))]), showkey=False)])]),
showkey=False)]), Wikilink(wraptext("f"), wrap([Argument(wraptext(
"g")), Comment(wraptext("h"))])), Template(wraptext("i"), params=[
Parameter(wraptext("j"), wrap([HTMLEntity("nbsp",
named=True)]))])])
self.assertWikicodeEqual(valid, self.builder.build(test))

if __name__ == "__main__":


+ 68
- 0
tests/test_comment.py View File

@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Comment

from ._test_tree_equality import TreeEqualityTestCase

class TestComment(TreeEqualityTestCase):
"""Test cases for the Comment node."""

def test_unicode(self):
"""test Comment.__unicode__()"""
node = Comment("foobar")
self.assertEqual("<!--foobar-->", str(node))

def test_iternodes(self):
"""test Comment.__iternodes__()"""
node = Comment("foobar")
gen = node.__iternodes__(None)
self.assertEqual((None, node), next(gen))
self.assertRaises(StopIteration, next, gen)

def test_strip(self):
"""test Comment.__strip__()"""
node = Comment("foobar")
for a in (True, False):
for b in (True, False):
self.assertIs(None, node.__strip__(a, b))

def test_showtree(self):
"""test Comment.__showtree__()"""
output = []
node = Comment("foobar")
node.__showtree__(output.append, None, None)
self.assertEqual(["<!--foobar-->"], output)

def test_contents(self):
"""test getter/setter for the contents attribute"""
node = Comment("foobar")
self.assertEqual("foobar", node.contents)
node.contents = "barfoo"
self.assertEqual("barfoo", node.contents)

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 91
- 0
tests/test_heading.py View File

@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Heading, Text

from ._test_tree_equality import TreeEqualityTestCase, getnodes, wrap, wraptext

class TestHeading(TreeEqualityTestCase):
"""Test cases for the Heading node."""

def test_unicode(self):
"""test Heading.__unicode__()"""
node = Heading(wraptext("foobar"), 2)
self.assertEqual("==foobar==", str(node))
node2 = Heading(wraptext(" zzz "), 5)
self.assertEqual("===== zzz =====", str(node2))

def test_iternodes(self):
"""test Heading.__iternodes__()"""
text1, text2 = Text("foo"), Text("bar")
node = Heading(wrap([text1, text2]), 3)
gen = node.__iternodes__(getnodes)
self.assertEqual((None, node), next(gen))
self.assertEqual((node.title, text1), next(gen))
self.assertEqual((node.title, text2), next(gen))
self.assertRaises(StopIteration, next, gen)

def test_strip(self):
"""test Heading.__strip__()"""
node = Heading(wraptext("foobar"), 3)
for a in (True, False):
for b in (True, False):
self.assertEqual("foobar", node.__strip__(a, b))

def test_showtree(self):
"""test Heading.__showtree__()"""
output = []
getter = object()
get = lambda code: output.append((getter, code))
node1 = Heading(wraptext("foobar"), 3)
node2 = Heading(wraptext(" baz "), 4)
node1.__showtree__(output.append, get, None)
node2.__showtree__(output.append, get, None)
valid = ["===", (getter, node1.title), "===",
"====", (getter, node2.title), "===="]
self.assertEqual(valid, output)

def test_title(self):
"""test getter/setter for the title attribute"""
title = wraptext("foobar")
node = Heading(title, 3)
self.assertIs(title, node.title)
node.title = "héhehé"
self.assertWikicodeEqual(wraptext("héhehé"), node.title)

def test_level(self):
"""test getter/setter for the level attribute"""
node = Heading(wraptext("foobar"), 3)
self.assertEqual(3, node.level)
node.level = 5
self.assertEqual(5, node.level)
self.assertRaises(ValueError, setattr, node, "level", 0)
self.assertRaises(ValueError, setattr, node, "level", 7)
self.assertRaises(ValueError, setattr, node, "level", "abc")
self.assertRaises(ValueError, setattr, node, "level", False)

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 169
- 0
tests/test_html_entity.py View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import HTMLEntity

from ._test_tree_equality import TreeEqualityTestCase, wrap

class TestHTMLEntity(TreeEqualityTestCase):
"""Test cases for the HTMLEntity node."""

def test_unicode(self):
"""test HTMLEntity.__unicode__()"""
node1 = HTMLEntity("nbsp", named=True, hexadecimal=False)
node2 = HTMLEntity("107", named=False, hexadecimal=False)
node3 = HTMLEntity("6b", named=False, hexadecimal=True)
node4 = HTMLEntity("6C", named=False, hexadecimal=True, hex_char="X")
self.assertEqual("&nbsp;", str(node1))
self.assertEqual("&#107;", str(node2))
self.assertEqual("&#x6b;", str(node3))
self.assertEqual("&#X6C;", str(node4))

def test_iternodes(self):
"""test HTMLEntity.__iternodes__()"""
node = HTMLEntity("nbsp", named=True, hexadecimal=False)
gen = node.__iternodes__(None)
self.assertEqual((None, node), next(gen))
self.assertRaises(StopIteration, next, gen)

def test_strip(self):
"""test HTMLEntity.__strip__()"""
node1 = HTMLEntity("nbsp", named=True, hexadecimal=False)
node2 = HTMLEntity("107", named=False, hexadecimal=False)
node3 = HTMLEntity("e9", named=False, hexadecimal=True)
for a in (True, False):
self.assertEqual("\xa0", node1.__strip__(True, a))
self.assertEqual("&nbsp;", node1.__strip__(False, a))
self.assertEqual("k", node2.__strip__(True, a))
self.assertEqual("&#107;", node2.__strip__(False, a))
self.assertEqual("é", node3.__strip__(True, a))
self.assertEqual("&#xe9;", node3.__strip__(False, a))

def test_showtree(self):
"""test HTMLEntity.__showtree__()"""
output = []
node1 = HTMLEntity("nbsp", named=True, hexadecimal=False)
node2 = HTMLEntity("107", named=False, hexadecimal=False)
node3 = HTMLEntity("e9", named=False, hexadecimal=True)
node1.__showtree__(output.append, None, None)
node2.__showtree__(output.append, None, None)
node3.__showtree__(output.append, None, None)
res = ["&nbsp;", "&#107;", "&#xe9;"]
self.assertEqual(res, output)

def test_value(self):
"""test getter/setter for the value attribute"""
node1 = HTMLEntity("nbsp")
node2 = HTMLEntity("107")
node3 = HTMLEntity("e9")
self.assertEqual("nbsp", node1.value)
self.assertEqual("107", node2.value)
self.assertEqual("e9", node3.value)

node1.value = "ffa4"
node2.value = 72
node3.value = "Sigma"
self.assertEqual("ffa4", node1.value)
self.assertFalse(node1.named)
self.assertTrue(node1.hexadecimal)
self.assertEqual("72", node2.value)
self.assertFalse(node2.named)
self.assertFalse(node2.hexadecimal)
self.assertEqual("Sigma", node3.value)
self.assertTrue(node3.named)
self.assertFalse(node3.hexadecimal)

node1.value = "10FFFF"
node2.value = 110000
node2.value = 1114111
self.assertRaises(ValueError, setattr, node3, "value", "")
self.assertRaises(ValueError, setattr, node3, "value", "foobar")
self.assertRaises(ValueError, setattr, node3, "value", True)
self.assertRaises(ValueError, setattr, node3, "value", -1)
self.assertRaises(ValueError, setattr, node1, "value", 110000)
self.assertRaises(ValueError, setattr, node1, "value", "1114112")

def test_named(self):
"""test getter/setter for the named attribute"""
node1 = HTMLEntity("nbsp")
node2 = HTMLEntity("107")
node3 = HTMLEntity("e9")
self.assertTrue(node1.named)
self.assertFalse(node2.named)
self.assertFalse(node3.named)
node1.named = 1
node2.named = 0
node3.named = 0
self.assertTrue(node1.named)
self.assertFalse(node2.named)
self.assertFalse(node3.named)
self.assertRaises(ValueError, setattr, node1, "named", False)
self.assertRaises(ValueError, setattr, node2, "named", True)
self.assertRaises(ValueError, setattr, node3, "named", True)

def test_hexadecimal(self):
"""test getter/setter for the hexadecimal attribute"""
node1 = HTMLEntity("nbsp")
node2 = HTMLEntity("107")
node3 = HTMLEntity("e9")
self.assertFalse(node1.hexadecimal)
self.assertFalse(node2.hexadecimal)
self.assertTrue(node3.hexadecimal)
node1.hexadecimal = False
node2.hexadecimal = True
node3.hexadecimal = False
self.assertFalse(node1.hexadecimal)
self.assertTrue(node2.hexadecimal)
self.assertFalse(node3.hexadecimal)
self.assertRaises(ValueError, setattr, node1, "hexadecimal", True)

def test_hex_char(self):
"""test getter/setter for the hex_char attribute"""
node1 = HTMLEntity("e9")
node2 = HTMLEntity("e9", hex_char="X")
self.assertEqual("x", node1.hex_char)
self.assertEqual("X", node2.hex_char)
node1.hex_char = "X"
node2.hex_char = "x"
self.assertEqual("X", node1.hex_char)
self.assertEqual("x", node2.hex_char)
self.assertRaises(ValueError, setattr, node1, "hex_char", 123)
self.assertRaises(ValueError, setattr, node1, "hex_char", "foobar")
self.assertRaises(ValueError, setattr, node1, "hex_char", True)

def test_normalize(self):
"""test getter/setter for the normalize attribute"""
node1 = HTMLEntity("nbsp")
node2 = HTMLEntity("107")
node3 = HTMLEntity("e9")
node4 = HTMLEntity("1f648")
self.assertEqual("\xa0", node1.normalize())
self.assertEqual("k", node2.normalize())
self.assertEqual("é", node3.normalize())
self.assertEqual("\U0001F648", node4.normalize())

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 75
- 0
tests/test_parameter.py View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Text
from mwparserfromhell.nodes.extras import Parameter

from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

class TestParameter(TreeEqualityTestCase):
"""Test cases for the Parameter node extra."""

def test_unicode(self):
"""test Parameter.__unicode__()"""
node = Parameter(wraptext("1"), wraptext("foo"), showkey=False)
self.assertEqual("foo", str(node))
node2 = Parameter(wraptext("foo"), wraptext("bar"))
self.assertEqual("foo=bar", str(node2))

def test_name(self):
"""test getter/setter for the name attribute"""
name1 = wraptext("1")
name2 = wraptext("foobar")
node1 = Parameter(name1, wraptext("foobar"), showkey=False)
node2 = Parameter(name2, wraptext("baz"))
self.assertIs(name1, node1.name)
self.assertIs(name2, node2.name)
node1.name = "héhehé"
node2.name = "héhehé"
self.assertWikicodeEqual(wraptext("héhehé"), node1.name)
self.assertWikicodeEqual(wraptext("héhehé"), node2.name)

def test_value(self):
"""test getter/setter for the value attribute"""
value = wraptext("bar")
node = Parameter(wraptext("foo"), value)
self.assertIs(value, node.value)
node.value = "héhehé"
self.assertWikicodeEqual(wraptext("héhehé"), node.value)

def test_showkey(self):
"""test getter/setter for the showkey attribute"""
node1 = Parameter(wraptext("1"), wraptext("foo"), showkey=False)
node2 = Parameter(wraptext("foo"), wraptext("bar"))
self.assertFalse(node1.showkey)
self.assertTrue(node2.showkey)
node1.showkey = True
node2.showkey = ""
self.assertTrue(node1.showkey)
self.assertFalse(node2.showkey)

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 9
- 12
tests/test_parser.py View File

@@ -26,10 +26,8 @@ import unittest
from mwparserfromhell import parser
from mwparserfromhell.nodes import Template, Text, Wikilink
from mwparserfromhell.nodes.extras import Parameter
from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.wikicode import Wikicode

from ._test_tree_equality import TreeEqualityTestCase
from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext
from .compat import range

class TestParser(TreeEqualityTestCase):
@@ -45,18 +43,17 @@ class TestParser(TreeEqualityTestCase):
def test_parsing(self):
"""integration test for parsing overall"""
text = "this is text; {{this|is=a|template={{with|[[links]]|in}}it}}"
wrap = lambda L: Wikicode(SmartList(L))
expected = wrap([
Text("this is text; "),
Template(wrap([Text("this")]), [
Parameter(wrap([Text("is")]), wrap([Text("a")])),
Parameter(wrap([Text("template")]), wrap([
Template(wrap([Text("with")]), [
Parameter(wrap([Text("1")]),
wrap([Wikilink(wrap([Text("links")]))]),
Template(wraptext("this"), [
Parameter(wraptext("is"), wraptext("a")),
Parameter(wraptext("template"), wrap([
Template(wraptext("with"), [
Parameter(wraptext("1"),
wrap([Wikilink(wraptext("links"))]),
showkey=False),
Parameter(wrap([Text("2")]),
wrap([Text("in")]), showkey=False)
Parameter(wraptext("2"),
wraptext("in"), showkey=False)
]),
Text("it")
]))


+ 364
- 0
tests/test_template.py View File

@@ -0,0 +1,364 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import HTMLEntity, Template, Text
from mwparserfromhell.nodes.extras import Parameter
from ._test_tree_equality import TreeEqualityTestCase, getnodes, wrap, wraptext

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):
"""Test cases for the Template node."""

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

def test_iternodes(self):
"""test Template.__iternodes__()"""
node1n1 = Text("foobar")
node2n1, node2n2, node2n3 = Text("foo"), Text("bar"), Text("abc")
node2n4, node2n5 = Text("def"), Text("ghi")
node2p1 = Parameter(wraptext("1"), wrap([node2n2]), showkey=False)
node2p2 = Parameter(wrap([node2n3]), wrap([node2n4, node2n5]),
showkey=True)
node1 = Template(wrap([node1n1]))
node2 = Template(wrap([node2n1]), [node2p1, node2p2])

gen1 = node1.__iternodes__(getnodes)
gen2 = node2.__iternodes__(getnodes)
self.assertEqual((None, node1), next(gen1))
self.assertEqual((None, node2), next(gen2))
self.assertEqual((node1.name, node1n1), next(gen1))
self.assertEqual((node2.name, node2n1), next(gen2))
self.assertEqual((node2.params[0].value, node2n2), next(gen2))
self.assertEqual((node2.params[1].name, node2n3), next(gen2))
self.assertEqual((node2.params[1].value, node2n4), next(gen2))
self.assertEqual((node2.params[1].value, node2n5), next(gen2))
self.assertRaises(StopIteration, next, gen1)
self.assertRaises(StopIteration, next, gen2)

def test_strip(self):
"""test Template.__strip__()"""
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("abc", "def")])
for a in (True, False):
for b in (True, False):
self.assertEqual(None, node1.__strip__(a, b))
self.assertEqual(None, node2.__strip__(a, b))

def test_showtree(self):
"""test Template.__showtree__()"""
output = []
getter, marker = object(), object()
get = lambda code: output.append((getter, code))
mark = lambda: output.append(marker)
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("abc", "def")])
node1.__showtree__(output.append, get, mark)
node2.__showtree__(output.append, get, mark)
valid = [
"{{", (getter, node1.name), "}}", "{{", (getter, node2.name),
" | ", marker, (getter, node2.params[0].name), " = ", marker,
(getter, node2.params[0].value), " | ", marker,
(getter, node2.params[1].name), " = ", marker,
(getter, node2.params[1].value), "}}"]
self.assertEqual(valid, output)

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

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

def test_has_param(self):
"""test Template.has_param()"""
node1 = Template(wraptext("foobar"))
node2 = Template(wraptext("foo"),
[pgenh("1", "bar"), pgens("\nabc ", "def")])
node3 = Template(wraptext("foo"),
[pgenh("1", "a"), pgens("b", "c"), pgens("1", "d")])
node4 = Template(wraptext("foo"), [pgenh("1", "a"), pgens("b", " ")])
self.assertFalse(node1.has_param("foobar"))
self.assertTrue(node2.has_param(1))
self.assertTrue(node2.has_param("abc"))
self.assertFalse(node2.has_param("def"))
self.assertTrue(node3.has_param("1"))
self.assertTrue(node3.has_param(" b "))
self.assertFalse(node4.has_param("b"))
self.assertTrue(node3.has_param("b", False))
self.assertTrue(node4.has_param("b", False))

def test_get(self):
"""test Template.get()"""
node1 = Template(wraptext("foobar"))
node2p1 = pgenh("1", "bar")
node2p2 = pgens("abc", "def")
node2 = Template(wraptext("foo"), [node2p1, node2p2])
node3p1 = pgens("b", "c")
node3p2 = pgens("1", "d")
node3 = Template(wraptext("foo"), [pgenh("1", "a"), node3p1, node3p2])
node4p1 = pgens(" b", " ")
node4 = Template(wraptext("foo"), [pgenh("1", "a"), node4p1])
self.assertRaises(ValueError, node1.get, "foobar")
self.assertIs(node2p1, node2.get(1))
self.assertIs(node2p2, node2.get("abc"))
self.assertRaises(ValueError, node2.get, "def")
self.assertIs(node3p1, node3.get("b"))
self.assertIs(node3p2, node3.get("1"))
self.assertIs(node4p1, node4.get("b "))

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

def test_remove(self):
"""test Template.remove()"""
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")])
node6 = Template(wraptext("foo"), [
pgens(" a", "b"), pgens("b", "c"), pgens("a ", "d")])
node7 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
node8 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgens(" 1", "b"), pgens("2", "c")])
node9 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])
node10 = Template(wraptext("foo"), [
pgens("1 ", "a"), pgenh("1", "b"), pgenh("2", "c")])

node2.remove("1")
node2.remove("abc")
node3.remove(1, keep_field=True)
node3.remove("abc", keep_field=True)
node4.remove("1", keep_field=False)
node5.remove("a", keep_field=False)
node6.remove("a", keep_field=True)
node7.remove(1, keep_field=True)
node8.remove(1, keep_field=False)
node9.remove(1, keep_field=True)
node10.remove(1, keep_field=False)

self.assertRaises(ValueError, node1.remove, 1)
self.assertRaises(ValueError, node1.remove, "a")
self.assertRaises(ValueError, node2.remove, "1")
self.assertEqual("{{foo}}", node2)
self.assertEqual("{{foo||abc=}}", node3)
self.assertEqual("{{foo||baz}}", node4)
self.assertEqual("{{foo|b=c}}", node5)
self.assertEqual("{{foo| a=|b=c}}", node6)
self.assertEqual("{{foo|1 =|2=c}}", node7)
self.assertEqual("{{foo|2=c}}", node8)
self.assertEqual("{{foo||c}}", node9)
self.assertEqual("{{foo||c}}", node10)

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 75
- 0
tests/test_text.py View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Text

class TestText(unittest.TestCase):
"""Test cases for the Text node."""

def test_unicode(self):
"""test Text.__unicode__()"""
node = Text("foobar")
self.assertEqual("foobar", str(node))
node2 = Text("fóóbar")
self.assertEqual("fóóbar", str(node2))

def test_iternodes(self):
"""test Text.__iternodes__()"""
node = Text("foobar")
gen = node.__iternodes__(None)
self.assertEqual((None, node), next(gen))
self.assertRaises(StopIteration, next, gen)

def test_strip(self):
"""test Text.__strip__()"""
node = Text("foobar")
for a in (True, False):
for b in (True, False):
self.assertIs(node, node.__strip__(a, b))

def test_showtree(self):
"""test Text.__showtree__()"""
output = []
node1 = Text("foobar")
node2 = Text("fóóbar")
node3 = Text("𐌲𐌿𐍄")
node1.__showtree__(output.append, None, None)
node2.__showtree__(output.append, None, None)
node3.__showtree__(output.append, None, None)
res = ["foobar", r"f\xf3\xf3bar", "\\U00010332\\U0001033f\\U00010344"]
self.assertEqual(res, output)

def test_value(self):
"""test getter/setter for the value attribute"""
node = Text("foobar")
self.assertEqual("foobar", node.value)
self.assertIsInstance(node.value, str)
node.value = "héhéhé"
self.assertEqual("héhéhé", node.value)
self.assertIsInstance(node.value, str)

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 11
- 16
tests/test_utils.py View File

@@ -24,33 +24,28 @@ from __future__ import unicode_literals
import unittest

from mwparserfromhell.nodes import Template, Text
from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.utils import parse_anything
from mwparserfromhell.wikicode import Wikicode

from ._test_tree_equality import TreeEqualityTestCase
from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

class TestUtils(TreeEqualityTestCase):
"""Tests for the utils module, which provides parse_anything()."""

def test_parse_anything_valid(self):
"""tests for valid input to utils.parse_anything()"""
wrap = lambda L: Wikicode(SmartList(L))
textify = lambda L: wrap([Text(item) for item in L])
tests = [
(wrap([Text("foobar")]), textify(["foobar"])),
(Template(wrap([Text("spam")])),
wrap([Template(textify(["spam"]))])),
("fóóbar", textify(["fóóbar"])),
(b"foob\xc3\xa1r", textify(["foobár"])),
(123, textify(["123"])),
(True, textify(["True"])),
(wraptext("foobar"), wraptext("foobar")),
(Template(wraptext("spam")), wrap([Template(wraptext("spam"))])),
("fóóbar", wraptext("fóóbar")),
(b"foob\xc3\xa1r", wraptext("foobár")),
(123, wraptext("123")),
(True, wraptext("True")),
(None, wrap([])),
([Text("foo"), Text("bar"), Text("baz")],
textify(["foo", "bar", "baz"])),
([wrap([Text("foo")]), Text("bar"), "baz", 123, 456],
textify(["foo", "bar", "baz", "123", "456"])),
([[[([[((("foo",),),)], "bar"],)]]], textify(["foo", "bar"]))
wraptext("foo", "bar", "baz")),
([wraptext("foo"), Text("bar"), "baz", 123, 456],
wraptext("foo", "bar", "baz", "123", "456")),
([[[([[((("foo",),),)], "bar"],)]]], wraptext("foo", "bar"))
]
for test, valid in tests:
self.assertWikicodeEqual(valid, parse_anything(test))


+ 107
- 0
tests/test_wikilink.py View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012-2013 Ben Kurtovic <ben.kurtovic@verizon.net>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import unicode_literals
import unittest

from mwparserfromhell.compat import str
from mwparserfromhell.nodes import Text, Wikilink

from ._test_tree_equality import TreeEqualityTestCase, getnodes, wrap, wraptext

class TestWikilink(TreeEqualityTestCase):
"""Test cases for the Wikilink node."""

def test_unicode(self):
"""test Wikilink.__unicode__()"""
node = Wikilink(wraptext("foobar"))
self.assertEqual("[[foobar]]", str(node))
node2 = Wikilink(wraptext("foo"), wraptext("bar"))
self.assertEqual("[[foo|bar]]", str(node2))

def test_iternodes(self):
"""test Wikilink.__iternodes__()"""
node1n1 = Text("foobar")
node2n1, node2n2, node2n3 = Text("foo"), Text("bar"), Text("baz")
node1 = Wikilink(wrap([node1n1]))
node2 = Wikilink(wrap([node2n1]), wrap([node2n2, node2n3]))
gen1 = node1.__iternodes__(getnodes)
gen2 = node2.__iternodes__(getnodes)
self.assertEqual((None, node1), next(gen1))
self.assertEqual((None, node2), next(gen2))
self.assertEqual((node1.title, node1n1), next(gen1))
self.assertEqual((node2.title, node2n1), next(gen2))
self.assertEqual((node2.text, node2n2), next(gen2))
self.assertEqual((node2.text, node2n3), next(gen2))
self.assertRaises(StopIteration, next, gen1)
self.assertRaises(StopIteration, next, gen2)

def test_strip(self):
"""test Wikilink.__strip__()"""
node = Wikilink(wraptext("foobar"))
node2 = Wikilink(wraptext("foo"), wraptext("bar"))
for a in (True, False):
for b in (True, False):
self.assertEqual("foobar", node.__strip__(a, b))
self.assertEqual("bar", node2.__strip__(a, b))

def test_showtree(self):
"""test Wikilink.__showtree__()"""
output = []
getter, marker = object(), object()
get = lambda code: output.append((getter, code))
mark = lambda: output.append(marker)
node1 = Wikilink(wraptext("foobar"))
node2 = Wikilink(wraptext("foo"), wraptext("bar"))
node1.__showtree__(output.append, get, mark)
node2.__showtree__(output.append, get, mark)
valid = [
"[[", (getter, node1.title), "]]", "[[", (getter, node2.title),
" | ", marker, (getter, node2.text), "]]"]
self.assertEqual(valid, output)

def test_title(self):
"""test getter/setter for the title attribute"""
title = wraptext("foobar")
node1 = Wikilink(title)
node2 = Wikilink(title, wraptext("baz"))
self.assertIs(title, node1.title)
self.assertIs(title, node2.title)
node1.title = "héhehé"
node2.title = "héhehé"
self.assertWikicodeEqual(wraptext("héhehé"), node1.title)
self.assertWikicodeEqual(wraptext("héhehé"), node2.title)

def test_text(self):
"""test getter/setter for the text attribute"""
text = wraptext("baz")
node1 = Wikilink(wraptext("foobar"))
node2 = Wikilink(wraptext("foobar"), text)
self.assertIs(None, node1.text)
self.assertIs(text, node2.text)
node1.text = "buzz"
node2.text = None
self.assertWikicodeEqual(wraptext("buzz"), node1.text)
self.assertIs(None, node2.text)

if __name__ == "__main__":
unittest.main(verbosity=2)

Loading…
Cancel
Save