diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4984243 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.pyc +*.egg +*.egg-info +.DS_Store +build +docs/_build diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f89e1a9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2012 by Ben Kurtovic + +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. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..c90c76c --- /dev/null +++ b/README.rst @@ -0,0 +1,105 @@ +mwtemplateparserfromhell +======================== + +**mwtemplateparserfromhell** (the *MediaWiki Template Parser from Hell*) is a +Python package that provides an easy-to-use and outrageously powerful template +parser for MediaWiki_ wikicode. + +Coded by Earwig_ and named by `Σ`_. + +Installation +------------ + +The easiest way to install the parser is through the `Python Package Index`_, +so you can install the latest release with ``pip install +mwtemplateparserfromhell`` (`get pip`_). Alternatively, get the latest +development version:: + + git clone git://github.com/earwig/mwtemplateparserfromhell.git mwtemplateparserfromhell + cd mwtemplateparserfromhell + python setup.py install + +You can run the comprehensive unit testing suite with ``python setup.py test``. + +Usage +----- + +Normal usage is rather straightforward (where ``text`` is page text):: + + >>> import mwtemplateparserfromhell + >>> parser = mwtemplateparserfromhell.Parser() + >>> templates = parser.parse(text) + +``templates`` is a list of ``mwtemplateparserfromhell.Template`` objects, which +contain a ``name`` attribute, a ``params`` attribute, and a ``get()`` method. +For example:: + + >>> templates = parser.parse("{{foo|bar|baz|eggs=spam}}") + >>> print templates + [Template(name="foo", params={"1": "bar", "2": "baz", "eggs": "spam"})] + >>> print templates[0].name + foo + >>> print templates[0].params + ['bar', 'baz'] + >>> print templates[0].get(0) + bar + >>> print templates[0].get("eggs") + spam + +If ``get``\ 's argument is a number *n*, it'll return the *n*\ th parameter, +otherwise it will return the parameter with the given name. Unnamed parameters +are given numerical names starting with 1, so ``{{foo|bar}}`` is the same as +``{{foo|1=bar}}``, and ``templates[0].get(0) is templates[0].get("1")``. + +By default, nested templates are supported like so:: + + >>> templates = parser.parse("{{foo|this {{includes a|template}}}}") + >>> print templates + [Template(name="foo", params={"1": "this {{includes a|template}}"})] + >>> print templates[0].get(0) + this {{includes a|template}} + >>> print templates[0].get(0).templates + [Template(name="includes a", params={"1": "template"})] + >>> print templates[0].get(0).templates[0].params[0] + template + +Integration +----------- + +``mwtemplateparserfromhell`` is used by and originally developed for +EarwigBot_; ``Page`` objects have a ``parse_templates`` method that essentially +calls ``Parser().parse()`` on ``page.get()``. + +If you're using PyWikipedia_, your code might look like this:: + + import mwtemplateparserfromhell + import wikipedia as pywikibot + def parse_templates(title): + site = pywikibot.get_site() + page = pywikibot.Page(site, title) + text = page.get() + parser = mwtemplateparserfromhell.Parser() + return parser.parse(text) + +If you're not using a library, you can parse templates in any page using the +following code (via the API_):: + + import json + import urllib + import mwtemplateparserfromhell + API_URL = "http://en.wikipedia.org/w/api.php" + def parse_templates(title): + raw = urllib.urlopen(API_URL, data).read() + res = json.loads(raw) + text = res["query"]["pages"].values()[0]["revisions"][0]["*"] + parser = mwtemplateparserfromhell.Parser() + return parser.parse(text) + +.. _MediaWiki: http://mediawiki.org +.. _Earwig: http://en.wikipedia.org/wiki/User:The_Earwig +.. _Σ: http://en.wikipedia.org/wiki/User:Σ +.. _Python Package Index: http://pypi.python.org +.. _get pip: http://pypi.python.org/pypi/pip +.. _EarwigBot: https://github.com/earwig/earwigbot +.. _PyWikipedia: http://pywikipediabot.sourceforge.net/ +.. _API: http://mediawiki.org/wiki/API diff --git a/mwtemplateparserfromhell/__init__.py b/mwtemplateparserfromhell/__init__.py new file mode 100644 index 0000000..49370ed --- /dev/null +++ b/mwtemplateparserfromhell/__init__.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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. + +""" +`mwtemplateparserfromhell +`_ (the MediaWiki Template +Parser from Hell) is a Python package that provides an easy-to-use and +outrageously powerful template parser for `MediaWiki `_ +wikicode. +""" + +__author__ = "Ben Kurtovic" +__copyright__ = "Copyright (C) 2012 by Ben Kurtovic" +__license__ = "MIT License" +__version__ = "0.1.dev" +__email__ = "ben.kurtovic@verizon.net" + +from mwtemplateparserfromhell import parameter, parser, template +from mwtemplateparserfromhell.parser import Parser diff --git a/mwtemplateparserfromhell/parameter.py b/mwtemplateparserfromhell/parameter.py new file mode 100644 index 0000000..1d62e13 --- /dev/null +++ b/mwtemplateparserfromhell/parameter.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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. + +__all__ = ["Parameter"] + +class Parameter(object): + def __init__(self, name, value, templates=None): + self._name = name + self._value = value + if templates: + self._templates = templates + else: + self._templates = [] + + def __repr__(self): + return repr(self.value) + + def __str__(self): + return self.value + + def __lt__(self, other): + if isinstance(other, Parameter): + return self.value < other.value + return self.value < other + + def __le__(self, other): + if isinstance(other, Parameter): + return self.value <= other.value + return self.value <= other + + def __eq__(self, other): + if isinstance(other, Parameter): + return (self.value == other.value and + self.templates == other.templates) + return self.value == other + + def __ne__(self, other): + if isinstance(other, Parameter): + return (self.value != other.value or + self.templates != other.templates) + return self.value != other + + def __gt__(self, other): + if isinstance(other, Parameter): + return self.value > other.value + return self.value > other + + def __ge__(self, other): + if isinstance(other, Parameter): + return self.value >= other.value + return self.value >= other + + def __nonzero__(self): + return bool(self.value) + + def __len__(self): + return len(self.value) + + def __iter__(self): + for char in self.value: + yield char + + def __contains__(self, item): + return item in self.value or item in self.templates + + @property + def name(self): + return self._name + + @property + def value(self): + return self._value + + @property + def templates(self): + return self._templates diff --git a/mwtemplateparserfromhell/parser.py b/mwtemplateparserfromhell/parser.py new file mode 100644 index 0000000..522a138 --- /dev/null +++ b/mwtemplateparserfromhell/parser.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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 mwtemplateparserfromhell.parameter import Parameter +from mwtemplateparserfromhell.template import Template + +__all__ = ["Parser"] + +class Parser(object): + def _tokenize(self, text): + return text + + def parse(self, text): + tokens = self._tokenize(text) + params = [Parameter("1", "bar"), Parameter("2", "baz")] + templates = [Template(name="foo", params=params)] + return templates diff --git a/mwtemplateparserfromhell/template.py b/mwtemplateparserfromhell/template.py new file mode 100644 index 0000000..1f9c77c --- /dev/null +++ b/mwtemplateparserfromhell/template.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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 collections import OrderedDict + +__all__ = ["Template"] + +class Template(object): + def __init__(self, name, params=None): + self._name = name + self._params = OrderedDict() + if params: + for param in params: + self._params[param.name] = param + + def __repr__(self): + paramlist = [] + for name, param in self._params.iteritems(): + paramlist.append('"{0}": "{1}"'.format(name, str(param))) + params = "{" + ", ".join(paramlist) + "}" + return "Template(name={0}, params={1})".format(self.name, params) + + def __eq__(self, other): + if isinstance(other, Template): + return self.name == other.name and self._params == other._params + return False + + def __ne__(self, other): + if isinstance(other, Template): + return self.name != other.name or self._params != other._params + return True + + @property + def name(self): + return self._name + + @property + def params(self): + return self._params.values() + + def get(self, name): + try: + return self._params[name] + except KeyError: # Try lookup by order in param list + return self._params.values()[name] diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..84d2dc9 --- /dev/null +++ b/setup.py @@ -0,0 +1,53 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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 setuptools import setup, find_packages + +from mwtemplateparserfromhell import __version__ + +with open("README.rst") as fp: + long_docs = fp.read() + +setup( + name = "mwtemplateparserfromhell", + packages = find_packages(exclude=("tests",)), + test_suite = "tests", + version = __version__, + author = "Ben Kurtovic", + author_email = "ben.kurtovic@verizon.net", + url = "https://github.com/earwig/mwtemplateparserfromhell", + description = "MWTemplateParserFromHell is a parser for MediaWiki templates.", + long_description = long_docs, + download_url = "https://github.com/earwig/mwtemplateparserfromhell/tarball/v{0}".format(__version__), + keywords = "earwig mwtemplateparserfromhell wikipedia wiki mediawiki template parsing", + license = "MIT License", + classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Text Processing :: Markup" + ], +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_parameter.py b/tests/test_parameter.py new file mode 100644 index 0000000..80b94e1 --- /dev/null +++ b/tests/test_parameter.py @@ -0,0 +1,99 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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. + +import unittest + +from mwtemplateparserfromhell.parameter import Parameter +from mwtemplateparserfromhell.template import Template + +class TestParameter(unittest.TestCase): + def setUp(self): + self.name = "foo" + self.value1 = "bar" + self.value2 = "{{spam}}" + self.value3 = "bar{{spam}}" + self.value4 = "embedded {{eggs|spam|baz=buz}} {{goes}} here" + self.templates2 = [Template("spam")] + self.templates3 = [Template("spam")] + self.templates4 = [Template("eggs", [Parameter("1", "spam"), + Parameter("baz", "buz")]), + Template("goes")] + + def test_construct(self): + Parameter(self.name, self.value1) + Parameter(self.name, self.value2, self.templates2) + Parameter(name=self.name, value=self.value3) + Parameter(name=self.name, value=self.value4, templates=self.templates4) + + def test_name(self): + params = [ + Parameter(self.name, self.value1), + Parameter(self.name, self.value2, self.templates2), + Parameter(name=self.name, value=self.value3), + Parameter(name=self.name, value=self.value4, + templates=self.templates4) + ] + for param in params: + self.assertEqual(param.name, self.name) + + def test_value(self): + tests = [ + (Parameter(self.name, self.value1), self.value1), + (Parameter(self.name, self.value2, self.templates2), self.value2), + (Parameter(name=self.name, value=self.value3), self.value3), + (Parameter(name=self.name, value=self.value4, + templates=self.templates4), self.value4) + ] + for param, correct in tests: + self.assertEqual(param.value, correct) + + def test_templates(self): + tests = [ + (Parameter(self.name, self.value3, self.templates3), + self.templates3), + (Parameter(name=self.name, value=self.value4, + templates=self.templates4), self.templates4) + ] + for param, correct in tests: + self.assertEqual(param.templates, correct) + + def test_magic(self): + params = [Parameter(self.name, self.value1), + Parameter(self.name, self.value2, self.templates2), + Parameter(self.name, self.value3, self.templates3), + Parameter(self.name, self.value4, self.templates4)] + for param in params: + self.assertEqual(repr(param), repr(param.value)) + self.assertEqual(str(param), str(param.value)) + self.assertIs(param < "eggs", param.value < "eggs") + self.assertIs(param <= "bar{{spam}}", param.value <= "bar{{spam}}") + self.assertIs(param == "bar", param.value == "bar") + self.assertIs(param != "bar", param.value != "bar") + self.assertIs(param > "eggs", param.value > "eggs") + self.assertIs(param >= "bar{{spam}}", param.value >= "bar{{spam}}") + self.assertEquals(bool(param), bool(param.value)) + self.assertEquals(len(param), len(param.value)) + self.assertEquals(list(param), list(param.value)) + self.assertIs("bar" in param, "bar" in param.value) + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/tests/test_parser.py b/tests/test_parser.py new file mode 100644 index 0000000..bbf12a5 --- /dev/null +++ b/tests/test_parser.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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. + +import unittest + +from mwtemplateparserfromhell.parameter import Parameter +from mwtemplateparserfromhell.parser import Parser +from mwtemplateparserfromhell.template import Template + +TESTS = [ + ("", []), + ("abcdef ghijhk", []), + ("abc{this is not a template}def", []), + ("neither is {{this one}nor} {this one {despite}} containing braces", []), + ("this is an acceptable {{template}}", [Template("template")]), + ("{{multiple}}{{templates}}", [Template("multiple"), + Template("templates")]), + ("multiple {{-}} templates {{+}}!", [Template("-"), Template("+")]), + ("{{{no templates here}}}", []), + ("{ {{templates here}}}", [Template("templates here")]), + ("{{{{I exist}} }}", [Template("I exist")]), + ("{{{{I do not exist}}}}", []), + ("{{foo|bar|baz|eggs=spam}}", + [Template("foo", [Parameter("1", "bar"), Parameter("2", "baz"), + Parameter("eggs", "spam")])]), + ("{{abc def|ghi|jk=lmno|pqr|st=uv|wx|yz}}", + [Template("abc def", [Parameter("1", "ghi"), Parameter("jk", "lmno"), + Parameter("2", "pqr"), Parameter("st", "uv"), + Parameter("3", "wx"), Parameter("4", "yz")])]), +] + +class TestParser(unittest.TestCase): + def test_parse(self): + parser = Parser() + for unparsed, parsed in TESTS: + self.assertEqual(parser.parse(unparsed), parsed) + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/tests/test_template.py b/tests/test_template.py new file mode 100644 index 0000000..0938e4a --- /dev/null +++ b/tests/test_template.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 by Ben Kurtovic +# +# 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 itertools import permutations +import unittest + +from mwtemplateparserfromhell.parameter import Parameter +from mwtemplateparserfromhell.template import Template + +class TestTemplate(unittest.TestCase): + def setUp(self): + self.name = "foo" + self.bar = Parameter("1", "bar") + self.baz = Parameter("2", "baz") + self.eggs = Parameter("eggs", "spam") + self.params = [self.bar, self.baz, self.eggs] + + def test_construct(self): + Template(self.name) + Template(self.name, self.params) + Template(name=self.name) + Template(name=self.name, params=self.params) + + def test_name(self): + templates = [ + Template(self.name), + Template(self.name, self.params), + Template(name=self.name), + Template(name=self.name, params=self.params) + ] + for template in templates: + self.assertEqual(template.name, self.name) + + def test_params(self): + for template in (Template(self.name), Template(name=self.name)): + self.assertEqual(template.params, []) + for template in (Template(self.name, self.params), + Template(name=self.name, params=self.params)): + self.assertEqual(template.params, self.params) + + def test_get(self): + template = Template(name=self.name, params=self.params) + self.assertIs(template.get(0), self.bar) + self.assertIs(template.get(1), self.baz) + self.assertIs(template.get(2), self.eggs) + self.assertIs(template.get("1"), self.bar) + self.assertIs(template.get("2"), self.baz) + self.assertIs(template.get("eggs"), self.eggs) + + def test_repr(self): + correct1= 'Template(name=foo, params={})' + correct2 = 'Template(name=foo, params={"1": "bar", "2": "baz", "eggs": "spam"})' + tests = [(Template(self.name), correct1), + (Template(self.name, self.params), correct2)] + for template, correct in tests: + self.assertEqual(repr(template), correct) + self.assertEqual(str(template), correct) + + def test_cmp(self): + tmp1 = Template(self.name) + tmp2 = Template(name=self.name) + tmp3 = Template(self.name, []) + tmp4 = Template(name=self.name, params=[]) + tmp5 = Template(self.name, self.params) + tmp6 = Template(name=self.name, params=self.params) + + for tmpA, tmpB in permutations((tmp1, tmp2, tmp3, tmp4), 2): + self.assertEqual(tmpA, tmpB) + + for tmpA, tmpB in permutations((tmp5, tmp6), 2): + self.assertEqual(tmpA, tmpB) + + for tmpA in (tmp5, tmp6): + for tmpB in (tmp1, tmp2, tmp3, tmp4): + self.assertNotEqual(tmpA, tmpB) + self.assertNotEqual(tmpB, tmpA) + +if __name__ == "__main__": + unittest.main(verbosity=2)