@@ -34,4 +34,4 @@ __email__ = "ben.kurtovic@verizon.net" | |||
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 | |||
# SOFTWARE. | |||
from mwparserfromhell.parser.utils import parse_anything | |||
from mwparserfromhell.string_mixin import StringMixIn | |||
__all__ = ["Parameter"] | |||
@@ -46,3 +47,15 @@ class Parameter(StringMixIn): | |||
@property | |||
def showkey(self): | |||
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"] | |||
class HTMLEntity(Node): | |||
def __init__(self, value, named): | |||
def __init__(self, value, named, hexadecimal=False): | |||
self._value = value | |||
self._named = named | |||
self._hexadecimal = hexadecimal | |||
def __unicode__(self): | |||
if self.named: | |||
return u"&{0};".format(self.value) | |||
if self.hexadecimal: | |||
return u"&#x{0};".format(self.value) | |||
return u"&#{0};".format(self.value) | |||
@property | |||
@@ -44,7 +47,13 @@ class HTMLEntity(Node): | |||
def named(self): | |||
return self._named | |||
@property | |||
def hexadecimal(self): | |||
return self._hexadecimal | |||
def normalize(self): | |||
if self.named: | |||
return unichr(htmlentitydefs.name2codepoint[self.value]) | |||
if self.hexadecimal: | |||
return unichr(int(str(self.value), 16)) | |||
return unichr(self.value) |
@@ -21,6 +21,8 @@ | |||
# SOFTWARE. | |||
from mwparserfromhell.nodes import Node | |||
from mwparserfromhell.nodes.extras import Parameter | |||
from mwparserfromhell.parser.utils import parse_anything | |||
__all__ = ["Template"] | |||
@@ -39,6 +41,9 @@ class Template(Node): | |||
else: | |||
return "{{" + unicode(self.name) + "}}" | |||
def _blank_param_value(self, value): # TODO | |||
pass | |||
@property | |||
def name(self): | |||
return self._name | |||
@@ -47,14 +52,53 @@ class Template(Node): | |||
def params(self): | |||
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 | |||
def value(self): | |||
return self._value | |||
def replace(self, old, new, count): # TODO | |||
pass |
@@ -27,10 +27,13 @@ from mwparserfromhell.wikicode import Wikicode | |||
__all__ = ["DemoParser"] | |||
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! | |||
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 mwparserfromhell | |||
from mwparserfromhell.nodes import HTMLEntity, Node, Template, Text | |||
from mwparserfromhell.parser.utils import parse_anything | |||
from mwparserfromhell.string_mixin import StringMixIn | |||
__all__ = ["Wikicode"] | |||
@@ -37,24 +37,6 @@ class Wikicode(StringMixIn): | |||
def __unicode__(self): | |||
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): | |||
yield (None, node) | |||
if isinstance(node, Template): | |||
@@ -147,7 +129,7 @@ class Wikicode(StringMixIn): | |||
return self.nodes[index] | |||
def set(self, index, value): | |||
nodes = self._nodify(value) | |||
nodes = parse_anything(value).nodes | |||
if len(nodes) > 1: | |||
raise ValueError("Cannot coerce multiple nodes into one index") | |||
if index >= len(self.nodes) or -1 * index > len(self.nodes): | |||
@@ -169,7 +151,7 @@ class Wikicode(StringMixIn): | |||
raise ValueError(obj) | |||
def insert(self, index, value): | |||
nodes = self._nodify(value) | |||
nodes = parse_anything(value).nodes | |||
for node in reversed(nodes): | |||
self.nodes.insert(index, node) | |||
@@ -189,7 +171,7 @@ class Wikicode(StringMixIn): | |||
self._do_search(obj, recursive, callback, self, value) | |||
def append(self, value): | |||
nodes = self._nodify(value) | |||
nodes = parse_anything(value).nodes | |||
for node in nodes: | |||
self.nodes.append(node) | |||