@@ -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)) |
@@ -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) |
@@ -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) |
@@ -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``. | ||||
@@ -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. | ||||
@@ -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) |
@@ -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__": | ||||
@@ -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) |
@@ -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) |
@@ -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(" ", str(node1)) | |||||
self.assertEqual("k", str(node2)) | |||||
self.assertEqual("k", str(node3)) | |||||
self.assertEqual("l", 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(" ", node1.__strip__(False, a)) | |||||
self.assertEqual("k", node2.__strip__(True, a)) | |||||
self.assertEqual("k", node2.__strip__(False, a)) | |||||
self.assertEqual("é", node3.__strip__(True, a)) | |||||
self.assertEqual("é", 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 = [" ", "k", "é"] | |||||
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) |
@@ -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) |
@@ -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") | ||||
])) | ])) | ||||
@@ -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|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=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=bar}}", node28) | |||||
self.assertIsInstance(node28.params[1].value.get(1), HTMLEntity) | |||||
self.assertEqual("{{a|b=d}}", node29) | |||||
self.assertEqual("{{a|foo=bar}}", node30) | |||||
self.assertIsInstance(node30.params[0].value.get(1), HTMLEntity) | |||||
self.assertEqual("{{a|1=foo=bar}}", node31) | |||||
self.assertEqual("{{a|foo=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) |
@@ -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) |
@@ -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)) | ||||
@@ -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) |