Browse Source

Docstrings for a good chunk of Wikicode.

tags/v0.1
Ben Kurtovic 12 years ago
parent
commit
ed6501344d
1 changed files with 83 additions and 12 deletions
  1. +83
    -12
      mwparserfromhell/wikicode.py

+ 83
- 12
mwparserfromhell/wikicode.py View File

@@ -44,21 +44,21 @@ class Wikicode(StringMixIn):
return "".join([str(node) for node in self.nodes])

def _get_children(self, node):
"""Iterate over all descendants of a given node, including itself.
"""Iterate over all descendants of a given *node*, including itself.

This is implemented by the __iternodes__() generator of Node classes,
which by default yields itself and nothing more.
This is implemented by the ``__iternodes__()`` generator of ``Node``
classes, which by default yields itself and nothing more.
"""
for context, child in node.__iternodes__(self._get_all_nodes):
yield child

def _get_context(self, node, obj):
"""Return a ``Wikicode`` that contains ``obj`` in its descendants.
"""Return a ``Wikicode`` that contains *obj* in its descendants.

The closest (shortest distance from ``node``) suitable ``Wikicode``
will be returned, or ``None`` if the ``obj`` is the ``node`` itself.
The closest (shortest distance from *node*) suitable ``Wikicode`` will
be returned, or ``None`` if the *obj* is the *node* itself.

Raises ``ValueError`` if ``obj`` is not within ``node``.
Raises ``ValueError`` if *obj* is not within *node*.
"""
for context, child in node.__iternodes__(self._get_all_nodes):
if child is obj:
@@ -76,7 +76,10 @@ class Wikicode(StringMixIn):
yield child

def _is_equivalent(self, obj, node):
"""Return ``True`` if obj and node are equivalent, otherwise ``False``.
"""Return ``True`` if *obj* and *node* are equivalent, else ``False``.

If *obj* is a ``Node``, the function will test whether they are the
same object, otherwise it will compare them with ``==``.
"""
if isinstance(obj, Node):
if node is obj:
@@ -87,16 +90,28 @@ class Wikicode(StringMixIn):
return False

def _contains(self, nodes, obj):
"""Return ``True`` if *obj* is inside of *nodes*, else ``False``.

If *obj* is a ``Node``, we will only return ``True`` if *obj* is
actually in the list (and not just a node that equals it). Otherwise,
the test is simply ``obj in nodes``.
"""
if isinstance(obj, Node):
for node in nodes:
if node is obj:
return True
else:
if obj in nodes:
return True
return False
return False
return obj in nodes

def _do_search(self, obj, recursive, callback, context, *args, **kwargs):
"""Look within *context* for *obj*, executing *callback* if found.

If *recursive* is ``True``, we'll look within context and its
descendants, otherwise we'll just execute callback. We raise
:py:exc:`ValueError` if *obj* isn't in our node list or context. If
found, *callback* is passed the context, the index of the node within
the context, and whatever were passed as ``*args`` and ``**kwargs``.
"""
if recursive:
for i, node in enumerate(context.nodes):
if self._is_equivalent(obj, node):
@@ -110,6 +125,16 @@ class Wikicode(StringMixIn):
callback(context, self.index(obj, recursive=False), *args, **kwargs)

def _get_tree(self, code, lines, marker, indent):
"""Build a tree to illustrate the way the Wikicode object was parsed.

The method that builds the actual tree is ``__showtree__`` of ``Node``
objects. *code* is the ``Wikicode`` object to build a tree for. *lines*
is the list to append the tree to, which is returned at the end of the
method. *marker* is some object to be used to indicate that the builder
should continue on from the last line instead of starting a new one; it
should be any object that can be tested for with ``is``. *indent* is
the starting indentation.
"""
def write(*args):
if lines and lines[-1] is marker: # Continue from the last line
lines.pop() # Remove the marker
@@ -126,6 +151,11 @@ class Wikicode(StringMixIn):

@property
def nodes(self):
"""A list of :py:class:`~mwparserfromhell.nodes.Node` objects.

This is the internal data actually stored within a
:py:class:`~mwparserfromhell.wikicode.Wikicode` object.
"""
return self._nodes

@nodes.setter
@@ -133,9 +163,18 @@ class Wikicode(StringMixIn):
self._nodes = value

def get(self, index):
"""Return the *index*\ th node within the list of nodes."""
return self.nodes[index]

def set(self, index, value):
"""Set the ``Node`` at *index* to *value*.

Raises :py:exc:`IndexError` if *index* is out of range, or
:py:exc:`ValueError` if *value* cannot be coerced into one
:py:class:`~mwparserfromhell.nodes.Node`. To insert multiple nodes at
an index, use :py:meth:`get` with either :py:meth:`remove` and
:py:meth:`insert` or :py:meth:`replace`.
"""
nodes = parse_anything(value).nodes
if len(nodes) > 1:
raise ValueError("Cannot coerce multiple nodes into one index")
@@ -146,6 +185,13 @@ class Wikicode(StringMixIn):
self.nodes[index] = nodes[0]

def index(self, obj, recursive=False):
"""Return the index of *obj* in the list of nodes.

Raises :py:exc:`ValueError` if *obj* is not found. If *recursive* is
``True``, we will look in all nodes of ours and their descendants, and
return the index of our direct descendant node within *our* list of
nodes. Otherwise, the lookup is done only on direct descendants.
"""
if recursive:
for i, node in enumerate(self.nodes):
if self._contains(self._get_children(node), obj):
@@ -158,15 +204,40 @@ class Wikicode(StringMixIn):
raise ValueError(obj)

def insert(self, index, value):
"""Insert *value* at *index* in the list of nodes.

*value* can be anything parasable by
:py:func:`mwparserfromhell.utils.parse_anything`, which includes
strings or other :py:class:`~mwparserfromhell.wikicode.Wikicode` or
:py:class:`~mwparserfromhell.nodes.Node` objects.
"""
nodes = parse_anything(value).nodes
for node in reversed(nodes):
self.nodes.insert(index, node)

def insert_before(self, obj, value, recursive=True):
"""Insert *value* immediately before *obj* in the list of nodes.

*value* can be anything parasable by
:py:func:`mwparserfromhell.utils.parse_anything`. If *recursive* is
``True``, we will try to find *obj* within our child nodes even if it
is not a direct descendant of this
:py:class:`~mwparserfromhell.wikicode.Wikicode` object. If *obj* is not
in the node list, :py:exc:`ValueError` is raised.
"""
callback = lambda self, i, value: self.insert(i, value)
self._do_search(obj, recursive, callback, self, value)

def insert_after(self, obj, value, recursive=True):
"""Insert *value* immediately after *obj* in the list of nodes.

*value* can be anything parasable by
:py:func:`mwparserfromhell.utils.parse_anything`. If *recursive* is
``True``, we will try to find *obj* within our child nodes even if it
is not a direct descendant of this
:py:class:`~mwparserfromhell.wikicode.Wikicode` object. If *obj* is not
in the node list, :py:exc:`ValueError` is raised.
"""
callback = lambda self, i, value: self.insert(i + 1, value)
self._do_search(obj, recursive, callback, self, value)



Loading…
Cancel
Save