| @@ -5,7 +5,7 @@ mwparserfromhell | |||||
| that provides an easy-to-use and outrageously powerful parser for MediaWiki_ | that provides an easy-to-use and outrageously powerful parser for MediaWiki_ | ||||
| wikicode. It supports Python 2 and Python 3. | wikicode. It supports Python 2 and Python 3. | ||||
| Developed by Earwig_ and named by `Σ`_. | |||||
| Developed by Earwig_ with help from `Σ`_. | |||||
| Installation | Installation | ||||
| ------------ | ------------ | ||||
| @@ -1,16 +1,25 @@ | |||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
| """ | |||||
| Implements support for both Python 2 and Python 3. | |||||
| """ | |||||
| import sys | import sys | ||||
| v = sys.version_info[0] | |||||
| py3k = sys.version_info.major == 3 | |||||
| if v >= 3: | |||||
| if py3k: | |||||
| bytes = bytes | bytes = bytes | ||||
| str = str | str = str | ||||
| basestring = (str, bytes) | |||||
| import html.entities as htmlentitydefs | |||||
| basestring = str | |||||
| maxsize = sys.maxsize | |||||
| import html.entities as htmlentities | |||||
| else: | else: | ||||
| bytes = str | bytes = str | ||||
| str = unicode | str = unicode | ||||
| basestring = basestring | basestring = basestring | ||||
| import htmlentitydefs | |||||
| maxsize = sys.maxint | |||||
| import htmlentitydefs as htmlentities | |||||
| del sys | |||||
| @@ -20,7 +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. | ||||
| import sys | |||||
| from .compat import maxsize, py3k | |||||
| __all__ = ["SmartList"] | __all__ = ["SmartList"] | ||||
| @@ -50,7 +50,7 @@ class SmartList(list): | |||||
| for child, (start, stop, step) in self._children.itervalues(): | for child, (start, stop, step) in self._children.itervalues(): | ||||
| if start >= key.stop: | if start >= key.stop: | ||||
| self._children[id(child)][1][0] += diff | self._children[id(child)][1][0] += diff | ||||
| if stop >= key.stop and stop != sys.maxint: | |||||
| if stop >= key.stop and stop != maxsize: | |||||
| self._children[id(child)][1][1] += diff | self._children[id(child)][1][1] += diff | ||||
| def __delitem__(self, key): | def __delitem__(self, key): | ||||
| @@ -64,14 +64,15 @@ class SmartList(list): | |||||
| if stop >= key.stop: | if stop >= key.stop: | ||||
| self._children[id(child)][1][1] -= diff | self._children[id(child)][1][1] -= diff | ||||
| def __getslice__(self, start, stop): | |||||
| return self.__getitem__(slice(start, stop)) | |||||
| if not py3k: | |||||
| def __getslice__(self, start, stop): | |||||
| return self.__getitem__(slice(start, stop)) | |||||
| def __setslice__(self, start, stop, iterable): | |||||
| self.__setitem__(slice(start, stop), iterable) | |||||
| def __setslice__(self, start, stop, iterable): | |||||
| self.__setitem__(slice(start, stop), iterable) | |||||
| def __delslice__(self, start, stop): | |||||
| self.__delitem__(slice(start, stop)) | |||||
| def __delslice__(self, start, stop): | |||||
| self.__delitem__(slice(start, stop)) | |||||
| def __add__(self, other): | def __add__(self, other): | ||||
| return SmartList(list(self) + other) | return SmartList(list(self) + other) | ||||
| @@ -165,8 +166,12 @@ class _ListProxy(list): | |||||
| return self._render() >= list(other) | return self._render() >= list(other) | ||||
| return self._render() >= other | return self._render() >= other | ||||
| def __nonzero__(self): | |||||
| return bool(self._render()) | |||||
| if py3k: | |||||
| def __bool__(self): | |||||
| return bool(self._render()) | |||||
| else: | |||||
| def __nonzero__(self): | |||||
| return bool(self._render()) | |||||
| def __len__(self): | def __len__(self): | ||||
| return (self._stop - self._start) / self._step | return (self._stop - self._start) / self._step | ||||
| @@ -205,14 +210,15 @@ class _ListProxy(list): | |||||
| def __contains__(self, item): | def __contains__(self, item): | ||||
| return item in self._render() | return item in self._render() | ||||
| def __getslice__(self, start, stop): | |||||
| return self.__getitem__(slice(start, stop)) | |||||
| if not py3k: | |||||
| def __getslice__(self, start, stop): | |||||
| return self.__getitem__(slice(start, stop)) | |||||
| def __setslice__(self, start, stop, iterable): | |||||
| self.__setitem__(slice(start, stop), iterable) | |||||
| def __setslice__(self, start, stop, iterable): | |||||
| self.__setitem__(slice(start, stop), iterable) | |||||
| def __delslice__(self, start, stop): | |||||
| self.__delitem__(slice(start, stop)) | |||||
| def __delslice__(self, start, stop): | |||||
| self.__delitem__(slice(start, stop)) | |||||
| def __add__(self, other): | def __add__(self, other): | ||||
| return SmartList(list(self) + other) | return SmartList(list(self) + other) | ||||
| @@ -21,26 +21,30 @@ | |||||
| # SOFTWARE. | # SOFTWARE. | ||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
| from .compat import str, bytes, v | |||||
| from .compat import py3k, str | |||||
| __all__ = ["StringMixIn"] | __all__ = ["StringMixIn"] | ||||
| def inheritdoc(method): | def inheritdoc(method): | ||||
| try: | |||||
| method.__doc__ = getattr(str, method.__name__).__doc__ | |||||
| except AttributeError: | |||||
| method.__doc__ = "This feature is only available on Python 2." | |||||
| method.__doc__ = getattr(str, method.__name__).__doc__ | |||||
| return method | return method | ||||
| class StringMixIn(object): | class StringMixIn(object): | ||||
| if v >= 3: | |||||
| def __str__(self): | |||||
| return self.__unicode__() | |||||
| if py3k: | |||||
| def __str__(self): | |||||
| return self.__unicode__() | |||||
| def __bytes__(self): | |||||
| return self.__unicode__().encode("utf8") | |||||
| else: | else: | ||||
| def __str__(self): | def __str__(self): | ||||
| return self.__unicode__().encode("utf8") | return self.__unicode__().encode("utf8") | ||||
| def __unicode__(self): | |||||
| raise NotImplementedError() | |||||
| def __repr__(self): | def __repr__(self): | ||||
| return repr(self.__unicode__()) | return repr(self.__unicode__()) | ||||
| @@ -74,11 +78,12 @@ class StringMixIn(object): | |||||
| return self.__unicode__() >= other.__unicode__() | return self.__unicode__() >= other.__unicode__() | ||||
| return self.__unicode__() >= other | return self.__unicode__() >= other | ||||
| def __nonzero__(self): | |||||
| return bool(self.__unicode__()) | |||||
| def __unicode__(self): | |||||
| raise NotImplementedError() | |||||
| if py3k: | |||||
| def __bool__(self): | |||||
| return bool(self.__unicode__()) | |||||
| else: | |||||
| def __nonzero__(self): | |||||
| return bool(self.__unicode__()) | |||||
| def __len__(self): | def __len__(self): | ||||
| return len(self.__unicode__()) | return len(self.__unicode__()) | ||||
| @@ -92,7 +97,7 @@ class StringMixIn(object): | |||||
| def __contains__(self, item): | def __contains__(self, item): | ||||
| if isinstance(item, StringMixIn): | if isinstance(item, StringMixIn): | ||||
| return unicode(item) in self.__unicode__() | |||||
| return str(item) in self.__unicode__() | |||||
| return item in self.__unicode__() | return item in self.__unicode__() | ||||
| @inheritdoc | @inheritdoc | ||||
| @@ -107,9 +112,10 @@ class StringMixIn(object): | |||||
| def count(self, sub=None, start=None, end=None): | def count(self, sub=None, start=None, end=None): | ||||
| return self.__unicode__().count(sub, start, end) | return self.__unicode__().count(sub, start, end) | ||||
| @inheritdoc | |||||
| def decode(self, encoding=None, errors=None): | |||||
| return self.__unicode__().decode(encoding, errors) | |||||
| if not py3k: | |||||
| @inheritdoc | |||||
| def decode(self, encoding=None, errors=None): | |||||
| return self.__unicode__().decode(encoding, errors) | |||||
| @inheritdoc | @inheritdoc | ||||
| def encode(self, encoding=None, errors=None): | def encode(self, encoding=None, errors=None): | ||||
| @@ -23,21 +23,24 @@ | |||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
| import mwparserfromhell | import mwparserfromhell | ||||
| from .compat import basestring, bytes, str | |||||
| from .nodes import Node | from .nodes import Node | ||||
| from .smart_list import SmartList | from .smart_list import SmartList | ||||
| from .compat import str, bytes, basestring | |||||
| def parse_anything(value): | def parse_anything(value): | ||||
| wikicode = mwparserfromhell.wikicode.Wikicode | wikicode = mwparserfromhell.wikicode.Wikicode | ||||
| if isinstance(value, wikicode): | if isinstance(value, wikicode): | ||||
| return value | return value | ||||
| if isinstance(value, Node): | |||||
| elif isinstance(value, Node): | |||||
| return wikicode(SmartList([value])) | return wikicode(SmartList([value])) | ||||
| if isinstance(value, basestring): | |||||
| elif isinstance(value, basestring): | |||||
| return mwparserfromhell.parse(value) | return mwparserfromhell.parse(value) | ||||
| if isinstance(value, int): | |||||
| elif isinstance(value, bytes): | |||||
| # This should only happen in py3k when bytes is not in basestring: | |||||
| return mwparserfromhell.parse(value.decode("utf8")) | |||||
| elif isinstance(value, int): | |||||
| return mwparserfromhell.parse(str(value)) | return mwparserfromhell.parse(str(value)) | ||||
| if value is None: | |||||
| elif value is None: | |||||
| return wikicode(SmartList()) | return wikicode(SmartList()) | ||||
| try: | try: | ||||
| nodelist = SmartList() | nodelist = SmartList() | ||||