| @@ -23,7 +23,7 @@ | |||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
| import re | import re | ||||
| from .compat import maxsize, str | |||||
| from .compat import maxsize, py3k, str | |||||
| from .nodes import Heading, Node, Tag, Template, Text, Wikilink | from .nodes import Heading, Node, Tag, Template, Text, Wikilink | ||||
| from .string_mixin import StringMixIn | from .string_mixin import StringMixIn | ||||
| from .utils import parse_anything | from .utils import parse_anything | ||||
| @@ -291,46 +291,36 @@ class Wikicode(StringMixIn): | |||||
| *flags*. If *forcetype* is given, only nodes that are instances of this | *flags*. If *forcetype* is given, only nodes that are instances of this | ||||
| type are yielded. | type are yielded. | ||||
| """ | """ | ||||
| if recursive: | |||||
| nodes = self._get_all_nodes(self) | |||||
| else: | |||||
| nodes = self.nodes | |||||
| for node in nodes: | |||||
| for node in (self._get_all_nodes(self) if recursive else self.nodes): | |||||
| if not forcetype or isinstance(node, forcetype): | if not forcetype or isinstance(node, forcetype): | ||||
| if not matches or re.search(matches, str(node), flags): | if not matches or re.search(matches, str(node), flags): | ||||
| yield node | yield node | ||||
| def ifilter_links(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Iterate over wikilink nodes. | |||||
| This is equivalent to :py:meth:`ifilter` with *forcetype* set to | |||||
| :py:class:`~.Wikilink`. | |||||
| """ | |||||
| return self.ifilter(recursive, matches, flags, forcetype=Wikilink) | |||||
| def ifilter_templates(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Iterate over template nodes. | |||||
| This is equivalent to :py:meth:`ifilter` with *forcetype* set to | |||||
| :py:class:`~.Template`. | |||||
| """ | |||||
| return self.filter(recursive, matches, flags, forcetype=Template) | |||||
| def ifilter_text(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Iterate over text nodes. | |||||
| This is equivalent to :py:meth:`ifilter` with *forcetype* set to | |||||
| :py:class:`~.nodes.Text`. | |||||
| @classmethod | |||||
| def _build_filter_methods(cls, meths): | |||||
| """Given a dict of Node types, build corresponding i?filter shortcuts. | |||||
| The dict should be given as keys storing the method's base name paired | |||||
| with values storing the corresponding :py:class:`~.Node` type. For | |||||
| example, the dict may contain the pair ``("templates", Template)``, | |||||
| which will produce the methods :py:meth:`ifilter_templates` and | |||||
| :py:meth:`filter_templates`, which are shortcuts for | |||||
| :py:meth:`ifilter(forcetype=Template) <ifilter>` and | |||||
| :py:meth:`filter(forcetype=Template) <filter>`, respectively. These | |||||
| shortcuts are added to the class itself, with an appropriate docstring. | |||||
| """ | """ | ||||
| return self.filter(recursive, matches, flags, forcetype=Text) | |||||
| def ifilter_tags(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Iterate over tag nodes. | |||||
| doc = """Iterate over {0}. | |||||
| This is equivalent to :py:meth:`ifilter` with *forcetype* set to | |||||
| :py:class:`~.Tag`. | |||||
| This is equivalent to :py:meth:`{1}` with *forcetype* set to | |||||
| :py:class:`~.{2}`. | |||||
| """ | """ | ||||
| return self.ifilter(recursive, matches, flags, forcetype=Tag) | |||||
| for name, forcetype in (meths.items() if py3k else meths.iteritems()): | |||||
| ifil = lambda self, **kw: self.ifilter(forcetype=forcetype, **kw) | |||||
| fil = lambda self, **kw: self.filter(forcetype=forcetype, **kw) | |||||
| ifil.__doc__ = doc.format(name, "ifilter", forcetype) | |||||
| fil.__doc__ = doc.format(name, "filter", forcetype) | |||||
| setattr(cls, "ifilter_" + name, ifil) | |||||
| setattr(cls, "filter_" + name, fil) | |||||
| def filter(self, recursive=False, matches=None, flags=FLAGS, | def filter(self, recursive=False, matches=None, flags=FLAGS, | ||||
| forcetype=None): | forcetype=None): | ||||
| @@ -340,38 +330,6 @@ class Wikicode(StringMixIn): | |||||
| """ | """ | ||||
| return list(self.ifilter(recursive, matches, flags, forcetype)) | return list(self.ifilter(recursive, matches, flags, forcetype)) | ||||
| def filter_links(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Return a list of wikilink nodes. | |||||
| This is equivalent to calling :py:func:`list` on | |||||
| :py:meth:`ifilter_links`. | |||||
| """ | |||||
| return list(self.ifilter_links(recursive, matches, flags)) | |||||
| def filter_templates(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Return a list of template nodes. | |||||
| This is equivalent to calling :py:func:`list` on | |||||
| :py:meth:`ifilter_templates`. | |||||
| """ | |||||
| return list(self.ifilter_templates(recursive, matches, flags)) | |||||
| def filter_text(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Return a list of text nodes. | |||||
| This is equivalent to calling :py:func:`list` on | |||||
| :py:meth:`ifilter_text`. | |||||
| """ | |||||
| return list(self.ifilter_text(recursive, matches, flags)) | |||||
| def filter_tags(self, recursive=False, matches=None, flags=FLAGS): | |||||
| """Return a list of tag nodes. | |||||
| This is equivalent to calling :py:func:`list` on | |||||
| :py:meth:`ifilter_tags`. | |||||
| """ | |||||
| return list(self.ifilter_tags(recursive, matches, flags)) | |||||
| def get_sections(self, flat=True, matches=None, levels=None, flags=FLAGS, | def get_sections(self, flat=True, matches=None, levels=None, flags=FLAGS, | ||||
| include_headings=True): | include_headings=True): | ||||
| """Return a list of sections within the page. | """Return a list of sections within the page. | ||||
| @@ -470,3 +428,10 @@ class Wikicode(StringMixIn): | |||||
| """ | """ | ||||
| marker = object() # Random object we can find with certainty in a list | marker = object() # Random object we can find with certainty in a list | ||||
| return "\n".join(self._get_tree(self, [], marker, 0)) | return "\n".join(self._get_tree(self, [], marker, 0)) | ||||
| Wikicode._build_filter_methods({ | |||||
| "links": Wikilink, | |||||
| "templates": Template, | |||||
| "text": Text, | |||||
| "tag": Tag | |||||
| }) | |||||