From b3bfe68cd87bdea8880fe655dafc166533468656 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 22 Aug 2012 00:37:00 -0400 Subject: [PATCH] Start Argument node type, implement argument in builder (#4). --- docs/api/mwparserfromhell.nodes.rst | 8 +++++ mwparserfromhell/nodes/__init__.py | 4 ++- mwparserfromhell/nodes/argument.py | 69 +++++++++++++++++++++++++++++++++++++ mwparserfromhell/parser/builder.py | 20 ++++++++++- mwparserfromhell/parser/tokens.py | 4 +++ 5 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 mwparserfromhell/nodes/argument.py diff --git a/docs/api/mwparserfromhell.nodes.rst b/docs/api/mwparserfromhell.nodes.rst index 6bd175f..9db797d 100644 --- a/docs/api/mwparserfromhell.nodes.rst +++ b/docs/api/mwparserfromhell.nodes.rst @@ -9,6 +9,14 @@ nodes Package .. autoclass:: mwparserfromhell.nodes.Node :special-members: +:mod:`argument` Module +---------------------- + +.. automodule:: mwparserfromhell.nodes.argument + :members: + :undoc-members: + :show-inheritance: + :mod:`heading` Module --------------------- diff --git a/mwparserfromhell/nodes/__init__.py b/mwparserfromhell/nodes/__init__.py index f066c0e..c04f718 100644 --- a/mwparserfromhell/nodes/__init__.py +++ b/mwparserfromhell/nodes/__init__.py @@ -34,7 +34,8 @@ from __future__ import unicode_literals from ..compat import str from ..string_mixin import StringMixIn -__all__ = ["Node", "Text", "Heading", "HTMLEntity", "Tag", "Template"] +__all__ = ["Node", "Text", "Argument", "Heading", "HTMLEntity", "Tag", + "Template"] class Node(StringMixIn): """Represents the base Node type, demonstrating the methods to override. @@ -66,6 +67,7 @@ class Node(StringMixIn): from . import extras from .text import Text +from .argument import Argument from .heading import Heading from .html_entity import HTMLEntity from .tag import Tag diff --git a/mwparserfromhell/nodes/argument.py b/mwparserfromhell/nodes/argument.py new file mode 100644 index 0000000..dfe92cf --- /dev/null +++ b/mwparserfromhell/nodes/argument.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 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 __future__ import unicode_literals + +from . import Node +from ..compat import str +from ..utils import parse_anything + +__all__ = ["Argument"] + +class Argument(Node): + """Represents a template argument substitution, like ``{{{foo}}}``.""" + def __init__(self, name, default=None): + super(Argument, self).__init__() + self._value = value + self._default = None + + def __unicode__(self): + start = "{{{" + unicode(self.name) + if self.default is not None: + return start + "|" + unicode(self.default) + "}}}" + return start + "}}}" + + @property + def name(self): + """The name of the argument to substitute.""" + return self._name + + @property + def default(self): + """The default value to substitute if none is passed. + + This will be ``None`` if the argument wasn't defined with one. The + MediaWiki parser handles this by rendering the argument itself in the + result, complete braces. To have the argument render as nothing, set + default to ``""`` (``{{{arg}}}`` vs. ``{{{arg|}}}``). + """ + return self._default + + @name.setter + def name(self, value): + self._name = parse_anything(value) + + @default.setter + def default(self, default): + if default is None: + self._default = None + else: + self._default = parse_anything(default) diff --git a/mwparserfromhell/parser/builder.py b/mwparserfromhell/parser/builder.py index 82233e4..94fd57d 100644 --- a/mwparserfromhell/parser/builder.py +++ b/mwparserfromhell/parser/builder.py @@ -24,7 +24,7 @@ from __future__ import unicode_literals from . import tokens from ..compat import str -from ..nodes import Heading, HTMLEntity, Tag, Template, Text +from ..nodes import Argument, Heading, HTMLEntity, Tag, Template, Text from ..nodes.extras import Attribute, Parameter from ..smart_list import SmartList from ..wikicode import Wikicode @@ -109,6 +109,22 @@ class Builder(object): else: self._write(self._handle_token(token)) + def _handle_argument(self): + """Handle a case where an argument is at the head of the tokens.""" + name = None + self._push() + while self._tokens: + token = self._tokens.pop() + if isinstance(token, tokens.ArgumentSeparator): + name = self._pop() + self._push() + elif isinstance(token, tokens.ArgumentClose): + if name is not None: + return Argument(name, self._pop()) + return Argument(self._pop()) + else: + self._write(self._handle_token(token)) + def _handle_entity(self): """Handle a case where a HTML entity is at the head of the tokens.""" token = self._tokens.pop() @@ -187,6 +203,8 @@ class Builder(object): return Text(token.text) elif isinstance(token, tokens.TemplateOpen): return self._handle_template() + elif isinstance(token, tokens.ArgumentOpen): + return self._handle_argument() elif isinstance(token, tokens.HTMLEntityStart): return self._handle_entity() elif isinstance(token, tokens.HeadingStart): diff --git a/mwparserfromhell/parser/tokens.py b/mwparserfromhell/parser/tokens.py index 23a04b2..0e91d48 100644 --- a/mwparserfromhell/parser/tokens.py +++ b/mwparserfromhell/parser/tokens.py @@ -75,6 +75,10 @@ TemplateParamSeparator = make("TemplateParamSeparator") # | TemplateParamEquals = make("TemplateParamEquals") # = TemplateClose = make("TemplateClose") # }} +ArgumentOpen = make("ArgumentOpen") # {{{ +ArgumentSeparator = make("ArgumentSeparator") # | +ArgumentClose = make("ArgumentClose") # }}} + HTMLEntityStart = make("HTMLEntityStart") # & HTMLEntityNumeric = make("HTMLEntityNumeric") # # HTMLEntityHex = make("HTMLEntityHex") # x