This is a breaking change for those who rely on default behavior.tags/v0.3
| @@ -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): | |||
| @@ -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:: | |||
| @@ -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 | |||
| @@ -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`, | |||
| @@ -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. | |||
| @@ -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}}" | |||
| @@ -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)) | |||