SF.net SVN: docutils:[9526 ] trunk/docutils/docutils/u tils/math
milde--- via Docutils-checkins <[email protected]>
| Newsgroups | gmane.text.docutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
Revision: 9526
http://sourceforge.net/p/docutils/code/9526
Author: milde
Date: 2024-02-01 13:02:23 +0000 (Thu, 01 Feb 2024)
Log Message:
-----------
Make MathML element children interface compatible to xml.etree.
List access via `__setitem__()`, `__getitem__()`, `__delitem__()`,
__pop__()`, `__iter__()`.
Use the new interface for cleaner code.
Modified Paths:
--------------
trunk/docutils/docutils/utils/math/latex2mathml.py
trunk/docutils/docutils/utils/math/mathml_elements.py
Modified: trunk/docutils/docutils/utils/math/latex2mathml.py
===================================================================
--- trunk/docutils/docutils/utils/math/latex2mathml.py 2024-02-01 13:02:12 UTC (rev 9525)
+++ trunk/docutils/docutils/utils/math/latex2mathml.py 2024-02-01 13:02:23 UTC (rev 9526)
@@ -569,8 +569,8 @@
# characters with a special meaning in LaTeX math mode
# fix spacing before "unary" minus.
attributes = {}
- if c == '-' and node.children:
- previous_node = node.children[-1]
+ if c == '-' and len(node):
+ previous_node = node[-1]
if (getattr(previous_node, 'data', '-') in '([='
or previous_node.get('class') == 'mathopen'):
attributes['form'] = 'prefix'
@@ -885,7 +885,7 @@
new_node = munderover(base)
sub_node = parse_latex_math(mrow(), subscript)
if len(sub_node) == 1:
- sub_node = sub_node.children[0]
+ sub_node = sub_node[0]
new_node.append(sub_node)
else:
new_node = mover(base)
@@ -897,7 +897,7 @@
new_node.nchildren = None
if isinstance(node, mrow) and len(node) == 0:
# replace node with new_node
- node.parent.children[node.parent.children.index(node)] = new_node
+ node.parent[node.parent.children.index(node)] = new_node
new_node.parent = node.parent
elif node.__class__.__name__ == 'math':
node.append(new_node)
@@ -997,7 +997,7 @@
def handle_script_or_limit(node, c, limits=''):
"""Append script or limit element to `node`."""
- child = node.children.pop()
+ child = node.pop()
if limits == 'limits':
child.set('movablelimits', 'false')
elif (limits == 'movablelimits'
@@ -1006,9 +1006,9 @@
if c == '_':
if isinstance(child, mover):
- new_node = munderover(*child.children, switch=True)
+ new_node = munderover(*child, switch=True)
elif isinstance(child, msup):
- new_node = msubsup(*child.children, switch=True)
+ new_node = msubsup(*child, switch=True)
elif (limits in ('limits', 'movablelimits')
or limits == '' and child.get('movablelimits', None)):
new_node = munder(child)
@@ -1016,9 +1016,9 @@
new_node = msub(child)
elif c == '^':
if isinstance(child, munder):
- new_node = munderover(*child.children)
+ new_node = munderover(*child)
elif isinstance(child, msub):
- new_node = msubsup(*child.children)
+ new_node = msubsup(*child)
elif (limits in ('limits', 'movablelimits')
or limits == '' and child.get('movablelimits', None)):
new_node = mover(child)
Modified: trunk/docutils/docutils/utils/math/mathml_elements.py
===================================================================
--- trunk/docutils/docutils/utils/math/mathml_elements.py 2024-02-01 13:02:12 UTC (rev 9525)
+++ trunk/docutils/docutils/utils/math/mathml_elements.py 2024-02-01 13:02:23 UTC (rev 9526)
@@ -83,7 +83,7 @@
self.attrib = {k.lower(): self.a_str(v)
for k, v in attributes.items()}
self.children = []
- self += children
+ self.extend(children)
@staticmethod
def a_str(v):
@@ -93,7 +93,7 @@
return str(v)
def __repr__(self):
- content = [repr(item) for item in self.children]
+ content = [repr(item) for item in self]
if hasattr(self, 'data'):
content.append(repr(self.data))
if getattr(self, 'switch', None):
@@ -101,10 +101,10 @@
content += [f'{k}={v!r}' for k, v in self.items() if v is not None]
return self.__class__.__name__ + '(%s)' % ', '.join(content)
- def __len__(self):
- return len(self.children)
+# Emulate dictionary access methods for attributes
+# and list-like interface to the child elements
+# (differs from `docutils.nodes.Element` dict/list interface).
- # emulate dictionary access methods for attributes
def get(self, key, default=None):
return self.attrib.get(key, default)
@@ -120,38 +120,67 @@
yield child
yield from child.subnodes()
+ def __len__(self):
+ return len(self.children)
+
+ def __getitem__(self, key):
+ return self.children.__getitem__(key)
+
+ def __setitem__(self, key, element):
+ element.parent = self
+ self.children.__setitem__(key, element)
+
+ def __delitem__(self, key):
+ self.children.__delitem__(key)
+
+ def __iter__(self):
+ return self.children.__iter__()
+
def full(self):
"""Return boolean indicating whether children may be appended."""
return self.nchildren is not None and len(self) >= self.nchildren
def close(self):
- """Close element and return first non-full parent or None."""
+ """Close element and return first non-full anchestor or None."""
+ self.nchildren = len(self) # mark node as full
parent = self.parent
while parent is not None and parent.full():
parent = parent.parent
return parent
- def append(self, child):
- """Append child and return self or first non-full parent.
+ def append(self, element):
+ """Append `element` and return new "current node" (insertion point).
- If self is full, go up the tree and return first non-full node or
- `None`.
+ Append as child element and set the internal `parent` attribute.
+
+ If self is already full, raise TypeError.
+
+ If self is full after appending, call `self.close()`
+ (returns first non-full anchestor or None) else return `self`.
"""
if self.full():
- raise TypeError(f'Element {self} already full!')
- self.children.append(child)
- child.parent = self
+ raise TypeError(f'Element "{self}" already full!')
+ self.children.append(element)
+ element.parent = self
if self.full():
return self.close()
return self
- def extend(self, children):
- for child in children:
- self.append(child)
- return self
+ def extend(self, elements):
+ """Sequentially append `elements`. Return new "current node".
- __iadd__ = extend # alias for ``+=`` operator
+ Raise TypeError if overfull.
+ """
+ current_node = self
+ for element in elements:
+ current_node = self.append(element)
+ return current_node
+ def pop(self, index=-1):
+ element = self[index]
+ del self[index]
+ return element
+
def is_block(self):
"""Return true, if `self` or a parent has ``display='block'``."""
try:
@@ -194,8 +223,7 @@
# '<math>\n <mn>2</mn>\n</math>'
# >>> len(n2)
# 1
-# >>> n2 += [mo('!')]
-# >>> n2
+# >>> n2.extend([mo('!')])
# math(mn(2), mo('!'))
# >>> eq3 = math(id='eq3', display='block')
# >>> eq3
@@ -248,16 +276,26 @@
self.switch = kwargs.pop('switch', False)
math.__init__(self, *children, **kwargs)
- def append(self, child):
- current_node = super().append(child)
- # normalize order if full
+ def append(self, element):
+ """Append element. Normalize order and close if full."""
+ current_node = super().append(element)
if self.switch and self.full():
- self.children[-1], self.children[-2] = \
- self.children[-2], self.children[-1]
+ self[-1], self[-2] = self[-2], self[-1]
self.switch = False
return current_node
+# >>> MathSchema(switch=True, display=True)
+# MathSchema(switch=True, display='true')
+# >>> MathSchema(MathElement(), switch=True)
+# MathSchema(MathElement(), switch=True)
+# >>> MathSchema(MathElement(id='c1'), MathElement(id='c2'), switch=True)
+# MathSchema(MathElement(id='c2'), MathElement(id='c1'))
+# >>> MathSchema(MathElement(), MathElement(), MathElement())
+# Traceback (most recent call last):
+# ...
+# TypeError: Element "MathSchema(MathElement(), MathElement())" already full!
+
# Token elements represent the smallest units of mathematical notation which
# carry meaning.
@@ -355,10 +393,10 @@
"""
parent = self.parent
# replace `self` with single child
- if len(self) == 1:
- child = self.children[0]
+ if parent is not None and len(self) == 1:
+ child = self[0]
try:
- parent.children[parent.children.index(self)] = child
+ parent[parent.children.index(self)] = child
child.parent = parent
except (AttributeError, ValueError):
return None
@@ -457,7 +495,7 @@
# munder(mi('lim'), mo('-'), accent='false')
# >>> mu.append(mi('lim'))
# Traceback (most recent call last):
-# TypeError: Element munder(mi('lim'), mo('-'), accent='false') already full!
+# TypeError: Element "munder(mi('lim'), mo('-'), accent='false')" already full!
# >>> munder(mo('-'), mi('lim'), accent='false', switch=True).toprettyxml()
# '<munder accent="false">\n <mi>lim</mi>\n <mo>-</mo>\n</munder>'
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.