@@ -34,4 +34,4 @@ __email__ = "ben.kurtovic@verizon.net" | |||||
from mwparserfromhell import nodes, parser, string_mixin, wikicode | from mwparserfromhell import nodes, parser, string_mixin, wikicode | ||||
parse = lambda text: parser.Parser().parse(text) | |||||
parse = lambda text: parser.Parser(text).parse() |
@@ -20,6 +20,7 @@ | |||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
# SOFTWARE. | # SOFTWARE. | ||||
from mwparserfromhell.parser.utils import parse_anything | |||||
from mwparserfromhell.string_mixin import StringMixIn | from mwparserfromhell.string_mixin import StringMixIn | ||||
__all__ = ["Parameter"] | __all__ = ["Parameter"] | ||||
@@ -46,3 +47,15 @@ class Parameter(StringMixIn): | |||||
@property | @property | ||||
def showkey(self): | def showkey(self): | ||||
return self._showkey | return self._showkey | ||||
@name.setter | |||||
def name(self, newval): | |||||
self._name = parse_anything(newval) | |||||
@value.setter | |||||
def value(self, newval): | |||||
self._value = parse_anything(newval) | |||||
@showkey.setter | |||||
def showkey(self, newval): | |||||
self._showkey = newval |
@@ -27,13 +27,16 @@ from mwparserfromhell.nodes import Node | |||||
__all__ = ["HTMLEntity"] | __all__ = ["HTMLEntity"] | ||||
class HTMLEntity(Node): | class HTMLEntity(Node): | ||||
def __init__(self, value, named): | |||||
def __init__(self, value, named, hexadecimal=False): | |||||
self._value = value | self._value = value | ||||
self._named = named | self._named = named | ||||
self._hexadecimal = hexadecimal | |||||
def __unicode__(self): | def __unicode__(self): | ||||
if self.named: | if self.named: | ||||
return u"&{0};".format(self.value) | return u"&{0};".format(self.value) | ||||
if self.hexadecimal: | |||||
return u"&#x{0};".format(self.value) | |||||
return u"&#{0};".format(self.value) | return u"&#{0};".format(self.value) | ||||
@property | @property | ||||
@@ -44,7 +47,13 @@ class HTMLEntity(Node): | |||||
def named(self): | def named(self): | ||||
return self._named | return self._named | ||||
@property | |||||
def hexadecimal(self): | |||||
return self._hexadecimal | |||||
def normalize(self): | def normalize(self): | ||||
if self.named: | if self.named: | ||||
return unichr(htmlentitydefs.name2codepoint[self.value]) | return unichr(htmlentitydefs.name2codepoint[self.value]) | ||||
if self.hexadecimal: | |||||
return unichr(int(str(self.value), 16)) | |||||
return unichr(self.value) | return unichr(self.value) |
@@ -21,6 +21,8 @@ | |||||
# SOFTWARE. | # SOFTWARE. | ||||
from mwparserfromhell.nodes import Node | from mwparserfromhell.nodes import Node | ||||
from mwparserfromhell.nodes.extras import Parameter | |||||
from mwparserfromhell.parser.utils import parse_anything | |||||
__all__ = ["Template"] | __all__ = ["Template"] | ||||
@@ -39,6 +41,9 @@ class Template(Node): | |||||
else: | else: | ||||
return "{{" + unicode(self.name) + "}}" | return "{{" + unicode(self.name) + "}}" | ||||
def _blank_param_value(self, value): # TODO | |||||
pass | |||||
@property | @property | ||||
def name(self): | def name(self): | ||||
return self._name | return self._name | ||||
@@ -47,14 +52,53 @@ class Template(Node): | |||||
def params(self): | def params(self): | ||||
return self._params | return self._params | ||||
def has_param(self): | |||||
pass | |||||
def has_param(self, name): | |||||
name = name.strip() if isinstance(name, basestring) else unicode(name) | |||||
for param in self.params: | |||||
if param.name.strip() == name: | |||||
return True | |||||
return False | |||||
def get_param(self): | |||||
pass | |||||
def get_param(self, name): | |||||
name = name.strip() if isinstance(name, basestring) else unicode(name) | |||||
for param in self.params: | |||||
if param.name.strip() == name: | |||||
return param | |||||
raise ValueError(name) | |||||
def add_param(self): | |||||
pass | |||||
def add_param(self, name, value, showkey=None): | |||||
name, value = parse_anything(name), parse_anything(value) | |||||
surface_text = value.filter_text(recursive=False) | |||||
for node in surface_text: | |||||
node.replace("|", "|") # INSERT AS HTMLEntity INSTEAD OF RAW TEXT | |||||
def remove_param(self): | |||||
pass | |||||
if showkey is None: | |||||
if any(["=" in node for node in surface_text]): | |||||
showkey = True | |||||
else: | |||||
try: | |||||
int(name) | |||||
except ValueError: | |||||
showkey = False | |||||
else: | |||||
showkey = True | |||||
elif not showkey: | |||||
for node in surface_text: | |||||
node.replace("=", "|") # INSERT AS HTMLEntity INSTEAD OF RAW TEXT | |||||
if self.has_param(name): | |||||
self.remove_param(name, keep_field=True) | |||||
existing = self.get_param(name).value | |||||
self.get_param(name).value = value # CONFORM TO FORMATTING? | |||||
else: | |||||
self.params.append(Parameter(name, value, showkey)) # CONFORM TO FORMATTING CONVENTIONS? | |||||
def remove_param(self, name, keep_field=False): # DON'T MESS UP NUMBERING WITH show_key = False AND keep_field = False | |||||
name = name.strip() if isinstance(name, basestring) else unicode(name) | |||||
for param in self.params: | |||||
if param.name.strip() == name: | |||||
if keep_field: | |||||
return self._blank_param_value(param.value) | |||||
else: | |||||
return self.params.remove(param) | |||||
raise ValueError(name) |
@@ -34,3 +34,6 @@ class Text(Node): | |||||
@property | @property | ||||
def value(self): | def value(self): | ||||
return self._value | return self._value | ||||
def replace(self, old, new, count): # TODO | |||||
pass |
@@ -27,10 +27,13 @@ from mwparserfromhell.wikicode import Wikicode | |||||
__all__ = ["DemoParser"] | __all__ = ["DemoParser"] | ||||
class DemoParser(object): | class DemoParser(object): | ||||
def _tokenize(self, text): | |||||
return text | |||||
def __init__(self, text): | |||||
self.text = text | |||||
def parse(self, text): | |||||
def _tokenize(self): | |||||
return [] | |||||
def parse(self): | |||||
# Ensure text is unicode! | # Ensure text is unicode! | ||||
text = u"This is a {{test}} message with a {{template|with|foo={{params}}}}." | text = u"This is a {{test}} message with a {{template|with|foo={{params}}}}." | ||||
@@ -0,0 +1,45 @@ | |||||
# -*- coding: utf-8 -*- | |||||
# | |||||
# Copyright (C) 2012 Ben Kurtovic <ben.kurtovic@verizon.net> | |||||
# | |||||
# 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 mwparserfromhell | |||||
from mwparserfromhell.nodes import Node | |||||
from mwparserfromhell.wikicode import Wikicode | |||||
def parse_anything(value): | |||||
if isinstance(value, Wikicode): | |||||
return value | |||||
if isinstance(value, Node): | |||||
return Wikicode([value]) | |||||
if isinstance(value, basestring): | |||||
return mwparserfromhell.parse(value) | |||||
if isinstance(value, int): | |||||
return mwparserfromhell.parse(unicode(value)) | |||||
if value is None: | |||||
return Wikicode([]) | |||||
try: | |||||
nodelist = [] | |||||
for item in value: | |||||
nodelist += parse_anything(item).nodes | |||||
except TypeError: | |||||
error = "Needs string, Node, Wikicode, int, None, or iterable of these, but got {0}: {1}" | |||||
raise ValueError(error.format(type(value), value)) | |||||
return Wikicode(nodelist) |
@@ -22,8 +22,8 @@ | |||||
import re | import re | ||||
import mwparserfromhell | |||||
from mwparserfromhell.nodes import HTMLEntity, Node, Template, Text | from mwparserfromhell.nodes import HTMLEntity, Node, Template, Text | ||||
from mwparserfromhell.parser.utils import parse_anything | |||||
from mwparserfromhell.string_mixin import StringMixIn | from mwparserfromhell.string_mixin import StringMixIn | ||||
__all__ = ["Wikicode"] | __all__ = ["Wikicode"] | ||||
@@ -37,24 +37,6 @@ class Wikicode(StringMixIn): | |||||
def __unicode__(self): | def __unicode__(self): | ||||
return "".join([unicode(node) for node in self.nodes]) | return "".join([unicode(node) for node in self.nodes]) | ||||
def _nodify(self, value): | |||||
if isinstance(value, Wikicode): | |||||
return value.nodes | |||||
if isinstance(value, Node): | |||||
return [value] | |||||
if isinstance(value, basestring): | |||||
return mwparserfromhell.parse(value).nodes | |||||
try: | |||||
nodelist = list(value) | |||||
except TypeError: | |||||
error = "Needs string, Node, iterable of Nodes, or Wikicode object, but got {0}: {1}" | |||||
raise ValueError(error.format(type(value), value)) | |||||
if not all([isinstance(node, Node) for node in nodelist]): | |||||
error = "Was passed an interable {0}, but it did not contain all Nodes: {1}" | |||||
raise ValueError(error.format(type(value), value)) | |||||
return nodelist | |||||
def _iterate_over_children(self, node): | def _iterate_over_children(self, node): | ||||
yield (None, node) | yield (None, node) | ||||
if isinstance(node, Template): | if isinstance(node, Template): | ||||
@@ -147,7 +129,7 @@ class Wikicode(StringMixIn): | |||||
return self.nodes[index] | return self.nodes[index] | ||||
def set(self, index, value): | def set(self, index, value): | ||||
nodes = self._nodify(value) | |||||
nodes = parse_anything(value).nodes | |||||
if len(nodes) > 1: | if len(nodes) > 1: | ||||
raise ValueError("Cannot coerce multiple nodes into one index") | raise ValueError("Cannot coerce multiple nodes into one index") | ||||
if index >= len(self.nodes) or -1 * index > len(self.nodes): | if index >= len(self.nodes) or -1 * index > len(self.nodes): | ||||
@@ -169,7 +151,7 @@ class Wikicode(StringMixIn): | |||||
raise ValueError(obj) | raise ValueError(obj) | ||||
def insert(self, index, value): | def insert(self, index, value): | ||||
nodes = self._nodify(value) | |||||
nodes = parse_anything(value).nodes | |||||
for node in reversed(nodes): | for node in reversed(nodes): | ||||
self.nodes.insert(index, node) | self.nodes.insert(index, node) | ||||
@@ -189,7 +171,7 @@ class Wikicode(StringMixIn): | |||||
self._do_search(obj, recursive, callback, self, value) | self._do_search(obj, recursive, callback, self, value) | ||||
def append(self, value): | def append(self, value): | ||||
nodes = self._nodify(value) | |||||
nodes = parse_anything(value).nodes | |||||
for node in nodes: | for node in nodes: | ||||
self.nodes.append(node) | self.nodes.append(node) | ||||