Browse Source

Clean up pytest-ported tests

tags/v0.6.1
Ben Kurtovic 1 year ago
parent
commit
074e368684
29 changed files with 3384 additions and 3377 deletions
  1. +1
    -0
      CHANGELOG
  2. +3
    -2
      README.rst
  3. +2
    -0
      docs/changelog.rst
  4. +3
    -2
      docs/index.rst
  5. +1
    -1
      mwparserfromhell/parser/tokenizer.py
  6. +2
    -2
      scripts/release.sh
  7. +0
    -131
      tests/_test_tree_equality.py
  8. +138
    -0
      tests/conftest.py
  9. +66
    -66
      tests/test_argument.py
  10. +75
    -75
      tests/test_attribute.py
  11. +399
    -399
      tests/test_builder.py
  12. +34
    -35
      tests/test_comment.py
  13. +88
    -87
      tests/test_docs.py
  14. +88
    -88
      tests/test_external_link.py
  15. +55
    -55
      tests/test_heading.py
  16. +158
    -159
      tests/test_html_entity.py
  17. +42
    -42
      tests/test_parameter.py
  18. +46
    -46
      tests/test_parser.py
  19. +383
    -383
      tests/test_smart_list.py
  20. +378
    -378
      tests/test_string_mixin.py
  21. +299
    -298
      tests/test_tag.py
  22. +414
    -413
      tests/test_template.py
  23. +39
    -38
      tests/test_text.py
  24. +3
    -11
      tests/test_tokenizer.py
  25. +60
    -59
      tests/test_tokens.py
  26. +30
    -30
      tests/test_utils.py
  27. +511
    -510
      tests/test_wikicode.py
  28. +66
    -66
      tests/test_wikilink.py
  29. +0
    -1
      tests/tokenizer/integration.mwtest

+ 1
- 0
CHANGELOG View File

@@ -1,5 +1,6 @@
v0.7 (unreleased):

- Port tests to pytest. (#237)
- Improve parsing of external links. (#232)

v0.6 (released December 21, 2020):


+ 3
- 2
README.rst View File

@@ -29,8 +29,8 @@ Alternatively, get the latest development version::
cd mwparserfromhell
python setup.py install

You can run the comprehensive unit testing suite with
``python -m unittest discover``.
The comprehensive unit testing suite requires `pytest`_ (``pip install pytest``)
and can be run with ``python -m pytest``.

Usage
-----
@@ -210,6 +210,7 @@ Python 3 code (using the API_ and the requests_ library):
.. _GitHub: https://github.com/earwig/mwparserfromhell
.. _Python Package Index: https://pypi.org/
.. _get pip: https://pypi.org/project/pip/
.. _pytest: https://docs.pytest.org/
.. _Word-ending links: https://www.mediawiki.org/wiki/Help:Links#linktrail
.. _EarwigBot: https://github.com/earwig/earwigbot
.. _Pywikibot: https://www.mediawiki.org/wiki/Manual:Pywikibot


+ 2
- 0
docs/changelog.rst View File

@@ -7,6 +7,8 @@ v0.7
Unreleased
(`changes <https://github.com/earwig/mwparserfromhell/compare/v0.6...develop>`__):

- Port tests to pytest.
(`#237 <https://github.com/earwig/mwparserfromhell/issues/237>`_)
- Improve parsing of external links.
(`#232 <https://github.com/earwig/mwparserfromhell/issues/232>`_)



+ 3
- 2
docs/index.rst View File

@@ -27,11 +27,12 @@ Alternatively, get the latest development version::
cd mwparserfromhell
python setup.py install

You can run the comprehensive unit testing suite with
``python -m unittest discover``.
The comprehensive unit testing suite requires `pytest`_ (``pip install pytest``)
and can be run with ``python -m pytest``.

.. _Python Package Index: https://pypi.org/
.. _get pip: https://pypi.org/project/pip/
.. _pytest: https://docs.pytest.org/

Contents
--------


+ 1
- 1
mwparserfromhell/parser/tokenizer.py View File

@@ -491,7 +491,7 @@ class Tokenizer:
return self._parse(push=False), None, 0
elif any(ch in this for ch in (" ", "\n", "[", "]", "<", ">",
"\"")):
before, after = re.split("[ \n\[\]<>\"]", this, maxsplit=1)
before, after = re.split(r"[ \n[\]<>\"]", this, maxsplit=1)
delimiter = this[len(before)]
if brackets:
self._emit_text(before)


+ 2
- 2
scripts/release.sh View File

@@ -102,7 +102,7 @@ test_release() {
echo " done."
echo -n "Installing mwparserfromhell with pip..."
pip -q install --upgrade pip
pip -q install mwparserfromhell
pip -q install mwparserfromhell pytest
echo " done."
echo -n "Checking version..."
reported_version=$(python -c 'print(__import__("mwparserfromhell").__version__)')
@@ -135,7 +135,7 @@ test_release() {
cd mwparserfromhell-$VERSION
echo "Running unit tests..."
python setup.py -q install
python -m unittest discover
python -m pytest
if [[ "$?" != "0" ]]; then
echo "*** ERROR: Unit tests failed!"
deactivate


+ 0
- 131
tests/_test_tree_equality.py View File

@@ -1,131 +0,0 @@
# Copyright (C) 2012-2020 Ben Kurtovic <ben.kurtovic@gmail.com>
#
# 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 mwparserfromhell.nodes import (Argument, Comment, Heading, HTMLEntity,
Tag, Template, Text, Wikilink)
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])

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

This adds a number of type equality functions, for Wikicode, Text,
Templates, and Wikilinks.
"""

def assertNodeEqual(self, expected, actual):
"""Assert that two Nodes have the same type and have the same data."""
registry = {
Argument: self.assertArgumentNodeEqual,
Comment: self.assertCommentNodeEqual,
Heading: self.assertHeadingNodeEqual,
HTMLEntity: self.assertHTMLEntityNodeEqual,
Tag: self.assertTagNodeEqual,
Template: self.assertTemplateNodeEqual,
Text: self.assertTextNodeEqual,
Wikilink: self.assertWikilinkNodeEqual
}
for nodetype in registry:
if isinstance(expected, nodetype):
assert isinstance(actual, nodetype)
registry[nodetype](expected, actual)

def assertArgumentNodeEqual(self, expected, actual):
"""Assert that two Argument nodes have the same data."""
self.assertWikicodeEqual(expected.name, actual.name)
if expected.default is not None:
self.assertWikicodeEqual(expected.default, actual.default)
else:
assert actual.default is None

def assertCommentNodeEqual(self, expected, actual):
"""Assert that two Comment nodes have the same data."""
assert expected.contents == actual.contents

def assertHeadingNodeEqual(self, expected, actual):
"""Assert that two Heading nodes have the same data."""
self.assertWikicodeEqual(expected.title, actual.title)
assert expected.level == actual.level

def assertHTMLEntityNodeEqual(self, expected, actual):
"""Assert that two HTMLEntity nodes have the same data."""
assert expected.value == actual.value
assert expected.named is actual.named
assert expected.hexadecimal is actual.hexadecimal
assert expected.hex_char == actual.hex_char

def assertTagNodeEqual(self, expected, actual):
"""Assert that two Tag nodes have the same data."""
self.assertWikicodeEqual(expected.tag, actual.tag)
if expected.contents is not None:
self.assertWikicodeEqual(expected.contents, actual.contents)
length = len(expected.attributes)
assert length == len(actual.attributes)
for i in range(length):
exp_attr = expected.attributes[i]
act_attr = actual.attributes[i]
self.assertWikicodeEqual(exp_attr.name, act_attr.name)
if exp_attr.value is not None:
self.assertWikicodeEqual(exp_attr.value, act_attr.value)
assert exp_attr.quotes == act_attr.quotes
assert exp_attr.pad_first == act_attr.pad_first
assert exp_attr.pad_before_eq == act_attr.pad_before_eq
assert exp_attr.pad_after_eq == act_attr.pad_after_eq
assert expected.wiki_markup == actual.wiki_markup
assert expected.self_closing is actual.self_closing
assert expected.invalid is actual.invalid
assert expected.implicit is actual.implicit
assert expected.padding == actual.padding
self.assertWikicodeEqual(expected.closing_tag, actual.closing_tag)

def assertTemplateNodeEqual(self, expected, actual):
"""Assert that two Template nodes have the same data."""
self.assertWikicodeEqual(expected.name, actual.name)
length = len(expected.params)
assert length == len(actual.params)
for i in range(length):
exp_param = expected.params[i]
act_param = actual.params[i]
self.assertWikicodeEqual(exp_param.name, act_param.name)
self.assertWikicodeEqual(exp_param.value, act_param.value)
assert exp_param.showkey is act_param.showkey

def assertTextNodeEqual(self, expected, actual):
"""Assert that two Text nodes have the same data."""
assert expected.value == actual.value

def assertWikilinkNodeEqual(self, expected, actual):
"""Assert that two Wikilink nodes have the same data."""
self.assertWikicodeEqual(expected.title, actual.title)
if expected.text is not None:
self.assertWikicodeEqual(expected.text, actual.text)
else:
assert None is actual.text

def assertWikicodeEqual(self, expected, actual):
"""Assert that two Wikicode objects have the same data."""
assert isinstance(actual, Wikicode)
length = len(expected.nodes)
assert length == len(actual.nodes)
for i in range(length):
self.assertNodeEqual(expected.get(i), actual.get(i))

+ 138
- 0
tests/conftest.py View File

@@ -0,0 +1,138 @@
# Copyright (C) 2012-2020 Ben Kurtovic <ben.kurtovic@gmail.com>
#
# 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 mwparserfromhell.nodes import (Argument, Comment, ExternalLink, Heading,
HTMLEntity, Tag, Template, Text, Wikilink)
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 _assert_node_equal(expected, actual):
"""Assert that two Nodes have the same type and have the same data."""
registry = {
Argument: _assert_argument_node_equal,
Comment: _assert_comment_node_equal,
ExternalLink: _assert_external_link_node_equal,
Heading: _assert_heading_node_equal,
HTMLEntity: _assert_html_entity_node_equal,
Tag: _assert_tag_node_equal,
Template: _assert_template_node_equal,
Text: _assert_text_node_equal,
Wikilink: _assert_wikilink_node_equal,
}
# pylint: disable=unidiomatic-typecheck
assert type(expected) == type(actual)
registry[type(expected)](expected, actual)

def _assert_argument_node_equal(expected, actual):
"""Assert that two Argument nodes have the same data."""
assert_wikicode_equal(expected.name, actual.name)
if expected.default is not None:
assert_wikicode_equal(expected.default, actual.default)
else:
assert actual.default is None

def _assert_comment_node_equal(expected, actual):
"""Assert that two Comment nodes have the same data."""
assert expected.contents == actual.contents

def _assert_external_link_node_equal(expected, actual):
"""Assert that two ExternalLink nodes have the same data."""
assert_wikicode_equal(expected.url, actual.url)
if expected.title is not None:
assert_wikicode_equal(expected.title, actual.title)
else:
assert actual.title is None
assert expected.brackets is actual.brackets
assert expected.suppress_space is actual.suppress_space

def _assert_heading_node_equal(expected, actual):
"""Assert that two Heading nodes have the same data."""
assert_wikicode_equal(expected.title, actual.title)
assert expected.level == actual.level

def _assert_html_entity_node_equal(expected, actual):
"""Assert that two HTMLEntity nodes have the same data."""
assert expected.value == actual.value
assert expected.named is actual.named
assert expected.hexadecimal is actual.hexadecimal
assert expected.hex_char == actual.hex_char

def _assert_tag_node_equal(expected, actual):
"""Assert that two Tag nodes have the same data."""
assert_wikicode_equal(expected.tag, actual.tag)
if expected.contents is not None:
assert_wikicode_equal(expected.contents, actual.contents)
else:
assert actual.contents is None
length = len(expected.attributes)
assert length == len(actual.attributes)
for i in range(length):
exp_attr = expected.attributes[i]
act_attr = actual.attributes[i]
assert_wikicode_equal(exp_attr.name, act_attr.name)
if exp_attr.value is not None:
assert_wikicode_equal(exp_attr.value, act_attr.value)
assert exp_attr.quotes == act_attr.quotes
else:
assert act_attr.value is None
assert exp_attr.pad_first == act_attr.pad_first
assert exp_attr.pad_before_eq == act_attr.pad_before_eq
assert exp_attr.pad_after_eq == act_attr.pad_after_eq
assert expected.wiki_markup == actual.wiki_markup
assert expected.self_closing is actual.self_closing
assert expected.invalid is actual.invalid
assert expected.implicit is actual.implicit
assert expected.padding == actual.padding
assert_wikicode_equal(expected.closing_tag, actual.closing_tag)

def _assert_template_node_equal(expected, actual):
"""Assert that two Template nodes have the same data."""
assert_wikicode_equal(expected.name, actual.name)
length = len(expected.params)
assert length == len(actual.params)
for i in range(length):
exp_param = expected.params[i]
act_param = actual.params[i]
assert_wikicode_equal(exp_param.name, act_param.name)
assert_wikicode_equal(exp_param.value, act_param.value)
assert exp_param.showkey is act_param.showkey

def _assert_text_node_equal(expected, actual):
"""Assert that two Text nodes have the same data."""
assert expected.value == actual.value

def _assert_wikilink_node_equal(expected, actual):
"""Assert that two Wikilink nodes have the same data."""
assert_wikicode_equal(expected.title, actual.title)
if expected.text is not None:
assert_wikicode_equal(expected.text, actual.text)
else:
assert actual.text is None

def assert_wikicode_equal(expected, actual):
"""Assert that two Wikicode objects have the same data."""
assert isinstance(actual, Wikicode)
length = len(expected.nodes)
assert length == len(actual.nodes)
for i in range(length):
_assert_node_equal(expected.get(i), actual.get(i))

+ 66
- 66
tests/test_argument.py View File

@@ -18,78 +18,78 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Test cases for the Argument node.
"""

import pytest

from mwparserfromhell.nodes import Argument, Text
from .conftest import assert_wikicode_equal, wrap, wraptext

from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

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

def test_str(self):
"""test Argument.__str__()"""
node = Argument(wraptext("foobar"))
assert "{{{foobar}}}" == str(node)
node2 = Argument(wraptext("foo"), wraptext("bar"))
assert "{{{foo|bar}}}" == str(node2)
def test_str():
"""test Argument.__str__()"""
node = Argument(wraptext("foobar"))
assert "{{{foobar}}}" == str(node)
node2 = Argument(wraptext("foo"), wraptext("bar"))
assert "{{{foo|bar}}}" == str(node2)

def test_children(self):
"""test Argument.__children__()"""
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foo"), wrap([Text("bar"), Text("baz")]))
gen1 = node1.__children__()
gen2 = node2.__children__()
assert node1.name is next(gen1)
assert node2.name is next(gen2)
assert node2.default is next(gen2)
with pytest.raises(StopIteration):
next(gen1)
with pytest.raises(StopIteration):
next(gen2)
def test_children():
"""test Argument.__children__()"""
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foo"), wrap([Text("bar"), Text("baz")]))
gen1 = node1.__children__()
gen2 = node2.__children__()
assert node1.name is next(gen1)
assert node2.name is next(gen2)
assert node2.default is next(gen2)
with pytest.raises(StopIteration):
next(gen1)
with pytest.raises(StopIteration):
next(gen2)

def test_strip(self):
"""test Argument.__strip__()"""
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foo"), wraptext("bar"))
assert node1.__strip__() is None
assert "bar" == node2.__strip__()
def test_strip():
"""test Argument.__strip__()"""
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foo"), wraptext("bar"))
assert node1.__strip__() is None
assert "bar" == node2.__strip__()

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), "}}}"]
assert valid == output
def test_showtree():
"""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), "}}}"]
assert valid == output

def test_name(self):
"""test getter/setter for the name attribute"""
name = wraptext("foobar")
node1 = Argument(name)
node2 = Argument(name, wraptext("baz"))
assert name is node1.name
assert name is 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_name():
"""test getter/setter for the name attribute"""
name = wraptext("foobar")
node1 = Argument(name)
node2 = Argument(name, wraptext("baz"))
assert name is node1.name
assert name is node2.name
node1.name = "héhehé"
node2.name = "héhehé"
assert_wikicode_equal(wraptext("héhehé"), node1.name)
assert_wikicode_equal(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)
assert None is node1.default
assert default is node2.default
node1.default = "buzz"
node2.default = None
self.assertWikicodeEqual(wraptext("buzz"), node1.default)
assert None is node2.default
def test_default():
"""test getter/setter for the default attribute"""
default = wraptext("baz")
node1 = Argument(wraptext("foobar"))
node2 = Argument(wraptext("foobar"), default)
assert None is node1.default
assert default is node2.default
node1.default = "buzz"
node2.default = None
assert_wikicode_equal(wraptext("buzz"), node1.default)
assert None is node2.default

+ 75
- 75
tests/test_attribute.py View File

@@ -18,88 +18,88 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Test cases for the Attribute node extra.
"""

import pytest

from mwparserfromhell.nodes import Template
from mwparserfromhell.nodes.extras import Attribute
from .conftest import assert_wikicode_equal, wrap, wraptext

from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

class TestAttribute(TreeEqualityTestCase):
"""Test cases for the Attribute node extra."""
def test_str():
"""test Attribute.__str__()"""
node = Attribute(wraptext("foo"))
assert " foo" == str(node)
node2 = Attribute(wraptext("foo"), wraptext("bar"))
assert ' foo="bar"' == str(node2)
node3 = Attribute(wraptext("a"), wraptext("b"), '"', "", " ", " ")
assert 'a = "b"' == str(node3)
node4 = Attribute(wraptext("a"), wraptext("b"), "'", "", " ", " ")
assert "a = 'b'" == str(node4)
node5 = Attribute(wraptext("a"), wraptext("b"), None, "", " ", " ")
assert "a = b" == str(node5)
node6 = Attribute(wraptext("a"), wrap([]), None, " ", "", " ")
assert " a= " == str(node6)

def test_str(self):
"""test Attribute.__str__()"""
node = Attribute(wraptext("foo"))
assert " foo" == str(node)
node2 = Attribute(wraptext("foo"), wraptext("bar"))
assert ' foo="bar"' == str(node2)
node3 = Attribute(wraptext("a"), wraptext("b"), '"', "", " ", " ")
assert 'a = "b"' == str(node3)
node4 = Attribute(wraptext("a"), wraptext("b"), "'", "", " ", " ")
assert "a = 'b'" == str(node4)
node5 = Attribute(wraptext("a"), wraptext("b"), None, "", " ", " ")
assert "a = b" == str(node5)
node6 = Attribute(wraptext("a"), wrap([]), None, " ", "", " ")
assert " a= " == str(node6)
def test_name():
"""test getter/setter for the name attribute"""
name = wraptext("id")
node = Attribute(name, wraptext("bar"))
assert name is node.name
node.name = "{{id}}"
assert_wikicode_equal(wrap([Template(wraptext("id"))]), node.name)

def test_name(self):
"""test getter/setter for the name attribute"""
name = wraptext("id")
node = Attribute(name, wraptext("bar"))
assert name is node.name
node.name = "{{id}}"
self.assertWikicodeEqual(wrap([Template(wraptext("id"))]), node.name)
def test_value():
"""test getter/setter for the value attribute"""
value = wraptext("foo")
node = Attribute(wraptext("id"), value)
assert value is node.value
node.value = "{{bar}}"
assert_wikicode_equal(wrap([Template(wraptext("bar"))]), node.value)
node.value = None
assert None is node.value
node2 = Attribute(wraptext("id"), wraptext("foo"), None)
node2.value = "foo bar baz"
assert_wikicode_equal(wraptext("foo bar baz"), node2.value)
assert '"' == node2.quotes
node2.value = 'foo "bar" baz'
assert_wikicode_equal(wraptext('foo "bar" baz'), node2.value)
assert "'" == node2.quotes
node2.value = "foo 'bar' baz"
assert_wikicode_equal(wraptext("foo 'bar' baz"), node2.value)
assert '"' == node2.quotes
node2.value = "fo\"o 'bar' b\"az"
assert_wikicode_equal(wraptext("fo\"o 'bar' b\"az"), node2.value)
assert '"' == node2.quotes

def test_value(self):
"""test getter/setter for the value attribute"""
value = wraptext("foo")
node = Attribute(wraptext("id"), value)
assert value is node.value
node.value = "{{bar}}"
self.assertWikicodeEqual(wrap([Template(wraptext("bar"))]), node.value)
node.value = None
assert None is node.value
node2 = Attribute(wraptext("id"), wraptext("foo"), None)
node2.value = "foo bar baz"
self.assertWikicodeEqual(wraptext("foo bar baz"), node2.value)
assert '"' == node2.quotes
node2.value = 'foo "bar" baz'
self.assertWikicodeEqual(wraptext('foo "bar" baz'), node2.value)
assert "'" == node2.quotes
node2.value = "foo 'bar' baz"
self.assertWikicodeEqual(wraptext("foo 'bar' baz"), node2.value)
assert '"' == node2.quotes
node2.value = "fo\"o 'bar' b\"az"
self.assertWikicodeEqual(wraptext("fo\"o 'bar' b\"az"), node2.value)
assert '"' == node2.quotes
def test_quotes():
"""test getter/setter for the quotes attribute"""
node1 = Attribute(wraptext("id"), wraptext("foo"), None)
node2 = Attribute(wraptext("id"), wraptext("bar"))
node3 = Attribute(wraptext("id"), wraptext("foo bar baz"))
assert None is node1.quotes
assert '"' == node2.quotes
node1.quotes = "'"
node2.quotes = None
assert "'" == node1.quotes
assert None is node2.quotes
with pytest.raises(ValueError):
node1.__setattr__("quotes", "foobar")
with pytest.raises(ValueError):
node3.__setattr__("quotes", None)
with pytest.raises(ValueError):
Attribute(wraptext("id"), wraptext("foo bar baz"), None)

def test_quotes(self):
"""test getter/setter for the quotes attribute"""
node1 = Attribute(wraptext("id"), wraptext("foo"), None)
node2 = Attribute(wraptext("id"), wraptext("bar"))
node3 = Attribute(wraptext("id"), wraptext("foo bar baz"))
assert None is node1.quotes
assert '"' == node2.quotes
node1.quotes = "'"
node2.quotes = None
assert "'" == node1.quotes
assert None is node2.quotes
with pytest.raises(ValueError):
node1.__setattr__("quotes", "foobar")
def test_padding():
"""test getter/setter for the padding attributes"""
for pad in ["pad_first", "pad_before_eq", "pad_after_eq"]:
node = Attribute(wraptext("id"), wraptext("foo"), **{pad: "\n"})
assert "\n" == getattr(node, pad)
setattr(node, pad, " ")
assert " " == getattr(node, pad)
setattr(node, pad, None)
assert "" == getattr(node, pad)
with pytest.raises(ValueError):
node3.__setattr__("quotes", None)
with pytest.raises(ValueError):
Attribute(wraptext("id"), wraptext("foo bar baz"), None)

def test_padding(self):
"""test getter/setter for the padding attributes"""
for pad in ["pad_first", "pad_before_eq", "pad_after_eq"]:
node = Attribute(wraptext("id"), wraptext("foo"), **{pad: "\n"})
assert "\n" == getattr(node, pad)
setattr(node, pad, " ")
assert " " == getattr(node, pad)
setattr(node, pad, None)
assert "" == getattr(node, pad)
with pytest.raises(ValueError):
node.__setattr__(pad, True)
node.__setattr__(pad, True)

+ 399
- 399
tests/test_builder.py View File

@@ -18,6 +18,10 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Tests for the builder, which turns tokens into Wikicode objects.
"""

import pytest

from mwparserfromhell.nodes import (Argument, Comment, ExternalLink, Heading,
@@ -25,402 +29,398 @@ from mwparserfromhell.nodes import (Argument, Comment, ExternalLink, Heading,
from mwparserfromhell.nodes.extras import Attribute, Parameter
from mwparserfromhell.parser import tokens, ParserError
from mwparserfromhell.parser.builder import Builder

from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

class TestBuilder(TreeEqualityTestCase):
"""Tests for the builder, which turns tokens into Wikicode objects."""

@pytest.fixture()
def builder(self):
return Builder()

@pytest.mark.parametrize("test,valid", [
([tokens.Text(text="foobar")], wraptext("foobar")),
([tokens.Text(text="fóóbar")], wraptext("fóóbar")),
([tokens.Text(text="spam"), tokens.Text(text="eggs")],
wraptext("spam", "eggs")),
])
def test_text(self, builder, test, valid):
"""tests for building Text nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.TemplateOpen(), tokens.Text(text="foobar"),
tokens.TemplateClose()],
wrap([Template(wraptext("foobar"))])),

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

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateClose()],
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(wraptext("foo"), params=[
Parameter(wraptext("bar"), wraptext("baz"))])])),

([tokens.TemplateOpen(), tokens.TemplateParamSeparator(),
tokens.TemplateParamSeparator(), tokens.TemplateParamEquals(),
tokens.TemplateParamSeparator(), tokens.TemplateClose()],
wrap([Template(wrap([]), params=[
Parameter(wraptext("1"), wrap([]), showkey=False),
Parameter(wrap([]), wrap([]), showkey=True),
Parameter(wraptext("2"), wrap([]), showkey=False)])])),

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateParamEquals(), tokens.Text(text="baz"),
tokens.TemplateParamSeparator(), tokens.Text(text="biz"),
tokens.TemplateParamSeparator(), tokens.Text(text="buzz"),
tokens.TemplateParamSeparator(), tokens.Text(text="3"),
tokens.TemplateParamEquals(), tokens.Text(text="buff"),
tokens.TemplateParamSeparator(), tokens.Text(text="baff"),
tokens.TemplateClose()],
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)])])),
])
def test_template(self, builder, test, valid):
"""tests for building Template nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.ArgumentOpen(), tokens.Text(text="foobar"),
tokens.ArgumentClose()],
wrap([Argument(wraptext("foobar"))])),

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

([tokens.ArgumentOpen(), tokens.Text(text="foo"),
tokens.ArgumentSeparator(), tokens.Text(text="bar"),
tokens.ArgumentClose()],
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(wraptext("foo", "bar"), wraptext("baz", "biz"))])),
])
def test_argument(self, builder, test, valid):
"""tests for building Argument nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.WikilinkOpen(), tokens.Text(text="foobar"),
tokens.WikilinkClose()],
wrap([Wikilink(wraptext("foobar"))])),

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

([tokens.WikilinkOpen(), tokens.Text(text="foo"),
tokens.WikilinkSeparator(), tokens.Text(text="bar"),
tokens.WikilinkClose()],
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(wraptext("foo", "bar"), wraptext("baz", "biz"))])),
])
def test_wikilink(self, builder, test, valid):
"""tests for building Wikilink nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.ExternalLinkOpen(brackets=False),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"),
brackets=False)])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"))])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkSeparator(), tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"), wrap([]))])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkSeparator(), tokens.Text(text="Example"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"),
wraptext("Example"))])),

([tokens.ExternalLinkOpen(brackets=False),
tokens.Text(text="http://example"), tokens.Text(text=".com/foo"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example", ".com/foo"),
brackets=False)])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example"), tokens.Text(text=".com/foo"),
tokens.ExternalLinkSeparator(), tokens.Text(text="Example"),
tokens.Text(text=" Web Page"), tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example", ".com/foo"),
wraptext("Example", " Web Page"))])),
])
def test_external_link(self, builder, test, valid):
"""tests for building ExternalLink nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.HTMLEntityStart(), tokens.Text(text="nbsp"),
tokens.HTMLEntityEnd()],
wrap([HTMLEntity("nbsp", named=True, hexadecimal=False)])),

([tokens.HTMLEntityStart(), tokens.HTMLEntityNumeric(),
tokens.Text(text="107"), tokens.HTMLEntityEnd()],
wrap([HTMLEntity("107", named=False, hexadecimal=False)])),

([tokens.HTMLEntityStart(), tokens.HTMLEntityNumeric(),
tokens.HTMLEntityHex(char="X"), tokens.Text(text="6B"),
tokens.HTMLEntityEnd()],
wrap([HTMLEntity("6B", named=False, hexadecimal=True,
hex_char="X")])),
])
def test_html_entity(self, builder, test, valid):
"""tests for building HTMLEntity nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.HeadingStart(level=2), tokens.Text(text="foobar"),
tokens.HeadingEnd()],
wrap([Heading(wraptext("foobar"), 2)])),

([tokens.HeadingStart(level=4), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.HeadingEnd()],
wrap([Heading(wraptext("spam", "eggs"), 4)])),
])
def test_heading(self, builder, test, valid):
"""tests for building Heading nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.CommentStart(), tokens.Text(text="foobar"),
tokens.CommentEnd()],
wrap([Comment("foobar")])),

([tokens.CommentStart(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.CommentEnd()],
wrap([Comment("spameggs")])),
])
def test_comment(self, builder, test, valid):
"""tests for building Comment nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
# <ref></ref>
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagCloseOpen(padding=""), tokens.TagOpenClose(),
tokens.Text(text="ref"), tokens.TagCloseClose()],
wrap([Tag(wraptext("ref"), wrap([]),
closing_tag=wraptext("ref"))])),

# <ref name></ref>
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="name"), tokens.TagCloseOpen(padding=""),
tokens.TagOpenClose(), tokens.Text(text="ref"),
tokens.TagCloseClose()],
wrap([Tag(wraptext("ref"), wrap([]),
attrs=[Attribute(wraptext("name"))])])),

# <ref name="abc" />
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="name"), tokens.TagAttrEquals(),
tokens.TagAttrQuote(char='"'), tokens.Text(text="abc"),
tokens.TagCloseSelfclose(padding=" ")],
wrap([Tag(wraptext("ref"),
attrs=[Attribute(wraptext("name"), wraptext("abc"))],
self_closing=True, padding=" ")])),

# <br/>
([tokens.TagOpenOpen(), tokens.Text(text="br"),
tokens.TagCloseSelfclose(padding="")],
wrap([Tag(wraptext("br"), self_closing=True)])),

# <li>
([tokens.TagOpenOpen(), tokens.Text(text="li"),
tokens.TagCloseSelfclose(padding="", implicit=True)],
wrap([Tag(wraptext("li"), self_closing=True, implicit=True)])),

# </br>
([tokens.TagOpenOpen(invalid=True), tokens.Text(text="br"),
tokens.TagCloseSelfclose(padding="", implicit=True)],
wrap([Tag(wraptext("br"), self_closing=True, invalid=True,
implicit=True)])),

# </br/>
([tokens.TagOpenOpen(invalid=True), tokens.Text(text="br"),
tokens.TagCloseSelfclose(padding="")],
wrap([Tag(wraptext("br"), self_closing=True, invalid=True)])),

# <ref name={{abc}} foo="bar {{baz}}" abc={{de}}f ghi=j{{k}}{{l}}
# mno = '{{p}} [[q]] {{r}}'>[[Source]]</ref>
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="name"), tokens.TagAttrEquals(),
tokens.TemplateOpen(), tokens.Text(text="abc"),
tokens.TemplateClose(),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="foo"), tokens.TagAttrEquals(),
tokens.TagAttrQuote(char='"'), tokens.Text(text="bar "),
tokens.TemplateOpen(), tokens.Text(text="baz"),
tokens.TemplateClose(),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="abc"), tokens.TagAttrEquals(),
tokens.TemplateOpen(), tokens.Text(text="de"),
tokens.TemplateClose(), tokens.Text(text="f"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="ghi"), tokens.TagAttrEquals(),
tokens.Text(text="j"), tokens.TemplateOpen(),
tokens.Text(text="k"), tokens.TemplateClose(),
tokens.TemplateOpen(), tokens.Text(text="l"),
tokens.TemplateClose(),
tokens.TagAttrStart(pad_first=" \n ", pad_before_eq=" ",
pad_after_eq=" "),
tokens.Text(text="mno"), tokens.TagAttrEquals(),
tokens.TagAttrQuote(char="'"), tokens.TemplateOpen(),
tokens.Text(text="p"), tokens.TemplateClose(),
tokens.Text(text=" "), tokens.WikilinkOpen(),
tokens.Text(text="q"), tokens.WikilinkClose(),
tokens.Text(text=" "), tokens.TemplateOpen(),
tokens.Text(text="r"), tokens.TemplateClose(),
tokens.TagCloseOpen(padding=""), tokens.WikilinkOpen(),
tokens.Text(text="Source"), tokens.WikilinkClose(),
tokens.TagOpenClose(), tokens.Text(text="ref"),
tokens.TagCloseClose()],
wrap([Tag(wraptext("ref"), wrap([Wikilink(wraptext("Source"))]), [
Attribute(wraptext("name"),
wrap([Template(wraptext("abc"))]), None),
Attribute(wraptext("foo"), wrap([Text("bar "),
Template(wraptext("baz"))]), pad_first=" "),
Attribute(wraptext("abc"), wrap([Template(wraptext("de")),
Text("f")]), None),
Attribute(wraptext("ghi"), wrap([Text("j"),
Template(wraptext("k")),
Template(wraptext("l"))]), None),
Attribute(wraptext("mno"), wrap([Template(wraptext("p")),
Text(" "), Wikilink(wraptext("q")), Text(" "),
Template(wraptext("r"))]), "'", " \n ", " ",
" ")])])),

# "''italic text''"
([tokens.TagOpenOpen(wiki_markup="''"), tokens.Text(text="i"),
tokens.TagCloseOpen(), tokens.Text(text="italic text"),
tokens.TagOpenClose(), tokens.Text(text="i"),
tokens.TagCloseClose()],
wrap([Tag(wraptext("i"), wraptext("italic text"),
wiki_markup="''")])),

# * bullet
([tokens.TagOpenOpen(wiki_markup="*"), tokens.Text(text="li"),
tokens.TagCloseSelfclose(), tokens.Text(text=" bullet")],
wrap([Tag(wraptext("li"), wiki_markup="*", self_closing=True),
Text(" bullet")])),
])
def test_tag(self, builder, test, valid):
"""tests for building Tag nodes"""
self.assertWikicodeEqual(valid, builder.build(test))

def test_integration(self, builder):
"""a test for building a combination of templates together"""
# {{{{{{{{foo}}bar|baz=biz}}buzz}}usr|{{bin}}}}
test = [tokens.TemplateOpen(), tokens.TemplateOpen(),
tokens.TemplateOpen(), tokens.TemplateOpen(),
tokens.Text(text="foo"), tokens.TemplateClose(),
tokens.Text(text="bar"), tokens.TemplateParamSeparator(),
tokens.Text(text="baz"), tokens.TemplateParamEquals(),
tokens.Text(text="biz"), tokens.TemplateClose(),
tokens.Text(text="buzz"), tokens.TemplateClose(),
tokens.Text(text="usr"), tokens.TemplateParamSeparator(),
tokens.TemplateOpen(), tokens.Text(text="bin"),
tokens.TemplateClose(), tokens.TemplateClose()]
valid = wrap(
[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, builder.build(test))

def test_integration2(self, builder):
"""an even more audacious test for building a horrible wikicode mess"""
# {{a|b|{{c|[[d]]{{{e}}}}}}}[[f|{{{g}}}<!--h-->]]{{i|j=&nbsp;}}
test = [tokens.TemplateOpen(), tokens.Text(text="a"),
tokens.TemplateParamSeparator(), tokens.Text(text="b"),
tokens.TemplateParamSeparator(), tokens.TemplateOpen(),
tokens.Text(text="c"), tokens.TemplateParamSeparator(),
tokens.WikilinkOpen(), tokens.Text(text="d"),
tokens.WikilinkClose(), tokens.ArgumentOpen(),
tokens.Text(text="e"), tokens.ArgumentClose(),
tokens.TemplateClose(), tokens.TemplateClose(),
tokens.WikilinkOpen(), tokens.Text(text="f"),
tokens.WikilinkSeparator(), tokens.ArgumentOpen(),
tokens.Text(text="g"), tokens.ArgumentClose(),
tokens.CommentStart(), tokens.Text(text="h"),
tokens.CommentEnd(), tokens.WikilinkClose(),
tokens.TemplateOpen(), tokens.Text(text="i"),
tokens.TemplateParamSeparator(), tokens.Text(text="j"),
tokens.TemplateParamEquals(), tokens.HTMLEntityStart(),
tokens.Text(text="nbsp"), tokens.HTMLEntityEnd(),
tokens.TemplateClose()]
valid = wrap(
[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("h")])), Template(wraptext("i"), params=[
Parameter(wraptext("j"), wrap([HTMLEntity("nbsp",
named=True)]))])])
self.assertWikicodeEqual(valid, builder.build(test))

@pytest.mark.parametrize("tokens", [
[tokens.TemplateOpen(), tokens.TemplateParamSeparator()],
[tokens.TemplateOpen()], [tokens.ArgumentOpen()],
[tokens.WikilinkOpen()], [tokens.ExternalLinkOpen()],
[tokens.HeadingStart()], [tokens.CommentStart()],
[tokens.TagOpenOpen(), tokens.TagAttrStart()],
[tokens.TagOpenOpen()]
])
def test_parser_errors(self, builder, tokens):
"""test whether ParserError gets thrown for bad input"""
with pytest.raises(ParserError):
builder.build(tokens)

def test_parser_errors_templateclose(self, builder):
with pytest.raises(
ParserError,
match=r"_handle_token\(\) got unexpected TemplateClose"
):
builder.build([tokens.TemplateClose()])
from .conftest import assert_wikicode_equal, wrap, wraptext

@pytest.fixture()
def builder():
return Builder()

@pytest.mark.parametrize("test,valid", [
([tokens.Text(text="foobar")], wraptext("foobar")),
([tokens.Text(text="fóóbar")], wraptext("fóóbar")),
([tokens.Text(text="spam"), tokens.Text(text="eggs")],
wraptext("spam", "eggs")),
])
def test_text(builder, test, valid):
"""tests for building Text nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.TemplateOpen(), tokens.Text(text="foobar"),
tokens.TemplateClose()],
wrap([Template(wraptext("foobar"))])),

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

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateClose()],
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(wraptext("foo"), params=[
Parameter(wraptext("bar"), wraptext("baz"))])])),

([tokens.TemplateOpen(), tokens.TemplateParamSeparator(),
tokens.TemplateParamSeparator(), tokens.TemplateParamEquals(),
tokens.TemplateParamSeparator(), tokens.TemplateClose()],
wrap([Template(wrap([]), params=[
Parameter(wraptext("1"), wrap([]), showkey=False),
Parameter(wrap([]), wrap([]), showkey=True),
Parameter(wraptext("2"), wrap([]), showkey=False)])])),

([tokens.TemplateOpen(), tokens.Text(text="foo"),
tokens.TemplateParamSeparator(), tokens.Text(text="bar"),
tokens.TemplateParamEquals(), tokens.Text(text="baz"),
tokens.TemplateParamSeparator(), tokens.Text(text="biz"),
tokens.TemplateParamSeparator(), tokens.Text(text="buzz"),
tokens.TemplateParamSeparator(), tokens.Text(text="3"),
tokens.TemplateParamEquals(), tokens.Text(text="buff"),
tokens.TemplateParamSeparator(), tokens.Text(text="baff"),
tokens.TemplateClose()],
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)])])),
])
def test_template(builder, test, valid):
"""tests for building Template nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.ArgumentOpen(), tokens.Text(text="foobar"),
tokens.ArgumentClose()],
wrap([Argument(wraptext("foobar"))])),

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

([tokens.ArgumentOpen(), tokens.Text(text="foo"),
tokens.ArgumentSeparator(), tokens.Text(text="bar"),
tokens.ArgumentClose()],
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(wraptext("foo", "bar"), wraptext("baz", "biz"))])),
])
def test_argument(builder, test, valid):
"""tests for building Argument nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.WikilinkOpen(), tokens.Text(text="foobar"),
tokens.WikilinkClose()],
wrap([Wikilink(wraptext("foobar"))])),

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

([tokens.WikilinkOpen(), tokens.Text(text="foo"),
tokens.WikilinkSeparator(), tokens.Text(text="bar"),
tokens.WikilinkClose()],
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(wraptext("foo", "bar"), wraptext("baz", "biz"))])),
])
def test_wikilink(builder, test, valid):
"""tests for building Wikilink nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.ExternalLinkOpen(brackets=False),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"),
brackets=False)])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"))])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkSeparator(), tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"), wrap([]))])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example.com/"),
tokens.ExternalLinkSeparator(), tokens.Text(text="Example"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example.com/"),
wraptext("Example"))])),

([tokens.ExternalLinkOpen(brackets=False),
tokens.Text(text="http://example"), tokens.Text(text=".com/foo"),
tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example", ".com/foo"),
brackets=False)])),

([tokens.ExternalLinkOpen(brackets=True),
tokens.Text(text="http://example"), tokens.Text(text=".com/foo"),
tokens.ExternalLinkSeparator(), tokens.Text(text="Example"),
tokens.Text(text=" Web Page"), tokens.ExternalLinkClose()],
wrap([ExternalLink(wraptext("http://example", ".com/foo"),
wraptext("Example", " Web Page"))])),
])
def test_external_link(builder, test, valid):
"""tests for building ExternalLink nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.HTMLEntityStart(), tokens.Text(text="nbsp"),
tokens.HTMLEntityEnd()],
wrap([HTMLEntity("nbsp", named=True, hexadecimal=False)])),

([tokens.HTMLEntityStart(), tokens.HTMLEntityNumeric(),
tokens.Text(text="107"), tokens.HTMLEntityEnd()],
wrap([HTMLEntity("107", named=False, hexadecimal=False)])),

([tokens.HTMLEntityStart(), tokens.HTMLEntityNumeric(),
tokens.HTMLEntityHex(char="X"), tokens.Text(text="6B"),
tokens.HTMLEntityEnd()],
wrap([HTMLEntity("6B", named=False, hexadecimal=True,
hex_char="X")])),
])
def test_html_entity(builder, test, valid):
"""tests for building HTMLEntity nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.HeadingStart(level=2), tokens.Text(text="foobar"),
tokens.HeadingEnd()],
wrap([Heading(wraptext("foobar"), 2)])),

([tokens.HeadingStart(level=4), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.HeadingEnd()],
wrap([Heading(wraptext("spam", "eggs"), 4)])),
])
def test_heading(builder, test, valid):
"""tests for building Heading nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
([tokens.CommentStart(), tokens.Text(text="foobar"),
tokens.CommentEnd()],
wrap([Comment("foobar")])),

([tokens.CommentStart(), tokens.Text(text="spam"),
tokens.Text(text="eggs"), tokens.CommentEnd()],
wrap([Comment("spameggs")])),
])
def test_comment(builder, test, valid):
"""tests for building Comment nodes"""
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("test,valid", [
# <ref></ref>
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagCloseOpen(padding=""), tokens.TagOpenClose(),
tokens.Text(text="ref"), tokens.TagCloseClose()],
wrap([Tag(wraptext("ref"), wrap([]),
closing_tag=wraptext("ref"))])),

# <ref name></ref>
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="name"), tokens.TagCloseOpen(padding=""),
tokens.TagOpenClose(), tokens.Text(text="ref"),
tokens.TagCloseClose()],
wrap([Tag(wraptext("ref"), wrap([]),
attrs=[Attribute(wraptext("name"))])])),

# <ref name="abc" />
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="name"), tokens.TagAttrEquals(),
tokens.TagAttrQuote(char='"'), tokens.Text(text="abc"),
tokens.TagCloseSelfclose(padding=" ")],
wrap([Tag(wraptext("ref"),
attrs=[Attribute(wraptext("name"), wraptext("abc"))],
self_closing=True, padding=" ")])),

# <br/>
([tokens.TagOpenOpen(), tokens.Text(text="br"),
tokens.TagCloseSelfclose(padding="")],
wrap([Tag(wraptext("br"), self_closing=True)])),

# <li>
([tokens.TagOpenOpen(), tokens.Text(text="li"),
tokens.TagCloseSelfclose(padding="", implicit=True)],
wrap([Tag(wraptext("li"), self_closing=True, implicit=True)])),

# </br>
([tokens.TagOpenOpen(invalid=True), tokens.Text(text="br"),
tokens.TagCloseSelfclose(padding="", implicit=True)],
wrap([Tag(wraptext("br"), self_closing=True, invalid=True,
implicit=True)])),

# </br/>
([tokens.TagOpenOpen(invalid=True), tokens.Text(text="br"),
tokens.TagCloseSelfclose(padding="")],
wrap([Tag(wraptext("br"), self_closing=True, invalid=True)])),

# <ref name={{abc}} foo="bar {{baz}}" abc={{de}}f ghi=j{{k}}{{l}}
# mno = '{{p}} [[q]] {{r}}'>[[Source]]</ref>
([tokens.TagOpenOpen(), tokens.Text(text="ref"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="name"), tokens.TagAttrEquals(),
tokens.TemplateOpen(), tokens.Text(text="abc"),
tokens.TemplateClose(),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="foo"), tokens.TagAttrEquals(),
tokens.TagAttrQuote(char='"'), tokens.Text(text="bar "),
tokens.TemplateOpen(), tokens.Text(text="baz"),
tokens.TemplateClose(),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="abc"), tokens.TagAttrEquals(),
tokens.TemplateOpen(), tokens.Text(text="de"),
tokens.TemplateClose(), tokens.Text(text="f"),
tokens.TagAttrStart(pad_first=" ", pad_before_eq="",
pad_after_eq=""),
tokens.Text(text="ghi"), tokens.TagAttrEquals(),
tokens.Text(text="j"), tokens.TemplateOpen(),
tokens.Text(text="k"), tokens.TemplateClose(),
tokens.TemplateOpen(), tokens.Text(text="l"),
tokens.TemplateClose(),
tokens.TagAttrStart(pad_first=" \n ", pad_before_eq=" ",
pad_after_eq=" "),
tokens.Text(text="mno"), tokens.TagAttrEquals(),
tokens.TagAttrQuote(char="'"), tokens.TemplateOpen(),
tokens.Text(text="p"), tokens.TemplateClose(),
tokens.Text(text=" "), tokens.WikilinkOpen(),
tokens.Text(text="q"), tokens.WikilinkClose(),
tokens.Text(text=" "), tokens.TemplateOpen(),
tokens.Text(text="r"), tokens.TemplateClose(),
tokens.TagCloseOpen(padding=""), tokens.WikilinkOpen(),
tokens.Text(text="Source"), tokens.WikilinkClose(),
tokens.TagOpenClose(), tokens.Text(text="ref"),
tokens.TagCloseClose()],
wrap([Tag(wraptext("ref"), wrap([Wikilink(wraptext("Source"))]), [
Attribute(wraptext("name"),
wrap([Template(wraptext("abc"))]), None),
Attribute(wraptext("foo"), wrap([Text("bar "),
Template(wraptext("baz"))]), pad_first=" "),
Attribute(wraptext("abc"), wrap([Template(wraptext("de")),
Text("f")]), None),
Attribute(wraptext("ghi"), wrap([Text("j"),
Template(wraptext("k")),
Template(wraptext("l"))]), None),
Attribute(wraptext("mno"), wrap([Template(wraptext("p")),
Text(" "), Wikilink(wraptext("q")), Text(" "),
Template(wraptext("r"))]), "'", " \n ", " ",
" ")])])),

# "''italic text''"
([tokens.TagOpenOpen(wiki_markup="''"), tokens.Text(text="i"),
tokens.TagCloseOpen(), tokens.Text(text="italic text"),
tokens.TagOpenClose(), tokens.Text(text="i"),
tokens.TagCloseClose()],
wrap([Tag(wraptext("i"), wraptext("italic text"),
wiki_markup="''")])),

# * bullet
([tokens.TagOpenOpen(wiki_markup="*"), tokens.Text(text="li"),
tokens.TagCloseSelfclose(), tokens.Text(text=" bullet")],
wrap([Tag(wraptext("li"), wiki_markup="*", self_closing=True),
Text(" bullet")])),
])
def test_tag(builder, test, valid):
"""tests for building Tag nodes"""
assert_wikicode_equal(valid, builder.build(test))

def test_integration(builder):
"""a test for building a combination of templates together"""
# {{{{{{{{foo}}bar|baz=biz}}buzz}}usr|{{bin}}}}
test = [tokens.TemplateOpen(), tokens.TemplateOpen(),
tokens.TemplateOpen(), tokens.TemplateOpen(),
tokens.Text(text="foo"), tokens.TemplateClose(),
tokens.Text(text="bar"), tokens.TemplateParamSeparator(),
tokens.Text(text="baz"), tokens.TemplateParamEquals(),
tokens.Text(text="biz"), tokens.TemplateClose(),
tokens.Text(text="buzz"), tokens.TemplateClose(),
tokens.Text(text="usr"), tokens.TemplateParamSeparator(),
tokens.TemplateOpen(), tokens.Text(text="bin"),
tokens.TemplateClose(), tokens.TemplateClose()]
valid = wrap(
[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)])])
assert_wikicode_equal(valid, builder.build(test))

def test_integration2(builder):
"""an even more audacious test for building a horrible wikicode mess"""
# {{a|b|{{c|[[d]]{{{e}}}}}}}[[f|{{{g}}}<!--h-->]]{{i|j=&nbsp;}}
test = [tokens.TemplateOpen(), tokens.Text(text="a"),
tokens.TemplateParamSeparator(), tokens.Text(text="b"),
tokens.TemplateParamSeparator(), tokens.TemplateOpen(),
tokens.Text(text="c"), tokens.TemplateParamSeparator(),
tokens.WikilinkOpen(), tokens.Text(text="d"),
tokens.WikilinkClose(), tokens.ArgumentOpen(),
tokens.Text(text="e"), tokens.ArgumentClose(),
tokens.TemplateClose(), tokens.TemplateClose(),
tokens.WikilinkOpen(), tokens.Text(text="f"),
tokens.WikilinkSeparator(), tokens.ArgumentOpen(),
tokens.Text(text="g"), tokens.ArgumentClose(),
tokens.CommentStart(), tokens.Text(text="h"),
tokens.CommentEnd(), tokens.WikilinkClose(),
tokens.TemplateOpen(), tokens.Text(text="i"),
tokens.TemplateParamSeparator(), tokens.Text(text="j"),
tokens.TemplateParamEquals(), tokens.HTMLEntityStart(),
tokens.Text(text="nbsp"), tokens.HTMLEntityEnd(),
tokens.TemplateClose()]
valid = wrap(
[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("h")])), Template(wraptext("i"), params=[
Parameter(wraptext("j"), wrap([HTMLEntity("nbsp",
named=True)]))])])
assert_wikicode_equal(valid, builder.build(test))

@pytest.mark.parametrize("tokens", [
[tokens.TemplateOpen(), tokens.TemplateParamSeparator()],
[tokens.TemplateOpen()], [tokens.ArgumentOpen()],
[tokens.WikilinkOpen()], [tokens.ExternalLinkOpen()],
[tokens.HeadingStart()], [tokens.CommentStart()],
[tokens.TagOpenOpen(), tokens.TagAttrStart()],
[tokens.TagOpenOpen()]
])
def test_parser_errors(builder, tokens):
"""test whether ParserError gets thrown for bad input"""
with pytest.raises(ParserError):
builder.build(tokens)

def test_parser_errors_templateclose(builder):
with pytest.raises(
ParserError,
match=r"_handle_token\(\) got unexpected TemplateClose"
):
builder.build([tokens.TemplateClose()])

+ 34
- 35
tests/test_comment.py View File

@@ -18,42 +18,41 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Test cases for the Comment node.
"""

import pytest

from mwparserfromhell.nodes import Comment

from ._test_tree_equality import TreeEqualityTestCase

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

def test_str(self):
"""test Comment.__str__()"""
node = Comment("foobar")
assert "<!--foobar-->" == str(node)

def test_children(self):
"""test Comment.__children__()"""
node = Comment("foobar")
gen = node.__children__()
with pytest.raises(StopIteration):
next(gen)

def test_strip(self):
"""test Comment.__strip__()"""
node = Comment("foobar")
assert node.__strip__() is None

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

def test_contents(self):
"""test getter/setter for the contents attribute"""
node = Comment("foobar")
assert "foobar" == node.contents
node.contents = "barfoo"
assert "barfoo" == node.contents
def test_str():
"""test Comment.__str__()"""
node = Comment("foobar")
assert "<!--foobar-->" == str(node)

def test_children():
"""test Comment.__children__()"""
node = Comment("foobar")
gen = node.__children__()
with pytest.raises(StopIteration):
next(gen)

def test_strip():
"""test Comment.__strip__()"""
node = Comment("foobar")
assert node.__strip__() is None

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

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

+ 88
- 87
tests/test_docs.py View File

@@ -18,103 +18,104 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Integration test cases for mwparserfromhell's documentation.
"""

import json
from io import StringIO
import os
import pytest
from urllib.parse import urlencode
from urllib.request import urlopen

import mwparserfromhell
import pytest

class TestDocs:
"""Integration test cases for mwparserfromhell's documentation."""
import mwparserfromhell

def assertPrint(self, value, output):
"""Assertion check that *value*, when printed, produces *output*."""
buff = StringIO()
print(value, end="", file=buff)
buff.seek(0)
assert output == buff.read()
def assert_print(value, output):
"""Assertion check that *value*, when printed, produces *output*."""
buff = StringIO()
print(value, end="", file=buff)
buff.seek(0)
assert output == buff.read()

def test_readme_1(self):
"""test a block of example code in the README"""
text = "I has a template! {{foo|bar|baz|eggs=spam}} See it?"
wikicode = mwparserfromhell.parse(text)
self.assertPrint(wikicode,
"I has a template! {{foo|bar|baz|eggs=spam}} See it?")
templates = wikicode.filter_templates()
self.assertPrint(templates, "['{{foo|bar|baz|eggs=spam}}']")
template = templates[0]
self.assertPrint(template.name, "foo")
self.assertPrint(template.params, "['bar', 'baz', 'eggs=spam']")
self.assertPrint(template.get(1).value, "bar")
self.assertPrint(template.get("eggs").value, "spam")
def test_readme_1():
"""test a block of example code in the README"""
text = "I has a template! {{foo|bar|baz|eggs=spam}} See it?"
wikicode = mwparserfromhell.parse(text)
assert_print(wikicode, "I has a template! {{foo|bar|baz|eggs=spam}} See it?")
templates = wikicode.filter_templates()
assert_print(templates, "['{{foo|bar|baz|eggs=spam}}']")
template = templates[0]
assert_print(template.name, "foo")
assert_print(template.params, "['bar', 'baz', 'eggs=spam']")
assert_print(template.get(1).value, "bar")
assert_print(template.get("eggs").value, "spam")

def test_readme_2(self):
"""test a block of example code in the README"""
text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
temps = mwparserfromhell.parse(text).filter_templates()
res = "['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']"
self.assertPrint(temps, res)
def test_readme_2():
"""test a block of example code in the README"""
text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
temps = mwparserfromhell.parse(text).filter_templates()
res = "['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']"
assert_print(temps, res)

def test_readme_3(self):
"""test a block of example code in the README"""
code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}")
self.assertPrint(code.filter_templates(recursive=False),
"['{{foo|this {{includes a|template}}}}']")
foo = code.filter_templates(recursive=False)[0]
self.assertPrint(foo.get(1).value, "this {{includes a|template}}")
self.assertPrint(foo.get(1).value.filter_templates()[0],
"{{includes a|template}}")
self.assertPrint(foo.get(1).value.filter_templates()[0].get(1).value,
"template")
def test_readme_3():
"""test a block of example code in the README"""
code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}")
assert_print(code.filter_templates(recursive=False),
"['{{foo|this {{includes a|template}}}}']")
foo = code.filter_templates(recursive=False)[0]
assert_print(foo.get(1).value, "this {{includes a|template}}")
assert_print(foo.get(1).value.filter_templates()[0],
"{{includes a|template}}")
assert_print(foo.get(1).value.filter_templates()[0].get(1).value,
"template")

def test_readme_4(self):
"""test a block of example code in the README"""
text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}"
code = mwparserfromhell.parse(text)
for template in code.filter_templates():
if template.name.matches("Cleanup") and not template.has("date"):
template.add("date", "July 2012")
res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{uncategorized}}"
self.assertPrint(code, res)
code.replace("{{uncategorized}}", "{{bar-stub}}")
res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}}"
self.assertPrint(code, res)
res = "['{{cleanup|date=July 2012}}', '{{bar-stub}}']"
self.assertPrint(code.filter_templates(), res)
text = str(code)
res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}}"
self.assertPrint(text, res)
assert text == code
def test_readme_4():
"""test a block of example code in the README"""
text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}"
code = mwparserfromhell.parse(text)
for template in code.filter_templates():
if template.name.matches("Cleanup") and not template.has("date"):
template.add("date", "July 2012")
res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{uncategorized}}"
assert_print(code, res)
code.replace("{{uncategorized}}", "{{bar-stub}}")
res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}}"
assert_print(code, res)
res = "['{{cleanup|date=July 2012}}', '{{bar-stub}}']"
assert_print(code.filter_templates(), res)
text = str(code)
res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}}"
assert_print(text, res)
assert text == code

@pytest.mark.skipif("NOWEB" in os.environ, reason="web test disabled by environ var")
def test_readme_5(self):
"""test a block of example code in the README; includes a web call"""
url1 = "https://en.wikipedia.org/w/api.php"
url2 = "https://en.wikipedia.org/w/index.php?title={0}&action=raw"
title = "Test"
data = {
"action": "query",
"prop": "revisions",
"rvprop": "content",
"rvslots": "main",
"rvlimit": 1,
"titles": title,
"format": "json",
"formatversion": "2",
}
try:
raw = urlopen(url1, urlencode(data).encode("utf8")).read()
except OSError:
pytest.skip("cannot continue because of unsuccessful web call")
res = json.loads(raw.decode("utf8"))
revision = res["query"]["pages"][0]["revisions"][0]
text = revision["slots"]["main"]["content"]
try:
expected = urlopen(url2.format(title)).read().decode("utf8")
except OSError:
pytest.skip("cannot continue because of unsuccessful web call")
actual = mwparserfromhell.parse(text)
assert expected == actual
@pytest.mark.skipif("NOWEB" in os.environ, reason="web test disabled by environ var")
def test_readme_5():
"""test a block of example code in the README; includes a web call"""
url1 = "https://en.wikipedia.org/w/api.php"
url2 = "https://en.wikipedia.org/w/index.php?title={0}&action=raw"
title = "Test"
data = {
"action": "query",
"prop": "revisions",
"rvprop": "content",
"rvslots": "main",
"rvlimit": 1,
"titles": title,
"format": "json",
"formatversion": "2",
}
try:
raw = urlopen(url1, urlencode(data).encode("utf8")).read()
except OSError:
pytest.skip("cannot continue because of unsuccessful web call")
res = json.loads(raw.decode("utf8"))
revision = res["query"]["pages"][0]["revisions"][0]
text = revision["slots"]["main"]["content"]
try:
expected = urlopen(url2.format(title)).read().decode("utf8")
except OSError:
pytest.skip("cannot continue because of unsuccessful web call")
actual = mwparserfromhell.parse(text)
assert expected == actual

+ 88
- 88
tests/test_external_link.py View File

@@ -18,102 +18,102 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Test cases for the ExternalLink node.
"""

import pytest

from mwparserfromhell.nodes import ExternalLink, Text
from .conftest import assert_wikicode_equal, wrap, wraptext

from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

class TestExternalLink(TreeEqualityTestCase):
"""Test cases for the ExternalLink node."""

def test_str(self):
"""test ExternalLink.__str__()"""
node = ExternalLink(wraptext("http://example.com/"), brackets=False)
assert "http://example.com/" == str(node)
node2 = ExternalLink(wraptext("http://example.com/"))
assert "[http://example.com/]" == str(node2)
node3 = ExternalLink(wraptext("http://example.com/"), wrap([]))
assert "[http://example.com/ ]" == str(node3)
node4 = ExternalLink(wraptext("http://example.com/"),
wraptext("Example Web Page"))
assert "[http://example.com/ Example Web Page]" == str(node4)
def test_str():
"""test ExternalLink.__str__()"""
node = ExternalLink(wraptext("http://example.com/"), brackets=False)
assert "http://example.com/" == str(node)
node2 = ExternalLink(wraptext("http://example.com/"))
assert "[http://example.com/]" == str(node2)
node3 = ExternalLink(wraptext("http://example.com/"), wrap([]))
assert "[http://example.com/ ]" == str(node3)
node4 = ExternalLink(wraptext("http://example.com/"),
wraptext("Example Web Page"))
assert "[http://example.com/ Example Web Page]" == str(node4)

def test_children(self):
"""test ExternalLink.__children__()"""
node1 = ExternalLink(wraptext("http://example.com/"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com/"),
wrap([Text("Example"), Text("Page")]))
gen1 = node1.__children__()
gen2 = node2.__children__()
assert node1.url == next(gen1)
assert node2.url == next(gen2)
assert node2.title == next(gen2)
with pytest.raises(StopIteration):
next(gen1)
with pytest.raises(StopIteration):
next(gen2)
def test_children():
"""test ExternalLink.__children__()"""
node1 = ExternalLink(wraptext("http://example.com/"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com/"),
wrap([Text("Example"), Text("Page")]))
gen1 = node1.__children__()
gen2 = node2.__children__()
assert node1.url == next(gen1)
assert node2.url == next(gen2)
assert node2.title == next(gen2)
with pytest.raises(StopIteration):
next(gen1)
with pytest.raises(StopIteration):
next(gen2)

def test_strip(self):
"""test ExternalLink.__strip__()"""
node1 = ExternalLink(wraptext("http://example.com"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com"))
node3 = ExternalLink(wraptext("http://example.com"), wrap([]))
node4 = ExternalLink(wraptext("http://example.com"), wraptext("Link"))
def test_strip():
"""test ExternalLink.__strip__()"""
node1 = ExternalLink(wraptext("http://example.com"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com"))
node3 = ExternalLink(wraptext("http://example.com"), wrap([]))
node4 = ExternalLink(wraptext("http://example.com"), wraptext("Link"))

assert "http://example.com" == node1.__strip__()
assert node2.__strip__() is None
assert node3.__strip__() is None
assert "Link" == node4.__strip__()
assert "http://example.com" == node1.__strip__()
assert node2.__strip__() is None
assert node3.__strip__() is None
assert "Link" == node4.__strip__()

def test_showtree(self):
"""test ExternalLink.__showtree__()"""
output = []
getter, marker = object(), object()
get = lambda code: output.append((getter, code))
mark = lambda: output.append(marker)
node1 = ExternalLink(wraptext("http://example.com"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com"), wraptext("Link"))
node1.__showtree__(output.append, get, mark)
node2.__showtree__(output.append, get, mark)
valid = [
(getter, node1.url), "[", (getter, node2.url),
(getter, node2.title), "]"]
assert valid == output
def test_showtree():
"""test ExternalLink.__showtree__()"""
output = []
getter, marker = object(), object()
get = lambda code: output.append((getter, code))
mark = lambda: output.append(marker)
node1 = ExternalLink(wraptext("http://example.com"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com"), wraptext("Link"))
node1.__showtree__(output.append, get, mark)
node2.__showtree__(output.append, get, mark)
valid = [
(getter, node1.url), "[", (getter, node2.url),
(getter, node2.title), "]"]
assert valid == output

def test_url(self):
"""test getter/setter for the url attribute"""
url = wraptext("http://example.com/")
node1 = ExternalLink(url, brackets=False)
node2 = ExternalLink(url, wraptext("Example"))
assert url is node1.url
assert url is node2.url
node1.url = "mailto:héhehé@spam.com"
node2.url = "mailto:héhehé@spam.com"
self.assertWikicodeEqual(wraptext("mailto:héhehé@spam.com"), node1.url)
self.assertWikicodeEqual(wraptext("mailto:héhehé@spam.com"), node2.url)
def test_url():
"""test getter/setter for the url attribute"""
url = wraptext("http://example.com/")
node1 = ExternalLink(url, brackets=False)
node2 = ExternalLink(url, wraptext("Example"))
assert url is node1.url
assert url is node2.url
node1.url = "mailto:héhehé@spam.com"
node2.url = "mailto:héhehé@spam.com"
assert_wikicode_equal(wraptext("mailto:héhehé@spam.com"), node1.url)
assert_wikicode_equal(wraptext("mailto:héhehé@spam.com"), node2.url)

def test_title(self):
"""test getter/setter for the title attribute"""
title = wraptext("Example!")
node1 = ExternalLink(wraptext("http://example.com/"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com/"), title)
assert None is node1.title
assert title is node2.title
node2.title = None
assert None is node2.title
node2.title = "My Website"
self.assertWikicodeEqual(wraptext("My Website"), node2.title)
def test_title():
"""test getter/setter for the title attribute"""
title = wraptext("Example!")
node1 = ExternalLink(wraptext("http://example.com/"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com/"), title)
assert None is node1.title
assert title is node2.title
node2.title = None
assert None is node2.title
node2.title = "My Website"
assert_wikicode_equal(wraptext("My Website"), node2.title)

def test_brackets(self):
"""test getter/setter for the brackets attribute"""
node1 = ExternalLink(wraptext("http://example.com/"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com/"), wraptext("Link"))
assert node1.brackets is False
assert node2.brackets is True
node1.brackets = True
node2.brackets = False
assert node1.brackets is True
assert node2.brackets is False
assert "[http://example.com/]" == str(node1)
assert "http://example.com/" == str(node2)
def test_brackets():
"""test getter/setter for the brackets attribute"""
node1 = ExternalLink(wraptext("http://example.com/"), brackets=False)
node2 = ExternalLink(wraptext("http://example.com/"), wraptext("Link"))
assert node1.brackets is False
assert node2.brackets is True
node1.brackets = True
node2.brackets = False
assert node1.brackets is True
assert node2.brackets is False
assert "[http://example.com/]" == str(node1)
assert "http://example.com/" == str(node2)

+ 55
- 55
tests/test_heading.py View File

@@ -18,67 +18,67 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
Test cases for the Heading node.
"""

import pytest

from mwparserfromhell.nodes import Heading, Text
from .conftest import assert_wikicode_equal, wrap, wraptext

from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext

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

def test_str(self):
"""test Heading.__str__()"""
node = Heading(wraptext("foobar"), 2)
assert "==foobar==" == str(node)
node2 = Heading(wraptext(" zzz "), 5)
assert "===== zzz =====" == str(node2)
def test_str():
"""test Heading.__str__()"""
node = Heading(wraptext("foobar"), 2)
assert "==foobar==" == str(node)
node2 = Heading(wraptext(" zzz "), 5)
assert "===== zzz =====" == str(node2)

def test_children(self):
"""test Heading.__children__()"""
node = Heading(wrap([Text("foo"), Text("bar")]), 3)
gen = node.__children__()
assert node.title == next(gen)
with pytest.raises(StopIteration):
next(gen)
def test_children():
"""test Heading.__children__()"""
node = Heading(wrap([Text("foo"), Text("bar")]), 3)
gen = node.__children__()
assert node.title == next(gen)
with pytest.raises(StopIteration):
next(gen)

def test_strip(self):
"""test Heading.__strip__()"""
node = Heading(wraptext("foobar"), 3)
assert "foobar" == node.__strip__()
def test_strip():
"""test Heading.__strip__()"""
node = Heading(wraptext("foobar"), 3)
assert "foobar" == node.__strip__()

def test_showtree(