diff --git a/CHANGELOG b/CHANGELOG index 32a14e4..f7858d8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,7 @@ v0.3 (unreleased): - 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. +- Added a matches() method to Wikicode for page/template name comparisons. - Various fixes and cleanup. v0.2 (released June 20, 2013): diff --git a/README.rst b/README.rst index d481700..f1092ee 100644 --- a/README.rst +++ b/README.rst @@ -82,13 +82,15 @@ templates manually. This is possible because nodes can contain additional template 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:: +objects can be treated like lists, with ``append()``, ``insert()``, +``remove()``, ``replace()``, and more. They also have a ``matches()`` method +for comparing page or template names, which takes care of capitalization and +whitespace:: >>> text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}" >>> code = mwparserfromhell.parse(text) >>> for template in code.filter_templates(): - ... if template.name == "cleanup" and not template.has_param("date"): + ... if template.name.matches("Cleanup") and not template.has_param("date"): ... template.add("date", "July 2012") ... >>> print code diff --git a/docs/changelog.rst b/docs/changelog.rst index 18687f0..8cfa2ec 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -14,6 +14,8 @@ Unreleased - :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.** +- Added a :py:meth:`.matches` method to :py:class:`~.Wikicode` for + page/template name comparisons. - Various fixes and cleanup. v0.2 diff --git a/docs/usage.rst b/docs/usage.rst index fd24a15..15b384b 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -49,14 +49,16 @@ additional :py:class:`~.Wikicode` objects:: template Templates can be easily modified to add, remove, or alter params. -:py:class:`~.Wikicode` can also be treated like a list with +:py:class:`~.Wikicode` objects can be treated like lists, with :py:meth:`~.Wikicode.append`, :py:meth:`~.Wikicode.insert`, -:py:meth:`~.Wikicode.remove`, :py:meth:`~.Wikicode.replace`, and more:: +:py:meth:`~.Wikicode.remove`, :py:meth:`~.Wikicode.replace`, and more. They +also have a :py:meth:`~.Wikicode.matches` method for comparing page or template +names, which takes care of capitalization and whitespace:: >>> text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}" >>> code = mwparserfromhell.parse(text) >>> for template in code.filter_templates(): - ... if template.name == "cleanup" and not template.has_param("date"): + ... if template.name.matches("Cleanup") and not template.has_param("date"): ... template.add("date", "July 2012") ... >>> print code diff --git a/mwparserfromhell/wikicode.py b/mwparserfromhell/wikicode.py index 90b5d18..a1921d7 100644 --- a/mwparserfromhell/wikicode.py +++ b/mwparserfromhell/wikicode.py @@ -309,6 +309,21 @@ class Wikicode(StringMixIn): callback = lambda self, i: self.nodes.pop(i) self._do_search(obj, recursive, callback, self) + def matches(self, other): + """Do a loose equivalency test suitable for comparing page names. + + *other* can be any string-like object, including + :py:class:`~.Wikicode`. This operation is symmetric; both sides are + adjusted. Specifically, whitespace and markup is stripped and the first + letter's case is normalized. Typical usage is + ``if template.name.matches("stub"): ...``. + """ + this = self.strip_code().strip() + that = parse_anything(other).strip_code().strip() + if not this or not that: + return this == that + return this[0].upper() + this[1:] == that[0].upper() + that[1:] + def ifilter(self, recursive=True, matches=None, flags=FLAGS, forcetype=None): """Iterate over nodes in our list matching certain conditions. diff --git a/tests/test_docs.py b/tests/test_docs.py index 5fdb520..53b3b76 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -90,7 +90,7 @@ class TestDocs(unittest.TestCase): text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}" code = mwparserfromhell.parse(text) for template in code.filter_templates(): - if template.name == "cleanup" and not template.has_param("date"): + if template.name.matches("Cleanup") and not template.has_param("date"): template.add("date", "July 2012") res = "{{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{uncategorized}}" self.assertPrint(code, res) diff --git a/tests/test_wikicode.py b/tests/test_wikicode.py index 2684414..5a28fb5 100644 --- a/tests/test_wikicode.py +++ b/tests/test_wikicode.py @@ -210,6 +210,19 @@ class TestWikicode(TreeEqualityTestCase): self.assertEqual("{{a||{{c|d={{h}}}}}}", code2) self.assertRaises(ValueError, code2.remove, "{{h}}", recursive=False) + def test_matches(self): + """test Wikicode.matches()""" + code1 = parse("Cleanup") + code2 = parse("\nstub") + self.assertTrue(code1.matches("Cleanup")) + self.assertTrue(code1.matches("cleanup")) + self.assertTrue(code1.matches(" cleanup\n")) + self.assertFalse(code1.matches("CLEANup")) + self.assertFalse(code1.matches("Blah")) + self.assertTrue(code2.matches("stub")) + self.assertTrue(code2.matches("Stub")) + self.assertFalse(code2.matches("StuB")) + def test_filter_family(self): """test the Wikicode.i?filter() family of functions""" def genlist(gen):