SF.net SVN: docutils:[10286 ] trunk/docutils
milde--- via Docutils-checkins <[email protected]> Wed, 07 Jan 2026 13:40:45 +0000
| Newsgroups | gmane.text.docutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
Revision: 10286
http://sourceforge.net/p/docutils/code/10286
Author: milde
Date: 2026-01-07 13:40:45 +0000 (Wed, 07 Jan 2026)
Log Message:
-----------
nodes.Element.findall() now accepts also a tuple of types as condition.
The "condition" argument to the may also be a tuple of node classes
It is converted to ``isinstance(node, class_or_tuple)``.
Modified Paths:
--------------
trunk/docutils/HISTORY.rst
trunk/docutils/docutils/nodes.py
trunk/docutils/test/test_nodes.py
Modified: trunk/docutils/HISTORY.rst
===================================================================
--- trunk/docutils/HISTORY.rst 2026-01-07 07:52:49 UTC (rev 10285)
+++ trunk/docutils/HISTORY.rst 2026-01-07 13:40:45 UTC (rev 10286)
@@ -51,6 +51,10 @@
- Ensure `FileInput.read()` returns a `str` (decode if `source.read`
returns `bytes`. Fixes bug #514.
+* docutils/nodes.py
+
+ - Element.findall() now accepts also a tuple of types as condition.
+
* docutils/parsers/rst/directives/body.py,
docutils/parsers/rst/directives/parts.py
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2026-01-07 07:52:49 UTC (rev 10285)
+++ trunk/docutils/docutils/nodes.py 2026-01-07 13:40:45 UTC (rev 10286)
@@ -245,7 +245,7 @@
visitor.dispatch_departure(self)
return stop
- def _fast_findall(self, cls: type) -> Iterator:
+ def _fast_findall(self, cls: type|tuple[type]) -> Iterator:
"""Return iterator that only supports instance checks."""
if isinstance(self, cls):
yield self
@@ -262,7 +262,7 @@
yield from child._superfast_findall()
def findall(self,
- condition: type | Callable[[Node], bool] | None = None,
+ condition: type|tuple[type]|Callable[[Node], bool]|None = None,
include_self: bool = True,
descend: bool = True,
siblings: bool = False,
@@ -279,9 +279,9 @@
their descendants (if also `descend` is true), and so on.
If `condition` is not None, the iterator yields only nodes
- for which ``condition(node)`` is true. If `condition` is a
- type ``cls``, it is equivalent to a function consisting
- of ``return isinstance(node, cls)``.
+ for which ``condition(node)`` is true.
+ If `condition` is a type (or tuple of types) ``cls``, it is equivalent
+ to a function consisting of ``return isinstance(node, cls)``.
If `ascend` is true, assume `siblings` to be true as well.
@@ -314,16 +314,16 @@
if condition is None:
yield from self._superfast_findall()
return
- elif isinstance(condition, type):
+ elif isinstance(condition, (type, tuple)):
yield from self._fast_findall(condition)
return
# Check if `condition` is a class (check for TypeType for Python
# implementations that use only new-style classes, like PyPy).
- if isinstance(condition, type):
- node_class = condition
+ if isinstance(condition, (type, tuple)):
+ class_or_tuple = condition
- def condition(node, node_class=node_class):
- return isinstance(node, node_class)
+ def condition(node, class_or_tuple=class_or_tuple):
+ return isinstance(node, class_or_tuple)
if include_self and (condition is None or condition(self)):
yield self
@@ -349,13 +349,14 @@
else:
node = node.parent
- def traverse(self,
- condition: type | Callable[[Node], bool] | None = None,
- include_self: bool = True,
- descend: bool = True,
- siblings: bool = False,
- ascend: bool = False,
- ) -> list:
+ def traverse(
+ self,
+ condition: type|tuple[type]|Callable[[Node], bool]|None = None,
+ include_self: bool = True,
+ descend: bool = True,
+ siblings: bool = False,
+ ascend: bool = False,
+ ) -> list:
"""Return list of nodes following `self`.
For looping, Node.findall() is faster and more memory efficient.
@@ -366,13 +367,14 @@
return list(self.findall(condition, include_self, descend,
siblings, ascend))
- def next_node(self,
- condition: type | Callable[[Node], bool] | None = None,
- include_self: bool = False,
- descend: bool = True,
- siblings: bool = False,
- ascend: bool = False,
- ) -> Node | None:
+ def next_node(
+ self,
+ condition: type|tuple[type]|Callable[[Node], bool]|None = None,
+ include_self: bool = False,
+ descend: bool = True,
+ siblings: bool = False,
+ ascend: bool = False,
+ ) -> Node | None:
"""
Return the first node in the iterator returned by findall(),
or None if the iterable is empty.
Modified: trunk/docutils/test/test_nodes.py
===================================================================
--- trunk/docutils/test/test_nodes.py 2026-01-07 07:52:49 UTC (rev 10285)
+++ trunk/docutils/test/test_nodes.py 2026-01-07 13:40:45 UTC (rev 10286)
@@ -58,6 +58,7 @@
self.assertEqual(list(e[0].findall()),
[e[0], e[0][0], e[0][1], e[0][1][0]])
self.testlist = [e[0][0], e[0][1]]
+ # Condition is function returning a boolean, class or tuple of classes:
self.assertEqual(list(e[0].findall(condition=self.not_in_testlist)),
[e[0], e[0][1][0]])
self.testlist.append(e[0][1][0])
@@ -64,6 +65,8 @@
self.assertEqual(list(e[0].findall(condition=self.not_in_testlist)),
[e[0]])
self.assertEqual(list(e.findall(nodes.TextElement)), [e[0][1]])
+ self.assertEqual(list(e.findall((nodes.TextElement, nodes.Text))),
+ [e[0][1], e[0][1][0]])
def test_findall_duplicate_texts(self):
e = nodes.Element()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.