Ver a proveniência

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

tags/v0.2
Ben Kurtovic há 11 anos
ascendente
cometimento
419e5af958
16 ficheiros alterados com 1257 adições e 163 eliminações
  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 Ver ficheiro

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


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


__all__ = ["HTMLEntity"] __all__ = ["HTMLEntity"]


@@ -63,28 +63,31 @@ class HTMLEntity(Node):
return self.normalize() return self.normalize()
return self 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 @property
def value(self): def value(self):
@@ -119,19 +122,47 @@ class HTMLEntity(Node):
@value.setter @value.setter
def value(self, newval): def value(self, newval):
newval = str(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 self._value = newval


@named.setter @named.setter
def named(self, newval): 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 @hexadecimal.setter
def hexadecimal(self, newval): 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 @hex_char.setter
def hex_char(self, newval): def hex_char(self, newval):
@@ -142,8 +173,9 @@ class HTMLEntity(Node):


def normalize(self): def normalize(self):
"""Return the unicode character represented by the HTML entity.""" """Return the unicode character represented by the HTML entity."""
chrfunc = chr if py3k else HTMLEntity._unichr
if self.named: if self.named:
return unichr(htmlentities.name2codepoint[self.value])
return chrfunc(htmlentities.name2codepoint[self.value])
if self.hexadecimal: 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 Ver ficheiro

@@ -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):
@@ -142,9 +142,9 @@ class Template(Node):
return False return False
return True 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.""" """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:]] dependents = [not after.showkey for after in self.params[i+1:]]
if any(dependents): if any(dependents):
return False return False
@@ -183,11 +183,10 @@ class Template(Node):
def get(self, name): def get(self, name):
"""Get the parameter whose name is *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) name = name.strip() if isinstance(name, basestring) else str(name)
for param in reversed(self.params): for param in reversed(self.params):
@@ -195,20 +194,34 @@ class Template(Node):
return param return param
raise ValueError(name) 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*. """Add a parameter to the template with a given *name* and *value*.


*name* and *value* can be anything parasable by *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 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 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) name, value = parse_anything(name), parse_anything(value)
self._surface_escape(value, "|") self._surface_escape(value, "|")
@@ -217,14 +230,17 @@ class Template(Node):
self.remove(name, keep_field=True) self.remove(name, keep_field=True)
existing = self.get(name) existing = self.get(name)
if showkey is not None: if showkey is not None:
if not showkey:
self._surface_escape(value, "=")
existing.showkey = showkey existing.showkey = showkey
if not existing.showkey:
self._surface_escape(value, "=")
nodes = existing.value.nodes 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]]) existing.value = parse_anything([nodes[0], value, nodes[1]])
else:
existing.value = value
return existing return existing


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


if not force_nonconformity:
if preserve_spacing:
before_n, after_n = self._get_spacing_conventions(use_names=True) 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) 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) 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 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*. """Remove a parameter from the template whose name is *name*.


If *keep_field* is ``True``, we will keep the parameter's name, but If *keep_field* is ``True``, we will keep the parameter's name, but
blank its value. Otherwise, we will remove the parameter completely blank its value. Otherwise, we will remove the parameter completely
*unless* other parameters are dependent on it (e.g. removing ``bar`` *unless* other parameters are dependent on it (e.g. removing ``bar``
from ``{{foo|bar|baz}}`` is unsafe because ``{{foo|baz}}`` is not what 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) name = name.strip() if isinstance(name, basestring) else str(name)
removed = False removed = False
to_remove =[]
for i, param in enumerate(self.params): for i, param in enumerate(self.params):
if param.name.strip() == name: if param.name.strip() == name:
if keep_field: if keep_field:
@@ -290,13 +301,15 @@ class Template(Node):
self._blank_param_value(param.value) self._blank_param_value(param.value)
keep_field = False keep_field = False
else: else:
self.params.remove(param)
to_remove.append(param)
else: 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: else:
self._blank_param_value(param.value) self._blank_param_value(param.value)
if not removed: if not removed:
removed = True removed = True
if not removed: if not removed:
raise ValueError(name) raise ValueError(name)
for param in to_remove:
self.params.remove(param)

+ 4
- 1
mwparserfromhell/nodes/wikilink.py Ver ficheiro

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


@text.setter @text.setter
def text(self, value): 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 Ver ficheiro

@@ -88,13 +88,7 @@ class Wikicode(StringMixIn):
If *obj* is a ``Node``, the function will test whether they are the If *obj* is a ``Node``, the function will test whether they are the
same object, otherwise it will compare them with ``==``. 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): def _contains(self, nodes, obj):
"""Return ``True`` if *obj* is inside of *nodes*, else ``False``. """Return ``True`` if *obj* is inside of *nodes*, else ``False``.


+ 13
- 0
tests/_test_tree_equality.py Ver ficheiro

@@ -26,8 +26,21 @@ from unittest import TestCase
from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity, from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity,
Tag, Template, Text, Wikilink) Tag, Template, Text, Wikilink)
from mwparserfromhell.nodes.extras import Attribute, Parameter from mwparserfromhell.nodes.extras import Attribute, Parameter
from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.wikicode import Wikicode 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): class TreeEqualityTestCase(TestCase):
"""A base test case with support for comparing the equality of node trees. """A base test case with support for comparing the equality of node trees.




+ 107
- 0
tests/test_argument.py Ver ficheiro

@@ -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 Ver ficheiro

@@ -28,12 +28,8 @@ from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity,
from mwparserfromhell.nodes.extras import Attribute, Parameter from mwparserfromhell.nodes.extras import Attribute, Parameter
from mwparserfromhell.parser import tokens from mwparserfromhell.parser import tokens
from mwparserfromhell.parser.builder import Builder 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): class TestBuilder(TreeEqualityTestCase):
"""Tests for the builder, which turns tokens into Wikicode objects.""" """Tests for the builder, which turns tokens into Wikicode objects."""
@@ -44,10 +40,10 @@ class TestBuilder(TreeEqualityTestCase):
def test_text(self): def test_text(self):
"""tests for building Text nodes""" """tests for building Text nodes"""
tests = [ 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")], ([tokens.Text(text="spam"), tokens.Text(text="eggs")],
wrap([Text("spam"), Text("eggs")])),
wraptext("spam", "eggs")),
] ]
for test, valid in tests: for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test)) self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -57,25 +53,24 @@ class TestBuilder(TreeEqualityTestCase):
tests = [ tests = [
([tokens.TemplateOpen(), tokens.Text(text="foobar"), ([tokens.TemplateOpen(), tokens.Text(text="foobar"),
tokens.TemplateClose()], tokens.TemplateClose()],
wrap([Template(wrap([Text("foobar")]))])),
wrap([Template(wraptext("foobar"))])),


([tokens.TemplateOpen(), tokens.Text(text="spam"), ([tokens.TemplateOpen(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.TemplateClose()], 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.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"), tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateClose()], 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.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"), tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateParamEquals(), tokens.Text(text="baz"), tokens.TemplateParamEquals(), tokens.Text(text="baz"),
tokens.TemplateClose()], 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.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"), tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
@@ -86,14 +81,12 @@ class TestBuilder(TreeEqualityTestCase):
tokens.TemplateParamEquals(), tokens.Text(text="buff"), tokens.TemplateParamEquals(), tokens.Text(text="buff"),
tokens.TemplateParamSeparator(), tokens.Text(text="baff"), tokens.TemplateParamSeparator(), tokens.Text(text="baff"),
tokens.TemplateClose()], 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)])])), showkey=False)])])),
] ]
for test, valid in tests: for test, valid in tests:
@@ -104,23 +97,22 @@ class TestBuilder(TreeEqualityTestCase):
tests = [ tests = [
([tokens.ArgumentOpen(), tokens.Text(text="foobar"), ([tokens.ArgumentOpen(), tokens.Text(text="foobar"),
tokens.ArgumentClose()], tokens.ArgumentClose()],
wrap([Argument(wrap([Text("foobar")]))])),
wrap([Argument(wraptext("foobar"))])),


([tokens.ArgumentOpen(), tokens.Text(text="spam"), ([tokens.ArgumentOpen(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.ArgumentClose()], 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.ArgumentOpen(), tokens.Text(text="foo"),
tokens.ArgumentSeparator(), tokens.Text(text="bar"), tokens.ArgumentSeparator(), tokens.Text(text="bar"),
tokens.ArgumentClose()], tokens.ArgumentClose()],
wrap([Argument(wrap([Text("foo")]), wrap([Text("bar")]))])),
wrap([Argument(wraptext("foo"), wraptext("bar"))])),


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


([tokens.WikilinkOpen(), tokens.Text(text="spam"), ([tokens.WikilinkOpen(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.WikilinkClose()], 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.WikilinkOpen(), tokens.Text(text="foo"),
tokens.WikilinkSeparator(), tokens.Text(text="bar"), tokens.WikilinkSeparator(), tokens.Text(text="bar"),
tokens.WikilinkClose()], tokens.WikilinkClose()],
wrap([Wikilink(wrap([Text("foo")]), wrap([Text("bar")]))])),
wrap([Wikilink(wraptext("foo"), wraptext("bar"))])),


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


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


([tokens.CommentStart(), tokens.Text(text="spam"), ([tokens.CommentStart(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.CommentEnd()], tokens.Text(text="eggs"), tokens.CommentEnd()],
wrap([Comment(wrap([Text("spam"), Text("eggs")]))])),
wrap([Comment(wraptext("spam", "eggs"))])),
] ]
for test, valid in tests: for test, valid in tests:
self.assertWikicodeEqual(valid, self.builder.build(test)) self.assertWikicodeEqual(valid, self.builder.build(test))
@@ -218,10 +209,10 @@ class TestBuilder(TreeEqualityTestCase):
tokens.TemplateOpen(), tokens.Text(text="bin"), tokens.TemplateOpen(), tokens.Text(text="bin"),
tokens.TemplateClose(), tokens.TemplateClose()] tokens.TemplateClose(), tokens.TemplateClose()]
valid = wrap( 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)])]) showkey=False)])])
self.assertWikicodeEqual(valid, self.builder.build(test)) self.assertWikicodeEqual(valid, self.builder.build(test))


@@ -247,14 +238,14 @@ class TestBuilder(TreeEqualityTestCase):
tokens.Text(text="nbsp"), tokens.HTMLEntityEnd(), tokens.Text(text="nbsp"), tokens.HTMLEntityEnd(),
tokens.TemplateClose()] tokens.TemplateClose()]
valid = wrap( 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)) self.assertWikicodeEqual(valid, self.builder.build(test))


if __name__ == "__main__": if __name__ == "__main__":


+ 68
- 0
tests/test_comment.py Ver ficheiro

@@ -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 Ver ficheiro

@@ -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 Ver ficheiro

@@ -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 Ver ficheiro

@@ -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 Ver ficheiro

@@ -26,10 +26,8 @@ import unittest
from mwparserfromhell import parser from mwparserfromhell import parser
from mwparserfromhell.nodes import Template, Text, Wikilink from mwparserfromhell.nodes import Template, Text, Wikilink
from mwparserfromhell.nodes.extras import Parameter 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 from .compat import range


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


+ 364
- 0
tests/test_template.py Ver ficheiro

@@ -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 Ver ficheiro

@@ -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 Ver ficheiro

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


from mwparserfromhell.nodes import Template, Text from mwparserfromhell.nodes import Template, Text
from mwparserfromhell.smart_list import SmartList
from mwparserfromhell.utils import parse_anything 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): class TestUtils(TreeEqualityTestCase):
"""Tests for the utils module, which provides parse_anything().""" """Tests for the utils module, which provides parse_anything()."""


def test_parse_anything_valid(self): def test_parse_anything_valid(self):
"""tests for valid input to utils.parse_anything()""" """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 = [ 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([])), (None, wrap([])),
([Text("foo"), Text("bar"), Text("baz")], ([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: for test, valid in tests:
self.assertWikicodeEqual(valid, parse_anything(test)) self.assertWikicodeEqual(valid, parse_anything(test))


+ 107
- 0
tests/test_wikilink.py Ver ficheiro

@@ -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)

Carregando…
Cancelar
Guardar