@@ -23,7 +23,7 @@ | |||
from __future__ import unicode_literals | |||
from . import Node | |||
from ..compat import htmlentities, str | |||
from ..compat import htmlentities, py3k, str | |||
__all__ = ["HTMLEntity"] | |||
@@ -63,28 +63,31 @@ class HTMLEntity(Node): | |||
return self.normalize() | |||
return self | |||
def _unichr(self, value): | |||
"""Implement the builtin unichr() with support for non-BMP code points. | |||
if not py3k: | |||
@staticmethod | |||
def _unichr(value): | |||
"""Implement builtin unichr() with support for non-BMP code points. | |||
On wide Python builds, this functions like the normal unichr(). On | |||
narrow builds, this returns the value's corresponding surrogate pair. | |||
""" | |||
try: | |||
return unichr(value) | |||
except ValueError: | |||
# Test whether we're on the wide or narrow Python build. Check the | |||
# length of a non-BMP code point (U+1F64A, SPEAK-NO-EVIL MONKEY): | |||
if len("\U0001F64A") == 2: | |||
# Ensure this is within the range we can encode: | |||
if value > 0x10FFFF: | |||
raise ValueError("unichr() arg not in range(0x110000)") | |||
code = value - 0x10000 | |||
if value < 0: # Invalid code point | |||
raise | |||
lead = 0xD800 + (code >> 10) | |||
trail = 0xDC00 + (code % (1 << 10)) | |||
return unichr(lead) + unichr(trail) | |||
raise | |||
On wide Python builds, this functions like the normal unichr(). On | |||
narrow builds, this returns the value's encoded surrogate pair. | |||
""" | |||
try: | |||
return unichr(value) | |||
except ValueError: | |||
# Test whether we're on the wide or narrow Python build. Check | |||
# the length of a non-BMP code point | |||
# (U+1F64A, SPEAK-NO-EVIL MONKEY): | |||
if len("\U0001F64A") == 2: | |||
# Ensure this is within the range we can encode: | |||
if value > 0x10FFFF: | |||
raise ValueError("unichr() arg not in range(0x110000)") | |||
code = value - 0x10000 | |||
if value < 0: # Invalid code point | |||
raise | |||
lead = 0xD800 + (code >> 10) | |||
trail = 0xDC00 + (code % (1 << 10)) | |||
return unichr(lead) + unichr(trail) | |||
raise | |||
@property | |||
def value(self): | |||
@@ -119,19 +122,47 @@ class HTMLEntity(Node): | |||
@value.setter | |||
def value(self, newval): | |||
newval = str(newval) | |||
if newval not in htmlentities.entitydefs: | |||
test = int(self.value, 16) | |||
if test < 0 or (test > 0x10FFFF and int(self.value) > 0x10FFFF): | |||
raise ValueError(newval) | |||
try: | |||
int(newval) | |||
except ValueError: | |||
try: | |||
int(newval, 16) | |||
except ValueError: | |||
if newval not in htmlentities.entitydefs: | |||
raise ValueError("entity value is not a valid name") | |||
self._named = True | |||
self._hexadecimal = False | |||
else: | |||
if int(newval, 16) < 0 or int(newval, 16) > 0x10FFFF: | |||
raise ValueError("entity value is not in range(0x110000)") | |||
self._named = False | |||
self._hexadecimal = True | |||
else: | |||
test = int(newval, 16 if self.hexadecimal else 10) | |||
if test < 0 or test > 0x10FFFF: | |||
raise ValueError("entity value is not in range(0x110000)") | |||
self._named = False | |||
self._value = newval | |||
@named.setter | |||
def named(self, newval): | |||
self._named = bool(newval) | |||
newval = bool(newval) | |||
if newval and self.value not in htmlentities.entitydefs: | |||
raise ValueError("entity value is not a valid name") | |||
if not newval: | |||
try: | |||
int(self.value, 16) | |||
except ValueError: | |||
err = "current entity value is not a valid Unicode codepoint" | |||
raise ValueError(err) | |||
self._named = newval | |||
@hexadecimal.setter | |||
def hexadecimal(self, newval): | |||
self._hexadecimal = bool(newval) | |||
newval = bool(newval) | |||
if newval and self.named: | |||
raise ValueError("a named entity cannot be hexadecimal") | |||
self._hexadecimal = newval | |||
@hex_char.setter | |||
def hex_char(self, newval): | |||
@@ -142,8 +173,9 @@ class HTMLEntity(Node): | |||
def normalize(self): | |||
"""Return the unicode character represented by the HTML entity.""" | |||
chrfunc = chr if py3k else HTMLEntity._unichr | |||
if self.named: | |||
return unichr(htmlentities.name2codepoint[self.value]) | |||
return chrfunc(htmlentities.name2codepoint[self.value]) | |||
if self.hexadecimal: | |||
return self._unichr(int(self.value, 16)) | |||
return self._unichr(int(self.value)) | |||
return chrfunc(int(self.value, 16)) | |||
return chrfunc(int(self.value)) |
@@ -81,7 +81,7 @@ class Template(Node): | |||
in parameter names or values so they are not mistaken for new | |||
parameters. | |||
""" | |||
replacement = HTMLEntity(value=ord(char)) | |||
replacement = str(HTMLEntity(value=ord(char))) | |||
for node in code.filter_text(recursive=False): | |||
if char in node: | |||
code.replace(node, node.replace(char, replacement)) | |||
@@ -107,7 +107,7 @@ class Template(Node): | |||
values = tuple(theories.values()) | |||
best = max(values) | |||
confidence = float(best) / sum(values) | |||
if confidence > 0.75: | |||
if confidence >= 0.75: | |||
return tuple(theories.keys())[values.index(best)] | |||
def _get_spacing_conventions(self, use_names): | |||
@@ -142,9 +142,9 @@ class Template(Node): | |||
return False | |||
return True | |||
def _remove_without_field(self, param, i, force_no_field): | |||
def _remove_without_field(self, param, i): | |||
"""Return False if a parameter name should be kept, otherwise True.""" | |||
if not param.showkey and not force_no_field: | |||
if not param.showkey: | |||
dependents = [not after.showkey for after in self.params[i+1:]] | |||
if any(dependents): | |||
return False | |||
@@ -183,11 +183,10 @@ class Template(Node): | |||
def get(self, name): | |||
"""Get the parameter whose name is *name*. | |||
The returned object is a | |||
:py:class:`~.Parameter` instance. Raises :py:exc:`ValueError` if no | |||
parameter has this name. Since multiple parameters can have the same | |||
name, we'll return the last match, since the last parameter is the only | |||
one read by the MediaWiki parser. | |||
The returned object is a :py:class:`~.Parameter` instance. Raises | |||
:py:exc:`ValueError` if no parameter has this name. Since multiple | |||
parameters can have the same name, we'll return the last match, since | |||
the last parameter is the only one read by the MediaWiki parser. | |||
""" | |||
name = name.strip() if isinstance(name, basestring) else str(name) | |||
for param in reversed(self.params): | |||
@@ -195,20 +194,34 @@ class Template(Node): | |||
return param | |||
raise ValueError(name) | |||
def add(self, name, value, showkey=None, force_nonconformity=False): | |||
def add(self, name, value, showkey=None, before=None, | |||
preserve_spacing=True): | |||
"""Add a parameter to the template with a given *name* and *value*. | |||
*name* and *value* can be anything parasable by | |||
:py:func:`.utils.parse_anything`; pipes (and equal signs, if | |||
appropriate) are automatically escaped from *value* where applicable. | |||
:py:func:`.utils.parse_anything`; pipes and equal signs are | |||
automatically escaped from *value* when appropriate. | |||
If *showkey* is given, this will determine whether or not to show the | |||
parameter's name (e.g., ``{{foo|bar}}``'s parameter has a name of | |||
``"1"`` but it is hidden); otherwise, we'll make a safe and intelligent | |||
guess. If *name* is already a parameter, we'll replace its value while | |||
keeping the same spacing rules unless *force_nonconformity* is | |||
``True``. We will also try to guess the dominant spacing convention | |||
when adding a new parameter using :py:meth:`_get_spacing_conventions` | |||
unless *force_nonconformity* is ``True``. | |||
guess. | |||
If *name* is already a parameter in the template, we'll replace its | |||
value while keeping the same whitespace around it. We will also try to | |||
guess the dominant spacing convention when adding a new parameter using | |||
:py:meth:`_get_spacing_conventions`. | |||
If *before* is given (either a :py:class:`~.Parameter` object or a | |||
name), then we will place the parameter immediately before this one. | |||
Otherwise, it will be added at the end. If *before* is a name and | |||
exists multiple times in the template, we will place it before the last | |||
occurance. If *before* is not in the template, :py:exc:`ValueError` is | |||
raised. The argument is ignored if the new parameter already exists. | |||
If *preserve_spacing* is ``False``, we will avoid preserving spacing | |||
conventions when changing the value of an existing parameter or when | |||
adding a new one. | |||
""" | |||
name, value = parse_anything(name), parse_anything(value) | |||
self._surface_escape(value, "|") | |||
@@ -217,14 +230,17 @@ class Template(Node): | |||
self.remove(name, keep_field=True) | |||
existing = self.get(name) | |||
if showkey is not None: | |||
if not showkey: | |||
self._surface_escape(value, "=") | |||
existing.showkey = showkey | |||
if not existing.showkey: | |||
self._surface_escape(value, "=") | |||
nodes = existing.value.nodes | |||
if force_nonconformity: | |||
existing.value = value | |||
else: | |||
if preserve_spacing: | |||
for i in range(2): # Ignore empty text nodes | |||
if not nodes[i]: | |||
nodes[i] = None | |||
existing.value = parse_anything([nodes[0], value, nodes[1]]) | |||
else: | |||
existing.value = value | |||
return existing | |||
if showkey is None: | |||
@@ -246,43 +262,38 @@ class Template(Node): | |||
if not showkey: | |||
self._surface_escape(value, "=") | |||
if not force_nonconformity: | |||
if preserve_spacing: | |||
before_n, after_n = self._get_spacing_conventions(use_names=True) | |||
if before_n and after_n: | |||
name = parse_anything([before_n, name, after_n]) | |||
elif before_n: | |||
name = parse_anything([before_n, name]) | |||
elif after_n: | |||
name = parse_anything([name, after_n]) | |||
before_v, after_v = self._get_spacing_conventions(use_names=False) | |||
if before_v and after_v: | |||
value = parse_anything([before_v, value, after_v]) | |||
elif before_v: | |||
value = parse_anything([before_v, value]) | |||
elif after_v: | |||
value = parse_anything([value, after_v]) | |||
name = parse_anything([before_n, name, after_n]) | |||
value = parse_anything([before_v, value, after_v]) | |||
param = Parameter(name, value, showkey) | |||
self.params.append(param) | |||
if before: | |||
if not isinstance(before, Parameter): | |||
before = self.get(before) | |||
self.params.insert(self.params.index(before), param) | |||
else: | |||
self.params.append(param) | |||
return param | |||
def remove(self, name, keep_field=False, force_no_field=False): | |||
def remove(self, name, keep_field=False): | |||
"""Remove a parameter from the template whose name is *name*. | |||
If *keep_field* is ``True``, we will keep the parameter's name, but | |||
blank its value. Otherwise, we will remove the parameter completely | |||
*unless* other parameters are dependent on it (e.g. removing ``bar`` | |||
from ``{{foo|bar|baz}}`` is unsafe because ``{{foo|baz}}`` is not what | |||
we expected, so ``{{foo||baz}}`` will be produced instead), unless | |||
*force_no_field* is also ``True``. If the parameter shows up multiple | |||
times in the template, we will remove all instances of it (and keep | |||
one if *keep_field* is ``True`` - that being the first instance if | |||
none of the instances have dependents, otherwise that instance will be | |||
kept). | |||
we expected, so ``{{foo||baz}}`` will be produced instead). | |||
If the parameter shows up multiple times in the template, we will | |||
remove all instances of it (and keep one if *keep_field* is ``True`` - | |||
the first instance if none have dependents, otherwise the one with | |||
dependents will be kept). | |||
""" | |||
name = name.strip() if isinstance(name, basestring) else str(name) | |||
removed = False | |||
to_remove =[] | |||
for i, param in enumerate(self.params): | |||
if param.name.strip() == name: | |||
if keep_field: | |||
@@ -290,13 +301,15 @@ class Template(Node): | |||
self._blank_param_value(param.value) | |||
keep_field = False | |||
else: | |||
self.params.remove(param) | |||
to_remove.append(param) | |||
else: | |||
if self._remove_without_field(param, i, force_no_field): | |||
self.params.remove(param) | |||
if self._remove_without_field(param, i): | |||
to_remove.append(param) | |||
else: | |||
self._blank_param_value(param.value) | |||
if not removed: | |||
removed = True | |||
if not removed: | |||
raise ValueError(name) | |||
for param in to_remove: | |||
self.params.remove(param) |
@@ -79,4 +79,7 @@ class Wikilink(Node): | |||
@text.setter | |||
def text(self, value): | |||
self._text = parse_anything(value) | |||
if value is None: | |||
self._text = None | |||
else: | |||
self._text = parse_anything(value) |
@@ -88,13 +88,7 @@ class Wikicode(StringMixIn): | |||
If *obj* is a ``Node``, the function will test whether they are the | |||
same object, otherwise it will compare them with ``==``. | |||
""" | |||
if isinstance(obj, Node): | |||
if node is obj: | |||
return True | |||
else: | |||
if node == obj: | |||
return True | |||
return False | |||
return (node is obj) if isinstance(obj, Node) else (node == obj) | |||
def _contains(self, nodes, obj): | |||
"""Return ``True`` if *obj* is inside of *nodes*, else ``False``. | |||
@@ -26,8 +26,21 @@ from unittest import TestCase | |||
from mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity, | |||
Tag, Template, Text, Wikilink) | |||
from mwparserfromhell.nodes.extras import Attribute, Parameter | |||
from mwparserfromhell.smart_list import SmartList | |||
from mwparserfromhell.wikicode import Wikicode | |||
wrap = lambda L: Wikicode(SmartList(L)) | |||
wraptext = lambda *args: wrap([Text(t) for t in args]) | |||
def getnodes(code): | |||
"""Iterate over all child nodes of a given parent node. | |||
Imitates Wikicode._get_all_nodes(). | |||
""" | |||
for node in code.nodes: | |||
for context, child in node.__iternodes__(getnodes): | |||
yield child | |||
class TreeEqualityTestCase(TestCase): | |||
"""A base test case with support for comparing the equality of node trees. | |||
@@ -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.parser import tokens | |||
from mwparserfromhell.parser.builder import Builder | |||
from mwparserfromhell.smart_list import SmartList | |||
from mwparserfromhell.wikicode import Wikicode | |||
from ._test_tree_equality import TreeEqualityTestCase | |||
wrap = lambda L: Wikicode(SmartList(L)) | |||
from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext | |||
class TestBuilder(TreeEqualityTestCase): | |||
"""Tests for the builder, which turns tokens into Wikicode objects.""" | |||
@@ -44,10 +40,10 @@ class TestBuilder(TreeEqualityTestCase): | |||
def test_text(self): | |||
"""tests for building Text nodes""" | |||
tests = [ | |||
([tokens.Text(text="foobar")], wrap([Text("foobar")])), | |||
([tokens.Text(text="fóóbar")], wrap([Text("fóóbar")])), | |||
([tokens.Text(text="foobar")], wraptext("foobar")), | |||
([tokens.Text(text="fóóbar")], wraptext("fóóbar")), | |||
([tokens.Text(text="spam"), tokens.Text(text="eggs")], | |||
wrap([Text("spam"), Text("eggs")])), | |||
wraptext("spam", "eggs")), | |||
] | |||
for test, valid in tests: | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
@@ -57,25 +53,24 @@ class TestBuilder(TreeEqualityTestCase): | |||
tests = [ | |||
([tokens.TemplateOpen(), tokens.Text(text="foobar"), | |||
tokens.TemplateClose()], | |||
wrap([Template(wrap([Text("foobar")]))])), | |||
wrap([Template(wraptext("foobar"))])), | |||
([tokens.TemplateOpen(), tokens.Text(text="spam"), | |||
tokens.Text(text="eggs"), tokens.TemplateClose()], | |||
wrap([Template(wrap([Text("spam"), Text("eggs")]))])), | |||
wrap([Template(wraptext("spam", "eggs"))])), | |||
([tokens.TemplateOpen(), tokens.Text(text="foo"), | |||
tokens.TemplateParamSeparator(), tokens.Text(text="bar"), | |||
tokens.TemplateClose()], | |||
wrap([Template(wrap([Text("foo")]), params=[ | |||
Parameter(wrap([Text("1")]), wrap([Text("bar")]), | |||
showkey=False)])])), | |||
wrap([Template(wraptext("foo"), params=[ | |||
Parameter(wraptext("1"), wraptext("bar"), showkey=False)])])), | |||
([tokens.TemplateOpen(), tokens.Text(text="foo"), | |||
tokens.TemplateParamSeparator(), tokens.Text(text="bar"), | |||
tokens.TemplateParamEquals(), tokens.Text(text="baz"), | |||
tokens.TemplateClose()], | |||
wrap([Template(wrap([Text("foo")]), params=[ | |||
Parameter(wrap([Text("bar")]), wrap([Text("baz")]))])])), | |||
wrap([Template(wraptext("foo"), params=[ | |||
Parameter(wraptext("bar"), wraptext("baz"))])])), | |||
([tokens.TemplateOpen(), tokens.Text(text="foo"), | |||
tokens.TemplateParamSeparator(), tokens.Text(text="bar"), | |||
@@ -86,14 +81,12 @@ class TestBuilder(TreeEqualityTestCase): | |||
tokens.TemplateParamEquals(), tokens.Text(text="buff"), | |||
tokens.TemplateParamSeparator(), tokens.Text(text="baff"), | |||
tokens.TemplateClose()], | |||
wrap([Template(wrap([Text("foo")]), params=[ | |||
Parameter(wrap([Text("bar")]), wrap([Text("baz")])), | |||
Parameter(wrap([Text("1")]), wrap([Text("biz")]), | |||
showkey=False), | |||
Parameter(wrap([Text("2")]), wrap([Text("buzz")]), | |||
showkey=False), | |||
Parameter(wrap([Text("3")]), wrap([Text("buff")])), | |||
Parameter(wrap([Text("3")]), wrap([Text("baff")]), | |||
wrap([Template(wraptext("foo"), params=[ | |||
Parameter(wraptext("bar"), wraptext("baz")), | |||
Parameter(wraptext("1"), wraptext("biz"), showkey=False), | |||
Parameter(wraptext("2"), wraptext("buzz"), showkey=False), | |||
Parameter(wraptext("3"), wraptext("buff")), | |||
Parameter(wraptext("3"), wraptext("baff"), | |||
showkey=False)])])), | |||
] | |||
for test, valid in tests: | |||
@@ -104,23 +97,22 @@ class TestBuilder(TreeEqualityTestCase): | |||
tests = [ | |||
([tokens.ArgumentOpen(), tokens.Text(text="foobar"), | |||
tokens.ArgumentClose()], | |||
wrap([Argument(wrap([Text("foobar")]))])), | |||
wrap([Argument(wraptext("foobar"))])), | |||
([tokens.ArgumentOpen(), tokens.Text(text="spam"), | |||
tokens.Text(text="eggs"), tokens.ArgumentClose()], | |||
wrap([Argument(wrap([Text("spam"), Text("eggs")]))])), | |||
wrap([Argument(wraptext("spam", "eggs"))])), | |||
([tokens.ArgumentOpen(), tokens.Text(text="foo"), | |||
tokens.ArgumentSeparator(), tokens.Text(text="bar"), | |||
tokens.ArgumentClose()], | |||
wrap([Argument(wrap([Text("foo")]), wrap([Text("bar")]))])), | |||
wrap([Argument(wraptext("foo"), wraptext("bar"))])), | |||
([tokens.ArgumentOpen(), tokens.Text(text="foo"), | |||
tokens.Text(text="bar"), tokens.ArgumentSeparator(), | |||
tokens.Text(text="baz"), tokens.Text(text="biz"), | |||
tokens.ArgumentClose()], | |||
wrap([Argument(wrap([Text("foo"), Text("bar")]), | |||
wrap([Text("baz"), Text("biz")]))])), | |||
wrap([Argument(wraptext("foo", "bar"), wraptext("baz", "biz"))])), | |||
] | |||
for test, valid in tests: | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
@@ -130,23 +122,22 @@ class TestBuilder(TreeEqualityTestCase): | |||
tests = [ | |||
([tokens.WikilinkOpen(), tokens.Text(text="foobar"), | |||
tokens.WikilinkClose()], | |||
wrap([Wikilink(wrap([Text("foobar")]))])), | |||
wrap([Wikilink(wraptext("foobar"))])), | |||
([tokens.WikilinkOpen(), tokens.Text(text="spam"), | |||
tokens.Text(text="eggs"), tokens.WikilinkClose()], | |||
wrap([Wikilink(wrap([Text("spam"), Text("eggs")]))])), | |||
wrap([Wikilink(wraptext("spam", "eggs"))])), | |||
([tokens.WikilinkOpen(), tokens.Text(text="foo"), | |||
tokens.WikilinkSeparator(), tokens.Text(text="bar"), | |||
tokens.WikilinkClose()], | |||
wrap([Wikilink(wrap([Text("foo")]), wrap([Text("bar")]))])), | |||
wrap([Wikilink(wraptext("foo"), wraptext("bar"))])), | |||
([tokens.WikilinkOpen(), tokens.Text(text="foo"), | |||
tokens.Text(text="bar"), tokens.WikilinkSeparator(), | |||
tokens.Text(text="baz"), tokens.Text(text="biz"), | |||
tokens.WikilinkClose()], | |||
wrap([Wikilink(wrap([Text("foo"), Text("bar")]), | |||
wrap([Text("baz"), Text("biz")]))])), | |||
wrap([Wikilink(wraptext("foo", "bar"), wraptext("baz", "biz"))])), | |||
] | |||
for test, valid in tests: | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
@@ -176,11 +167,11 @@ class TestBuilder(TreeEqualityTestCase): | |||
tests = [ | |||
([tokens.HeadingStart(level=2), tokens.Text(text="foobar"), | |||
tokens.HeadingEnd()], | |||
wrap([Heading(wrap([Text("foobar")]), 2)])), | |||
wrap([Heading(wraptext("foobar"), 2)])), | |||
([tokens.HeadingStart(level=4), tokens.Text(text="spam"), | |||
tokens.Text(text="eggs"), tokens.HeadingEnd()], | |||
wrap([Heading(wrap([Text("spam"), Text("eggs")]), 4)])), | |||
wrap([Heading(wraptext("spam", "eggs"), 4)])), | |||
] | |||
for test, valid in tests: | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
@@ -190,11 +181,11 @@ class TestBuilder(TreeEqualityTestCase): | |||
tests = [ | |||
([tokens.CommentStart(), tokens.Text(text="foobar"), | |||
tokens.CommentEnd()], | |||
wrap([Comment(wrap([Text("foobar")]))])), | |||
wrap([Comment(wraptext("foobar"))])), | |||
([tokens.CommentStart(), tokens.Text(text="spam"), | |||
tokens.Text(text="eggs"), tokens.CommentEnd()], | |||
wrap([Comment(wrap([Text("spam"), Text("eggs")]))])), | |||
wrap([Comment(wraptext("spam", "eggs"))])), | |||
] | |||
for test, valid in tests: | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
@@ -218,10 +209,10 @@ class TestBuilder(TreeEqualityTestCase): | |||
tokens.TemplateOpen(), tokens.Text(text="bin"), | |||
tokens.TemplateClose(), tokens.TemplateClose()] | |||
valid = wrap( | |||
[Template(wrap([Template(wrap([Template(wrap([Template(wrap([Text( | |||
"foo")])), Text("bar")]), params=[Parameter(wrap([Text("baz")]), | |||
wrap([Text("biz")]))]), Text("buzz")])), Text("usr")]), params=[ | |||
Parameter(wrap([Text("1")]), wrap([Template(wrap([Text("bin")]))]), | |||
[Template(wrap([Template(wrap([Template(wrap([Template(wraptext( | |||
"foo")), Text("bar")]), params=[Parameter(wraptext("baz"), | |||
wraptext("biz"))]), Text("buzz")])), Text("usr")]), params=[ | |||
Parameter(wraptext("1"), wrap([Template(wraptext("bin"))]), | |||
showkey=False)])]) | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
@@ -247,14 +238,14 @@ class TestBuilder(TreeEqualityTestCase): | |||
tokens.Text(text="nbsp"), tokens.HTMLEntityEnd(), | |||
tokens.TemplateClose()] | |||
valid = wrap( | |||
[Template(wrap([Text("a")]), params=[Parameter(wrap([Text("1")]), | |||
wrap([Text("b")]), showkey=False), Parameter(wrap([Text("2")]), | |||
wrap([Template(wrap([Text("c")]), params=[Parameter(wrap([Text("1") | |||
]), wrap([Wikilink(wrap([Text("d")])), Argument(wrap([Text("e")]))] | |||
), showkey=False)])]), showkey=False)]), Wikilink(wrap([Text("f")] | |||
), wrap([Argument(wrap([Text("g")])), Comment(wrap([Text("h")]))]) | |||
), Template(wrap([Text("i")]), params=[Parameter(wrap([Text("j")]), | |||
wrap([HTMLEntity("nbsp", named=True)]))])]) | |||
[Template(wraptext("a"), params=[Parameter(wraptext("1"), wraptext( | |||
"b"), showkey=False), Parameter(wraptext("2"), wrap([Template( | |||
wraptext("c"), params=[Parameter(wraptext("1"), wrap([Wikilink( | |||
wraptext("d")), Argument(wraptext("e"))]), showkey=False)])]), | |||
showkey=False)]), Wikilink(wraptext("f"), wrap([Argument(wraptext( | |||
"g")), Comment(wraptext("h"))])), Template(wraptext("i"), params=[ | |||
Parameter(wraptext("j"), wrap([HTMLEntity("nbsp", | |||
named=True)]))])]) | |||
self.assertWikicodeEqual(valid, self.builder.build(test)) | |||
if __name__ == "__main__": | |||
@@ -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.nodes import Template, Text, Wikilink | |||
from mwparserfromhell.nodes.extras import Parameter | |||
from mwparserfromhell.smart_list import SmartList | |||
from mwparserfromhell.wikicode import Wikicode | |||
from ._test_tree_equality import TreeEqualityTestCase | |||
from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext | |||
from .compat import range | |||
class TestParser(TreeEqualityTestCase): | |||
@@ -45,18 +43,17 @@ class TestParser(TreeEqualityTestCase): | |||
def test_parsing(self): | |||
"""integration test for parsing overall""" | |||
text = "this is text; {{this|is=a|template={{with|[[links]]|in}}it}}" | |||
wrap = lambda L: Wikicode(SmartList(L)) | |||
expected = wrap([ | |||
Text("this is text; "), | |||
Template(wrap([Text("this")]), [ | |||
Parameter(wrap([Text("is")]), wrap([Text("a")])), | |||
Parameter(wrap([Text("template")]), wrap([ | |||
Template(wrap([Text("with")]), [ | |||
Parameter(wrap([Text("1")]), | |||
wrap([Wikilink(wrap([Text("links")]))]), | |||
Template(wraptext("this"), [ | |||
Parameter(wraptext("is"), wraptext("a")), | |||
Parameter(wraptext("template"), wrap([ | |||
Template(wraptext("with"), [ | |||
Parameter(wraptext("1"), | |||
wrap([Wikilink(wraptext("links"))]), | |||
showkey=False), | |||
Parameter(wrap([Text("2")]), | |||
wrap([Text("in")]), showkey=False) | |||
Parameter(wraptext("2"), | |||
wraptext("in"), showkey=False) | |||
]), | |||
Text("it") | |||
])) | |||
@@ -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 | |||
from mwparserfromhell.nodes import Template, Text | |||
from mwparserfromhell.smart_list import SmartList | |||
from mwparserfromhell.utils import parse_anything | |||
from mwparserfromhell.wikicode import Wikicode | |||
from ._test_tree_equality import TreeEqualityTestCase | |||
from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext | |||
class TestUtils(TreeEqualityTestCase): | |||
"""Tests for the utils module, which provides parse_anything().""" | |||
def test_parse_anything_valid(self): | |||
"""tests for valid input to utils.parse_anything()""" | |||
wrap = lambda L: Wikicode(SmartList(L)) | |||
textify = lambda L: wrap([Text(item) for item in L]) | |||
tests = [ | |||
(wrap([Text("foobar")]), textify(["foobar"])), | |||
(Template(wrap([Text("spam")])), | |||
wrap([Template(textify(["spam"]))])), | |||
("fóóbar", textify(["fóóbar"])), | |||
(b"foob\xc3\xa1r", textify(["foobár"])), | |||
(123, textify(["123"])), | |||
(True, textify(["True"])), | |||
(wraptext("foobar"), wraptext("foobar")), | |||
(Template(wraptext("spam")), wrap([Template(wraptext("spam"))])), | |||
("fóóbar", wraptext("fóóbar")), | |||
(b"foob\xc3\xa1r", wraptext("foobár")), | |||
(123, wraptext("123")), | |||
(True, wraptext("True")), | |||
(None, wrap([])), | |||
([Text("foo"), Text("bar"), Text("baz")], | |||
textify(["foo", "bar", "baz"])), | |||
([wrap([Text("foo")]), Text("bar"), "baz", 123, 456], | |||
textify(["foo", "bar", "baz", "123", "456"])), | |||
([[[([[((("foo",),),)], "bar"],)]]], textify(["foo", "bar"])) | |||
wraptext("foo", "bar", "baz")), | |||
([wraptext("foo"), Text("bar"), "baz", 123, 456], | |||
wraptext("foo", "bar", "baz", "123", "456")), | |||
([[[([[((("foo",),),)], "bar"],)]]], wraptext("foo", "bar")) | |||
] | |||
for test, valid in tests: | |||
self.assertWikicodeEqual(valid, parse_anything(test)) | |||
@@ -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) |