| @@ -11,7 +11,8 @@ | |||||
| # All configuration values have a default; values that are commented out | # All configuration values have a default; values that are commented out | ||||
| # serve to show the default. | # serve to show the default. | ||||
| import sys, os | |||||
| import sys | |||||
| import os | |||||
| # If extensions (or modules to document with autodoc) are in another directory, | # If extensions (or modules to document with autodoc) are in another directory, | ||||
| # add these directories to sys.path here. If the directory is relative to the | # add these directories to sys.path here. If the directory is relative to the | ||||
| @@ -30,6 +30,17 @@ __license__ = "MIT License" | |||||
| __version__ = "0.7.dev0" | __version__ = "0.7.dev0" | ||||
| __email__ = "ben.kurtovic@gmail.com" | __email__ = "ben.kurtovic@gmail.com" | ||||
| __all__ = [ | |||||
| "definitions", | |||||
| "nodes", | |||||
| "parser", | |||||
| "smart_list", | |||||
| "string_mixin", | |||||
| "utils", | |||||
| "wikicode", | |||||
| "parse", | |||||
| ] | |||||
| from . import definitions, nodes, parser, smart_list, string_mixin, utils, wikicode | from . import definitions, nodes, parser, smart_list, string_mixin, utils, wikicode | ||||
| parse = utils.parse_anything | parse = utils.parse_anything | ||||
| @@ -50,4 +50,5 @@ __all__ = [ | |||||
| "Template", | "Template", | ||||
| "Text", | "Text", | ||||
| "Wikilink", | "Wikilink", | ||||
| "extras", | |||||
| ] | ] | ||||
| @@ -23,5 +23,10 @@ This package contains objects used by :class:`.Node`\\ s, but that are not | |||||
| nodes themselves. This includes template parameters and HTML tag attributes. | nodes themselves. This includes template parameters and HTML tag attributes. | ||||
| """ | """ | ||||
| __all__ = [ | |||||
| "Attribute", | |||||
| "Parameter", | |||||
| ] | |||||
| from .attribute import Attribute | from .attribute import Attribute | ||||
| from .parameter import Parameter | from .parameter import Parameter | ||||
| @@ -239,12 +239,10 @@ class Template(Node): | |||||
| return self.has(name, ignore_empty) | return self.has(name, ignore_empty) | ||||
| @overload | @overload | ||||
| def get(self, name: Union[str, Any]) -> Parameter: | |||||
| ... | |||||
| def get(self, name: Union[str, Any]) -> Parameter: ... | |||||
| @overload | @overload | ||||
| def get(self, name: Union[str, Any], default: T) -> Union[Parameter, T]: | |||||
| ... | |||||
| def get(self, name: Union[str, Any], default: T) -> Union[Parameter, T]: ... | |||||
| def get(self, name: Union[str, Any], default: T = _UNSET) -> Union[Parameter, T]: | def get(self, name: Union[str, Any], default: T = _UNSET) -> Union[Parameter, T]: | ||||
| """Get the parameter whose name is *name*. | """Get the parameter whose name is *name*. | ||||
| @@ -32,8 +32,6 @@ try: | |||||
| use_c = True | use_c = True | ||||
| except ImportError: | except ImportError: | ||||
| from .tokenizer import Tokenizer | |||||
| CTokenizer = None | CTokenizer = None | ||||
| use_c = False | use_c = False | ||||
| @@ -63,7 +63,7 @@ struct avl_tree_node { | |||||
| /* Cast an AVL tree node to the containing data structure. */ | /* Cast an AVL tree node to the containing data structure. */ | ||||
| #define avl_tree_entry(entry, type, member) \ | #define avl_tree_entry(entry, type, member) \ | ||||
| ((type *) ((char *) (entry) -offsetof(type, member))) | |||||
| ((type *) ((char *) (entry) - offsetof(type, member))) | |||||
| /* Returns a pointer to the parent of the specified AVL tree node, or NULL if it | /* Returns a pointer to the parent of the specified AVL tree node, or NULL if it | ||||
| * is already the root of the tree. */ | * is already the root of the tree. */ | ||||
| @@ -396,7 +396,10 @@ class Tokenizer: | |||||
| self._emit_text("//") | self._emit_text("//") | ||||
| self._head += 2 | self._head += 2 | ||||
| else: | else: | ||||
| all_valid = lambda: all(char in self.URISCHEME for char in self._read()) | |||||
| def all_valid(): | |||||
| return all(char in self.URISCHEME for char in self._read()) | |||||
| scheme = "" | scheme = "" | ||||
| while self._read() is not self.END and all_valid(): | while self._read() is not self.END and all_valid(): | ||||
| scheme += self._read() | scheme += self._read() | ||||
| @@ -827,7 +830,10 @@ class Tokenizer: | |||||
| def _handle_tag_close_close(self): | def _handle_tag_close_close(self): | ||||
| """Handle the ending of a closing tag (``</foo>``).""" | """Handle the ending of a closing tag (``</foo>``).""" | ||||
| strip = lambda tok: tok.text.rstrip().lower() | |||||
| def strip(tok): | |||||
| return tok.text.rstrip().lower() | |||||
| closing = self._pop() | closing = self._pop() | ||||
| if len(closing) != 1 or ( | if len(closing) != 1 or ( | ||||
| not isinstance(closing[0], tokens.Text) | not isinstance(closing[0], tokens.Text) | ||||
| @@ -840,7 +846,10 @@ class Tokenizer: | |||||
| def _handle_blacklisted_tag(self): | def _handle_blacklisted_tag(self): | ||||
| """Handle the body of an HTML tag that is parser-blacklisted.""" | """Handle the body of an HTML tag that is parser-blacklisted.""" | ||||
| strip = lambda text: text.rstrip().lower() | |||||
| def strip(text): | |||||
| return text.rstrip().lower() | |||||
| while True: | while True: | ||||
| this, nxt = self._read(), self._read(1) | this, nxt = self._read(), self._read(1) | ||||
| if this is self.END: | if this is self.END: | ||||
| @@ -25,5 +25,6 @@ This module contains the :class:`.SmartList` type, as well as its | |||||
| reflect changes made to the main list, and vice-versa. | reflect changes made to the main list, and vice-versa. | ||||
| """ | """ | ||||
| from .list_proxy import ListProxy as _ListProxy | |||||
| __all__ = ["SmartList"] | |||||
| from .smart_list import SmartList | from .smart_list import SmartList | ||||
| @@ -176,7 +176,10 @@ class Wikicode(StringMixIn): | |||||
| return obj, slice(0, len(obj.nodes)) | return obj, slice(0, len(obj.nodes)) | ||||
| if isinstance(obj, Node): | if isinstance(obj, Node): | ||||
| mkslice = lambda i: slice(i, i + 1) | |||||
| def mkslice(i): | |||||
| return slice(i, i + 1) | |||||
| if not recursive: | if not recursive: | ||||
| return self, mkslice(self.index(obj)) | return self, mkslice(self.index(obj)) | ||||
| for node in self.nodes: | for node in self.nodes: | ||||
| @@ -258,8 +261,12 @@ class Wikicode(StringMixIn): | |||||
| else: | else: | ||||
| lines.append(" " * 6 * indent + " ".join(args)) | lines.append(" " * 6 * indent + " ".join(args)) | ||||
| get = lambda code: self._get_tree(code, lines, marker, indent + 1) | |||||
| mark = lambda: lines.append(marker) | |||||
| def get(code): | |||||
| return self._get_tree(code, lines, marker, indent + 1) | |||||
| def mark(): | |||||
| return lines.append(marker) | |||||
| for node in code.nodes: | for node in code.nodes: | ||||
| node.__showtree__(write, get, mark) | node.__showtree__(write, get, mark) | ||||
| return lines | return lines | ||||
| @@ -282,12 +289,13 @@ class Wikicode(StringMixIn): | |||||
| This is equivalent to :meth:`{1}` with *forcetype* set to | This is equivalent to :meth:`{1}` with *forcetype* set to | ||||
| :class:`~{2.__module__}.{2.__name__}`. | :class:`~{2.__module__}.{2.__name__}`. | ||||
| """ | """ | ||||
| make_ifilter = lambda ftype: ( | |||||
| lambda self, *a, **kw: self.ifilter(forcetype=ftype, *a, **kw) | |||||
| ) | |||||
| make_filter = lambda ftype: ( | |||||
| lambda self, *a, **kw: self.filter(forcetype=ftype, *a, **kw) | |||||
| ) | |||||
| def make_ifilter(ftype): | |||||
| return lambda self, *a, **kw: self.ifilter(forcetype=ftype, *a, **kw) | |||||
| def make_filter(ftype): | |||||
| return lambda self, *a, **kw: self.filter(forcetype=ftype, *a, **kw) | |||||
| for name, ftype in meths.items(): | for name, ftype in meths.items(): | ||||
| ifilt = make_ifilter(ftype) | ifilt = make_ifilter(ftype) | ||||
| filt = make_filter(ftype) | filt = make_filter(ftype) | ||||
| @@ -312,12 +320,10 @@ class Wikicode(StringMixIn): | |||||
| self._nodes = value | self._nodes = value | ||||
| @overload | @overload | ||||
| def get(self, index: int) -> Node: | |||||
| ... | |||||
| def get(self, index: int) -> Node: ... | |||||
| @overload | @overload | ||||
| def get(self, index: slice) -> list[Node]: | |||||
| ... | |||||
| def get(self, index: slice) -> list[Node]: ... | |||||
| def get(self, index): | def get(self, index): | ||||
| """Return the *index*\\ th node within the list of nodes.""" | """Return the *index*\\ th node within the list of nodes.""" | ||||
| @@ -644,9 +650,12 @@ class Wikicode(StringMixIn): | |||||
| :class:`.Heading` object will be included; otherwise, this is skipped. | :class:`.Heading` object will be included; otherwise, this is skipped. | ||||
| """ | """ | ||||
| title_matcher = self._build_matcher(matches, flags) | title_matcher = self._build_matcher(matches, flags) | ||||
| matcher = lambda heading: ( | |||||
| title_matcher(heading.title) and (not levels or heading.level in levels) | |||||
| ) | |||||
| def matcher(heading): | |||||
| return title_matcher(heading.title) and ( | |||||
| not levels or heading.level in levels | |||||
| ) | |||||
| iheadings = self._indexed_ifilter(recursive=False, forcetype=Heading) | iheadings = self._indexed_ifilter(recursive=False, forcetype=Heading) | ||||
| sections = [] # Tuples of (index_of_first_node, section) | sections = [] # Tuples of (index_of_first_node, section) | ||||
| # Tuples of (index, heading), where index and heading.level are both | # Tuples of (index, heading), where index and heading.level are both | ||||
| @@ -32,8 +32,13 @@ from mwparserfromhell.nodes import ( | |||||
| from mwparserfromhell.smart_list import SmartList | from mwparserfromhell.smart_list import SmartList | ||||
| from mwparserfromhell.wikicode import Wikicode | from mwparserfromhell.wikicode import Wikicode | ||||
| wrap = lambda L: Wikicode(SmartList(L)) | |||||
| wraptext = lambda *args: wrap([Text(t) for t in args]) | |||||
| def wrap(L): | |||||
| return Wikicode(SmartList(L)) | |||||
| def wraptext(*args): | |||||
| return wrap([Text(t) for t in args]) | |||||
| def _assert_node_equal(expected, actual): | def _assert_node_equal(expected, actual): | ||||
| @@ -49,8 +54,7 @@ def _assert_node_equal(expected, actual): | |||||
| Text: _assert_text_node_equal, | Text: _assert_text_node_equal, | ||||
| Wikilink: _assert_wikilink_node_equal, | Wikilink: _assert_wikilink_node_equal, | ||||
| } | } | ||||
| # pylint: disable=unidiomatic-typecheck | |||||
| assert type(expected) == type(actual) | |||||
| assert type(expected) is type(actual) | |||||
| registry[type(expected)](expected, actual) | registry[type(expected)](expected, actual) | ||||
| @@ -63,8 +63,13 @@ def test_showtree(): | |||||
| """test Argument.__showtree__()""" | """test Argument.__showtree__()""" | ||||
| output = [] | output = [] | ||||
| getter, marker = object(), object() | getter, marker = object(), object() | ||||
| get = lambda code: output.append((getter, code)) | |||||
| mark = lambda: output.append(marker) | |||||
| def get(code): | |||||
| return output.append((getter, code)) | |||||
| def mark(): | |||||
| return output.append(marker) | |||||
| node1 = Argument(wraptext("foobar")) | node1 = Argument(wraptext("foobar")) | ||||
| node2 = Argument(wraptext("foo"), wraptext("bar")) | node2 = Argument(wraptext("foo"), wraptext("bar")) | ||||
| node1.__showtree__(output.append, get, mark) | node1.__showtree__(output.append, get, mark) | ||||
| @@ -74,8 +74,13 @@ def test_showtree(): | |||||
| """test ExternalLink.__showtree__()""" | """test ExternalLink.__showtree__()""" | ||||
| output = [] | output = [] | ||||
| getter, marker = object(), object() | getter, marker = object(), object() | ||||
| get = lambda code: output.append((getter, code)) | |||||
| mark = lambda: output.append(marker) | |||||
| def get(code): | |||||
| return output.append((getter, code)) | |||||
| def mark(): | |||||
| return output.append(marker) | |||||
| node1 = ExternalLink(wraptext("http://example.com"), brackets=False) | node1 = ExternalLink(wraptext("http://example.com"), brackets=False) | ||||
| node2 = ExternalLink(wraptext("http://example.com"), wraptext("Link")) | node2 = ExternalLink(wraptext("http://example.com"), wraptext("Link")) | ||||
| node1.__showtree__(output.append, get, mark) | node1.__showtree__(output.append, get, mark) | ||||
| @@ -55,7 +55,10 @@ def test_showtree(): | |||||
| """test Heading.__showtree__()""" | """test Heading.__showtree__()""" | ||||
| output = [] | output = [] | ||||
| getter = object() | getter = object() | ||||
| get = lambda code: output.append((getter, code)) | |||||
| def get(code): | |||||
| return output.append((getter, code)) | |||||
| node1 = Heading(wraptext("foobar"), 3) | node1 = Heading(wraptext("foobar"), 3) | ||||
| node2 = Heading(wraptext(" baz "), 4) | node2 = Heading(wraptext(" baz "), 4) | ||||
| node1.__showtree__(output.append, get, None) | node1.__showtree__(output.append, get, None) | ||||
| @@ -184,7 +184,7 @@ def test_normalize(): | |||||
| assert "\xa0" == node1.normalize() | assert "\xa0" == node1.normalize() | ||||
| assert "k" == node2.normalize() | assert "k" == node2.normalize() | ||||
| assert "é" == node3.normalize() | assert "é" == node3.normalize() | ||||
| assert "\U0001F648" == node4.normalize() | |||||
| assert "\U0001f648" == node4.normalize() | |||||
| with pytest.raises(ValueError): | with pytest.raises(ValueError): | ||||
| node5.normalize() | node5.normalize() | ||||
| with pytest.raises(ValueError): | with pytest.raises(ValueError): | ||||
| @@ -216,7 +216,7 @@ def test_other_methods(): | |||||
| assert 0 == str1.count("r", 5, 7) | assert 0 == str1.count("r", 5, 7) | ||||
| str3 = _FakeString("𐌲𐌿𐍄") | str3 = _FakeString("𐌲𐌿𐍄") | ||||
| actual = b"\xF0\x90\x8C\xB2\xF0\x90\x8C\xBF\xF0\x90\x8D\x84" | |||||
| actual = b"\xf0\x90\x8c\xb2\xf0\x90\x8c\xbf\xf0\x90\x8d\x84" | |||||
| assert b"fake string" == str1.encode() | assert b"fake string" == str1.encode() | ||||
| assert actual == str3.encode("utf-8") | assert actual == str3.encode("utf-8") | ||||
| assert actual == str3.encode(encoding="utf-8") | assert actual == str3.encode(encoding="utf-8") | ||||
| @@ -293,7 +293,7 @@ def test_other_methods(): | |||||
| str12 = _FakeString("123") | str12 = _FakeString("123") | ||||
| str13 = _FakeString("\u2155") | str13 = _FakeString("\u2155") | ||||
| str14 = _FakeString("\u00B2") | |||||
| str14 = _FakeString("\u00b2") | |||||
| assert str9.isdecimal() is False | assert str9.isdecimal() is False | ||||
| assert str12.isdecimal() is True | assert str12.isdecimal() is True | ||||
| assert str13.isdecimal() is False | assert str13.isdecimal() is False | ||||
| @@ -28,11 +28,25 @@ from mwparserfromhell.nodes import Tag, Template, Text | |||||
| from mwparserfromhell.nodes.extras import Attribute | from mwparserfromhell.nodes.extras import Attribute | ||||
| from .conftest import assert_wikicode_equal, wrap, wraptext | from .conftest import assert_wikicode_equal, wrap, wraptext | ||||
| agen = lambda name, value: Attribute(wraptext(name), wraptext(value)) | |||||
| agennv = lambda name: Attribute(wraptext(name)) | |||||
| agennq = lambda name, value: Attribute(wraptext(name), wraptext(value), None) | |||||
| agenp = lambda name, v, a, b, c: Attribute(wraptext(name), v, '"', a, b, c) | |||||
| agenpnv = lambda name, a, b, c: Attribute(wraptext(name), None, '"', a, b, c) | |||||
| def agen(name, value): | |||||
| return Attribute(wraptext(name), wraptext(value)) | |||||
| def agennv(name): | |||||
| return Attribute(wraptext(name)) | |||||
| def agennq(name, value): | |||||
| return Attribute(wraptext(name), wraptext(value), None) | |||||
| def agenp(name, v, a, b, c): | |||||
| return Attribute(wraptext(name), v, '"', a, b, c) | |||||
| def agenpnv(name, a, b, c): | |||||
| return Attribute(wraptext(name), None, '"', a, b, c) | |||||
| def test_str(): | def test_str(): | ||||
| @@ -112,8 +126,13 @@ def test_showtree(): | |||||
| """test Tag.__showtree__()""" | """test Tag.__showtree__()""" | ||||
| output = [] | output = [] | ||||
| getter, marker = object(), object() | getter, marker = object(), object() | ||||
| get = lambda code: output.append((getter, code)) | |||||
| mark = lambda: output.append(marker) | |||||
| def get(code): | |||||
| return output.append((getter, code)) | |||||
| def mark(): | |||||
| return output.append(marker) | |||||
| node1 = Tag( | node1 = Tag( | ||||
| wraptext("ref"), wraptext("text"), [agen("name", "foo"), agennv("selected")] | wraptext("ref"), wraptext("text"), [agen("name", "foo"), agennv("selected")] | ||||
| ) | ) | ||||
| @@ -31,8 +31,13 @@ from mwparserfromhell.nodes.extras import Parameter | |||||
| from mwparserfromhell import parse | from mwparserfromhell import parse | ||||
| from .conftest import assert_wikicode_equal, wrap, wraptext | from .conftest import assert_wikicode_equal, wrap, wraptext | ||||
| pgens = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=True) | |||||
| pgenh = lambda k, v: Parameter(wraptext(k), wraptext(v), showkey=False) | |||||
| def pgens(k, v): | |||||
| return Parameter(wraptext(k), wraptext(v), showkey=True) | |||||
| def pgenh(k, v): | |||||
| return Parameter(wraptext(k), wraptext(v), showkey=False) | |||||
| def test_str(): | def test_str(): | ||||
| @@ -91,8 +96,13 @@ def test_showtree(): | |||||
| """test Template.__showtree__()""" | """test Template.__showtree__()""" | ||||
| output = [] | output = [] | ||||
| getter, marker = object(), object() | getter, marker = object(), object() | ||||
| get = lambda code: output.append((getter, code)) | |||||
| mark = lambda: output.append(marker) | |||||
| def get(code): | |||||
| return output.append((getter, code)) | |||||
| def mark(): | |||||
| return output.append(marker) | |||||
| node1 = Template(wraptext("foobar")) | node1 = Template(wraptext("foobar")) | ||||
| node2 = Template(wraptext("foo"), [pgenh("1", "bar"), pgens("abc", "def")]) | node2 = Template(wraptext("foo"), [pgenh("1", "bar"), pgens("abc", "def")]) | ||||
| node1.__showtree__(output.append, get, mark) | node1.__showtree__(output.append, get, mark) | ||||
| @@ -404,10 +414,7 @@ def test_update(): | |||||
| node2.update({"1": "b"}, showkey=False) | node2.update({"1": "b"}, showkey=False) | ||||
| assert "{{a|b}}" == node2 | assert "{{a|b}}" == node2 | ||||
| node3 = Template(wraptext("a\n"), [ | |||||
| pgens("b ", "c\n"), | |||||
| pgens("d ", " e") | |||||
| ]) | |||||
| node3 = Template(wraptext("a\n"), [pgens("b ", "c\n"), pgens("d ", " e")]) | |||||
| node3.update({"b ": "f"}, preserve_spacing=False) | node3.update({"b ": "f"}, preserve_spacing=False) | ||||
| assert "{{a\n|b =f|d = e}}" == node3 | assert "{{a\n|b =f|d = e}}" == node3 | ||||
| @@ -276,7 +276,10 @@ def _test_search(meth, expected): | |||||
| def test_insert_before(): | def test_insert_before(): | ||||
| """test Wikicode.insert_before()""" | """test Wikicode.insert_before()""" | ||||
| meth = lambda code, *args, **kw: code.insert_before(*args, **kw) | |||||
| def meth(code, *args, **kw): | |||||
| return code.insert_before(*args, **kw) | |||||
| expected = [ | expected = [ | ||||
| "{{a}}xz{{b}}{{c}}[[y]]{{d}}{{e}}", | "{{a}}xz{{b}}{{c}}[[y]]{{d}}{{e}}", | ||||
| "d{{a}}cd{{a}}d{{a}}f{{b}}f{{b}}ef{{b}}", | "d{{a}}cd{{a}}d{{a}}f{{b}}f{{b}}ef{{b}}", | ||||
| @@ -293,7 +296,10 @@ def test_insert_before(): | |||||
| def test_insert_after(): | def test_insert_after(): | ||||
| """test Wikicode.insert_after()""" | """test Wikicode.insert_after()""" | ||||
| meth = lambda code, *args, **kw: code.insert_after(*args, **kw) | |||||
| def meth(code, *args, **kw): | |||||
| return code.insert_after(*args, **kw) | |||||
| expected = [ | expected = [ | ||||
| "{{a}}{{b}}xz{{c}}{{d}}[[y]]{{e}}", | "{{a}}{{b}}xz{{c}}{{d}}[[y]]{{e}}", | ||||
| "{{a}}d{{a}}dc{{a}}d{{b}}f{{b}}f{{b}}fe", | "{{a}}d{{a}}dc{{a}}d{{b}}f{{b}}f{{b}}fe", | ||||
| @@ -310,7 +316,10 @@ def test_insert_after(): | |||||
| def test_replace(): | def test_replace(): | ||||
| """test Wikicode.replace()""" | """test Wikicode.replace()""" | ||||
| meth = lambda code, *args, **kw: code.replace(*args, **kw) | |||||
| def meth(code, *args, **kw): | |||||
| return code.replace(*args, **kw) | |||||
| expected = [ | expected = [ | ||||
| "{{a}}xz[[y]]{{e}}", | "{{a}}xz[[y]]{{e}}", | ||||
| "dcdffe", | "dcdffe", | ||||
| @@ -341,7 +350,10 @@ def test_append(): | |||||
| def test_remove(): | def test_remove(): | ||||
| """test Wikicode.remove()""" | """test Wikicode.remove()""" | ||||
| meth = lambda code, obj, value, **kw: code.remove(obj, **kw) | |||||
| def meth(code, obj, value, **kw): | |||||
| return code.remove(obj, **kw) | |||||
| expected = [ | expected = [ | ||||
| "{{a}}{{c}}", | "{{a}}{{c}}", | ||||
| "", | "", | ||||
| @@ -395,7 +407,8 @@ def test_filter_family(): | |||||
| assert isinstance(gen, GeneratorType) | assert isinstance(gen, GeneratorType) | ||||
| return list(gen) | return list(gen) | ||||
| ifilter = lambda code: (lambda *a, **k: genlist(code.ifilter(*a, **k))) | |||||
| def ifilter(code): | |||||
| return lambda *a, **k: genlist(code.ifilter(*a, **k)) | |||||
| code = parse("a{{b}}c[[d]]{{{e}}}{{f}}[[g]]") | code = parse("a{{b}}c[[d]]{{{e}}}{{f}}[[g]]") | ||||
| for func in (code.filter, ifilter(code)): | for func in (code.filter, ifilter(code)): | ||||
| @@ -63,8 +63,13 @@ def test_showtree(): | |||||
| """test Wikilink.__showtree__()""" | """test Wikilink.__showtree__()""" | ||||
| output = [] | output = [] | ||||
| getter, marker = object(), object() | getter, marker = object(), object() | ||||
| get = lambda code: output.append((getter, code)) | |||||
| mark = lambda: output.append(marker) | |||||
| def get(code): | |||||
| return output.append((getter, code)) | |||||
| def mark(): | |||||
| return output.append(marker) | |||||
| node1 = Wikilink(wraptext("foobar")) | node1 = Wikilink(wraptext("foobar")) | ||||
| node2 = Wikilink(wraptext("foo"), wraptext("bar")) | node2 = Wikilink(wraptext("foo"), wraptext("bar")) | ||||
| node1.__showtree__(output.append, get, mark) | node1.__showtree__(output.append, get, mark) | ||||