Browse Source

Wikicode's filter() methods now passed recursive=True instead of False.

This is a breaking change for those who rely on default behavior.
tags/v0.3
Ben Kurtovic 10 years ago
parent
commit
02e52185f4
7 changed files with 54 additions and 48 deletions
  1. +4
    -1
      CHANGELOG
  2. +11
    -11
      README.rst
  3. +4
    -1
      docs/changelog.rst
  4. +11
    -11
      docs/usage.rst
  5. +2
    -2
      mwparserfromhell/wikicode.py
  6. +13
    -13
      tests/test_docs.py
  7. +9
    -9
      tests/test_wikicode.py

+ 4
- 1
CHANGELOG View File

@@ -2,7 +2,10 @@ v0.3 (unreleased):

- Added complete support for HTML Tags, along with appropriate unit tests. This
includes forms like <ref>foo</ref>, <ref name="bar"/>, and wiki-markup tags
like bold ('''), italics (''), and lists (''*'', ''#'', '';'' and '':'').
like bold ('''), italics (''), and lists (*, #, ; and :).
- Wikicode's filter methods are now passed 'recursive=True' by default instead
of False. This is a breaking change if you rely on any filter() methods being
non-recursive by default.
- Various fixes and cleanup.

v0.2 (released June 20, 2013):


+ 11
- 11
README.rst View File

@@ -60,13 +60,20 @@ For example::
>>> print template.get("eggs").value
spam

Since every node you reach is also a ``Wikicode`` object, it's trivial to get
nested templates::
Since nodes can contain other nodes, getting nested templates is trivial::

>>> text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
>>> mwparserfromhell.parse(text).filter_templates()
['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']

You can also pass ``recursive=False`` to ``filter_templates()`` and explore
templates manually. This is possible because nodes can contain additional
``Wikicode`` objects::

>>> code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}")
>>> print code.filter_templates()
>>> print code.filter_templates(recursive=False)
['{{foo|this {{includes a|template}}}}']
>>> foo = code.filter_templates()[0]
>>> foo = code.filter_templates(recursive=False)[0]
>>> print foo.get(1).value
this {{includes a|template}}
>>> print foo.get(1).value.filter_templates()[0]
@@ -74,13 +81,6 @@ nested templates::
>>> print foo.get(1).value.filter_templates()[0].get(1).value
template

Additionally, you can include nested templates in ``filter_templates()`` by
passing ``recursive=True``::

>>> text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
>>> mwparserfromhell.parse(text).filter_templates(recursive=True)
['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']

Templates can be easily modified to add, remove, or alter params. ``Wikicode``
can also be treated like a list with ``append()``, ``insert()``, ``remove()``,
``replace()``, and more::


+ 4
- 1
docs/changelog.rst View File

@@ -10,7 +10,10 @@ Unreleased
- Added complete support for HTML :py:class:`Tags <.Tag>`, along with
appropriate unit tests. This includes forms like ``<ref>foo</ref>``,
``<ref name="bar"/>``, and wiki-markup tags like bold (``'''``), italics
(``''``), and lists (``''*''``, ``''#''``, ``'';''`` and ``'':''``).
(``''``), and lists (``*``, ``#``, ``;`` and ``:``).
- :py:class:`Wikicode's <.Wikicode>` :py:meth:`.filter` methods are now passed
*recursive=True* by default instead of *False*. **This is a breaking change
if you rely on any filter() methods being non-recursive by default.**
- Various fixes and cleanup.

v0.2


+ 11
- 11
docs/usage.rst View File

@@ -27,13 +27,20 @@ some extra methods. For example::
>>> print template.get("eggs").value
spam

Since every node you reach is also a :py:class:`~.Wikicode` object, it's
trivial to get nested templates::
Since nodes can contain other nodes, getting nested templates is trivial::

>>> text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
>>> mwparserfromhell.parse(text).filter_templates()
['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']

You can also pass *recursive=False* to :py:meth:`~.filter_templates` and
explore templates manually. This is possible because nodes can contain
additional :py:class:`~.Wikicode` objects::

>>> code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}")
>>> print code.filter_templates()
>>> print code.filter_templates(recursive=False)
['{{foo|this {{includes a|template}}}}']
>>> foo = code.filter_templates()[0]
>>> foo = code.filter_templates(recursive=False)[0]
>>> print foo.get(1).value
this {{includes a|template}}
>>> print foo.get(1).value.filter_templates()[0]
@@ -41,13 +48,6 @@ trivial to get nested templates::
>>> print foo.get(1).value.filter_templates()[0].get(1).value
template

Additionally, you can include nested templates in :py:meth:`~.filter_templates`
by passing *recursive=True*::

>>> text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
>>> mwparserfromhell.parse(text).filter_templates(recursive=True)
['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']

Templates can be easily modified to add, remove, or alter params.
:py:class:`~.Wikicode` can also be treated like a list with
:py:meth:`~.Wikicode.append`, :py:meth:`~.Wikicode.insert`,


+ 2
- 2
mwparserfromhell/wikicode.py View File

@@ -309,7 +309,7 @@ class Wikicode(StringMixIn):
callback = lambda self, i: self.nodes.pop(i)
self._do_search(obj, recursive, callback, self)

def ifilter(self, recursive=False, matches=None, flags=FLAGS,
def ifilter(self, recursive=True, matches=None, flags=FLAGS,
forcetype=None):
"""Iterate over nodes in our list matching certain conditions.

@@ -327,7 +327,7 @@ class Wikicode(StringMixIn):
if not matches or re.search(matches, str(node), flags):
yield node

def filter(self, recursive=False, matches=None, flags=FLAGS,
def filter(self, recursive=True, matches=None, flags=FLAGS,
forcetype=None):
"""Return a list of nodes within our list matching certain conditions.



+ 13
- 13
tests/test_docs.py View File

@@ -61,30 +61,30 @@ class TestDocs(unittest.TestCase):

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()
if py3k:
res = "['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']"
else:
res = "[u'{{foo|{{bar}}={{baz|{{spam}}}}}}', u'{{bar}}', u'{{baz|{{spam}}}}', u'{{spam}}']"
self.assertPrint(temps, res)

def test_readme_3(self):
"""test a block of example code in the README"""
code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}")
if py3k:
self.assertPrint(code.filter_templates(),
self.assertPrint(code.filter_templates(recursive=False),
"['{{foo|this {{includes a|template}}}}']")
else:
self.assertPrint(code.filter_templates(),
self.assertPrint(code.filter_templates(recursive=False),
"[u'{{foo|this {{includes a|template}}}}']")
foo = code.filter_templates()[0]
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(self):
"""test a block of example code in the README"""
text = "{{foo|{{bar}}={{baz|{{spam}}}}}}"
temps = mwparserfromhell.parse(text).filter_templates(recursive=True)
if py3k:
res = "['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}']"
else:
res = "[u'{{foo|{{bar}}={{baz|{{spam}}}}}}', u'{{bar}}', u'{{baz|{{spam}}}}', u'{{spam}}']"
self.assertPrint(temps, res)

def test_readme_4(self):
"""test a block of example code in the README"""
text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}"


+ 9
- 9
tests/test_wikicode.py View File

@@ -219,11 +219,11 @@ class TestWikicode(TreeEqualityTestCase):

code = parse("a{{b}}c[[d]]{{{e}}}{{f}}[[g]]")
for func in (code.filter, ifilter(code)):
self.assertEqual(["a", "{{b}}", "c", "[[d]]", "{{{e}}}", "{{f}}",
"[[g]]"], func())
self.assertEqual(["a", "{{b}}", "b", "c", "[[d]]", "d", "{{{e}}}",
"e", "{{f}}", "f", "[[g]]", "g"], func())
self.assertEqual(["{{{e}}}"], func(forcetype=Argument))
self.assertIs(code.get(4), func(forcetype=Argument)[0])
self.assertEqual(["a", "c"], func(forcetype=Text))
self.assertEqual(list("abcdefg"), func(forcetype=Text))
self.assertEqual([], func(forcetype=Heading))
self.assertRaises(TypeError, func, forcetype=True)

@@ -239,7 +239,7 @@ class TestWikicode(TreeEqualityTestCase):
self.assertEqual([], get_filter("html_entities"))
self.assertEqual([], get_filter("tags"))
self.assertEqual(["{{b}}", "{{f}}"], get_filter("templates"))
self.assertEqual(["a", "c"], get_filter("text"))
self.assertEqual(list("abcdefg"), get_filter("text"))
self.assertEqual(["[[d]]", "[[g]]"], get_filter("wikilinks"))

code2 = parse("{{a|{{b}}|{{c|d={{f}}{{h}}}}}}")
@@ -252,13 +252,13 @@ class TestWikicode(TreeEqualityTestCase):

code3 = parse("{{foobar}}{{FOO}}{{baz}}{{bz}}")
for func in (code3.filter, ifilter(code3)):
self.assertEqual(["{{foobar}}", "{{FOO}}"], func(matches=r"foo"))
self.assertEqual(["{{foobar}}", "{{FOO}}"], func(recursive=False, matches=r"foo"))
self.assertEqual(["{{foobar}}", "{{FOO}}"],
func(matches=r"^{{foo.*?}}"))
func(recursive=False, matches=r"^{{foo.*?}}"))
self.assertEqual(["{{foobar}}"],
func(matches=r"^{{foo.*?}}", flags=re.UNICODE))
self.assertEqual(["{{baz}}", "{{bz}}"], func(matches=r"^{{b.*?z"))
self.assertEqual(["{{baz}}"], func(matches=r"^{{b.+?z}}"))
func(recursive=False, matches=r"^{{foo.*?}}", flags=re.UNICODE))
self.assertEqual(["{{baz}}", "{{bz}}"], func(recursive=False, matches=r"^{{b.*?z"))
self.assertEqual(["{{baz}}"], func(recursive=False, matches=r"^{{b.+?z}}"))

self.assertEqual(["{{a|{{b}}|{{c|d={{f}}{{h}}}}}}"],
code2.filter_templates(recursive=False))


Loading…
Cancel
Save