|
From: <mi...@us...> - 2025-05-13 20:49:29
|
Revision: 10128
http://sourceforge.net/p/docutils/code/10128
Author: milde
Date: 2025-05-13 20:49:24 +0000 (Tue, 13 May 2025)
Log Message:
-----------
Relax the transform handling transitions.
Report a WARNING instead of raising an AssertionError, if a
`<transition>` element's parent is neither `<document>` nor `<section>`.
This prevents errors with 3rd-party parsers or some (invalid)
Docutils-XML input.
Downgrade the system message reporting a `<transition>` at an
invalid position from ERROR to WARNING.
Insert the `<system_message>` *after* the transition (instead of before)
to prevent an infinite loop with `document.findall()`
Insert `<system_message>` element only if valid at this position.1
Dangling `<system_messages>` are collected and moved to a
system messages" section by the `universal.Messages` transform).
1This check can lead to overcautious behaviour if there are
other validity violations.
This is an implementation detail, we want to keep it simple.
Adapt "transition" transform tests. Add a test for transitions at
"strange" places (with Docutils-XML sample).
Modified Paths:
--------------
trunk/docutils/docutils/transforms/misc.py
trunk/docutils/test/test_transforms/test_transitions.py
Modified: trunk/docutils/docutils/transforms/misc.py
===================================================================
--- trunk/docutils/docutils/transforms/misc.py 2025-05-13 20:49:10 UTC (rev 10127)
+++ trunk/docutils/docutils/transforms/misc.py 2025-05-13 20:49:24 UTC (rev 10128)
@@ -101,20 +101,30 @@
index = node.parent.index(node)
previous_sibling = node.previous_sibling()
msg = ''
- assert isinstance(node.parent, (nodes.document, nodes.section))
- if index == 0 or isinstance(previous_sibling, (nodes.title,
- nodes.subtitle,
- nodes.meta,
- nodes.decoration)):
+ if not isinstance(node.parent, (nodes.document, nodes.section)):
+ msg = 'Transition must be child of <document> or <section>.'
+ elif index == 0 or isinstance(previous_sibling, (nodes.title,
+ nodes.subtitle,
+ nodes.meta,
+ nodes.decoration)):
msg = 'Document or section may not begin with a transition.'
elif isinstance(previous_sibling, nodes.transition):
msg = ('At least one body element must separate transitions; '
'adjacent transitions are not allowed.')
if msg:
- # Insert before node and update index.
- error = self.document.reporter.error(msg, base_node=node)
- node.parent.insert(index, error)
- index += 1
+ warning = self.document.reporter.warning(msg, base_node=node)
+ # Check, if it is valid to insert a body element
+ node.parent[index] = nodes.paragraph()
+ try:
+ node.parent.validate(recursive=False)
+ except nodes.ValidationError:
+ node.parent[index] = node
+ else:
+ node.parent[index] = node
+ node.parent.insert(index+1, warning)
+ index += 1
+ if not isinstance(node.parent, (nodes.document, nodes.section)):
+ return
assert index < len(node.parent)
if index != len(node.parent) - 1:
# No need to move the node.
@@ -124,14 +134,13 @@
# While sibling is the last node of its parent.
while index == len(sibling.parent) - 1:
sibling = sibling.parent
- # If sibling is the whole document (i.e. it has no parent).
- if sibling.parent is None:
+ if sibling.parent is None: # sibling is the top node (document)
# Transition at the end of document. Do not move the
- # transition up, and place an error behind.
- error = self.document.reporter.error(
- 'Document may not end with a transition.',
- line=node.line)
- node.parent.insert(node.parent.index(node) + 1, error)
+ # transition up, and place a warning behind.
+ warning = self.document.reporter.warning(
+ 'Document may not end with a transition.',
+ base_node=node)
+ node.parent.append(warning)
return
index = sibling.parent.index(sibling)
# Remove the original transition node.
Modified: trunk/docutils/test/test_transforms/test_transitions.py
===================================================================
--- trunk/docutils/test/test_transforms/test_transitions.py 2025-05-13 20:49:10 UTC (rev 10127)
+++ trunk/docutils/test/test_transforms/test_transitions.py 2025-05-13 20:49:24 UTC (rev 10128)
@@ -18,7 +18,7 @@
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from docutils.frontend import get_default_settings
-from docutils.parsers.rst import Parser
+from docutils.parsers import rst, docutils_xml
from docutils.transforms.misc import Transitions
from docutils.transforms.universal import TestMessages
from docutils.utils import new_document
@@ -25,9 +25,12 @@
class TransformTestCase(unittest.TestCase):
+
+ maxDiff = None
+
def test_transforms(self):
- parser = Parser()
- settings = get_default_settings(Parser)
+ parser = rst.Parser()
+ settings = get_default_settings(rst.Parser)
settings.warning_stream = ''
for name, (transforms, cases) in totest.items():
for casenum, (case_input, case_expected) in enumerate(cases):
@@ -42,9 +45,29 @@
output = document.pformat()
self.assertEqual(case_expected, output)
+ def test_transfroms_x(self):
+ # test samples given as Docutils XML in `totest_x`
+ # (for document trees that cannot be generated from rST)
+ parser = docutils_xml.Parser()
+ settings = get_default_settings(docutils_xml.Parser)
+ settings.warning_stream = ''
+ for name, (transforms, cases) in totest_x.items():
+ for casenum, (case_input, case_expected) in enumerate(cases):
+ with self.subTest(id=f'totest[{name!r}][{casenum}]'):
+ document = new_document('test data', settings.copy())
+ parser.parse(case_input, document)
+ # Don't do a ``populate_from_components()`` because that
+ # would enable the Transformer's default transforms.
+ document.transformer.add_transforms(transforms)
+ document.transformer.add_transform(TestMessages)
+ document.transformer.apply_transforms()
+ output = document.pformat()
+ self.assertEqual(case_expected, output)
-totest = {}
+totest = {} # rST samples and expected pseudoXML
+totest_x = {} # XML samples and expected pseudoXML
+
totest['transitions'] = ((Transitions,), [
["""\
Section 1
@@ -53,7 +76,7 @@
Subsection 1
------------
-Some text.
+A transition at the end of a section is moved behind the section.
----------
@@ -71,7 +94,7 @@
<title>
Subsection 1
<paragraph>
- Some text.
+ A transition at the end of a section is moved behind the section.
<transition>
<section ids="section-2" names="section\\ 2">
<title>
@@ -103,47 +126,51 @@
["""\
--------
-A section or document may not begin with a transition.
+A system message warns about invalid placement of transitions.
+""",
+"""\
+<document source="test data">
+ <transition>
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <paragraph>
+ A system message warns about invalid placement of transitions.
+"""],
+["""\
+The DTD specifies ...
-The DTD specifies that two transitions may not
-be adjacent:
-
--------
--------
---------
-
-The DTD also specifies that a section or document
-may not end with a transition.
-
---------
+... that two transitions may not be adjacent:
""",
"""\
<document source="test data">
- <system_message level="3" line="1" source="test data" type="ERROR">
- <paragraph>
- Document or section may not begin with a transition.
- <transition>
<paragraph>
- A section or document may not begin with a transition.
- <paragraph>
- The DTD specifies that two transitions may not
- be adjacent:
+ The DTD specifies ...
<transition>
- <system_message level="3" line="10" source="test data" type="ERROR">
- <paragraph>
- At least one body element must separate transitions; adjacent transitions are not allowed.
<transition>
- <system_message level="3" line="12" source="test data" type="ERROR">
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
At least one body element must separate transitions; adjacent transitions are not allowed.
- <transition>
<paragraph>
+ ... that two transitions may not be adjacent:
+"""],
+["""\
+The DTD also specifies that a section or document
+may not end with a transition.
+
+--------
+""",
+"""\
+<document source="test data">
+ <paragraph>
The DTD also specifies that a section or document
may not end with a transition.
<transition>
- <system_message level="3" line="17" source="test data" type="ERROR">
+ <system_message level="2" line="4" source="test data" type="WARNING">
<paragraph>
Document may not end with a transition.
"""],
@@ -155,13 +182,13 @@
----------
-The next transition is legal:
+Some text after transition.
-----------
-
Section 2
=========
+Some text before the transition.
+
----------
""",
"""\
@@ -171,21 +198,19 @@
<section ids="section-1" names="section\\ 1">
<title>
Section 1
- <system_message level="3" line="6" source="test data" type="ERROR">
+ <transition>
+ <system_message level="2" line="6" source="test data" type="WARNING">
<paragraph>
Document or section may not begin with a transition.
- <transition>
<paragraph>
- The next transition is legal:
- <transition>
+ Some text after transition.
<section ids="section-2" names="section\\ 2">
<title>
Section 2
- <system_message level="3" line="15" source="test data" type="ERROR">
- <paragraph>
- Document or section may not begin with a transition.
+ <paragraph>
+ Some text before the transition.
<transition>
- <system_message level="3" line="15" source="test data" type="ERROR">
+ <system_message level="2" line="15" source="test data" type="WARNING">
<paragraph>
Document may not end with a transition.
"""],
@@ -201,11 +226,11 @@
<paragraph>
A paragraph and two transitions.
<transition>
- <system_message level="3" line="5" source="test data" type="ERROR">
+ <transition>
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
At least one body element must separate transitions; adjacent transitions are not allowed.
- <transition>
- <system_message level="3" line="5" source="test data" type="ERROR">
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
Document may not end with a transition.
"""],
@@ -222,11 +247,11 @@
<paragraph>
A paragraph, two transitions, and a blank line.
<transition>
- <system_message level="3" line="5" source="test data" type="ERROR">
+ <transition>
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
At least one body element must separate transitions; adjacent transitions are not allowed.
- <transition>
- <system_message level="3" line="5" source="test data" type="ERROR">
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
Document may not end with a transition.
"""],
@@ -237,10 +262,10 @@
""",
"""\
<document source="test data">
- <system_message level="3" line="1" source="test data" type="ERROR">
+ <transition>
+ <system_message level="2" line="1" source="test data" type="WARNING">
<paragraph>
Document or section may not begin with a transition.
- <transition>
<paragraph>
Document beginning with a transition.
"""],
@@ -254,10 +279,10 @@
"""\
<document source="test data">
<meta content="transition test" name="keywords">
- <system_message level="3" line="3" source="test data" type="ERROR">
+ <transition>
+ <system_message level="2" line="3" source="test data" type="WARNING">
<paragraph>
Document or section may not begin with a transition.
- <transition>
<paragraph>
Document beginning with a transition (meta elements don't count).
"""],
@@ -274,10 +299,10 @@
<header>
<paragraph>
a header
- <system_message level="3" line="3" source="test data" type="ERROR">
+ <transition>
+ <system_message level="2" line="3" source="test data" type="WARNING">
<paragraph>
Document or section may not begin with a transition.
- <transition>
<paragraph>
Document beginning with a transition (decoration elements don't count).
"""],
@@ -291,10 +316,14 @@
----------
-Section 2
-=========
+Implementation Detail
+=====================
-Some text.
+If the element containing the transition is invalid after replacing the
+transition with a body element, the system_message is appended at the end
+of the document (by the "universal.Messages" transform).
+This check can lead to overcautious behaviour if there are other
+validity violations (here: several misplaced transitions).
""",
"""\
<document source="test data">
@@ -301,23 +330,27 @@
<section ids="section-1" names="section\\ 1">
<title>
Section 1
- <system_message level="3" line="4" source="test data" type="ERROR">
- <paragraph>
- Document or section may not begin with a transition.
<transition>
- <system_message level="3" line="6" source="test data" type="ERROR">
- <paragraph>
- At least one body element must separate transitions; adjacent transitions are not allowed.
<transition>
- <system_message level="3" line="8" source="test data" type="ERROR">
- <paragraph>
- At least one body element must separate transitions; adjacent transitions are not allowed.
<transition>
- <section ids="section-2" names="section\\ 2">
+ <section ids="implementation-detail" names="implementation\\ detail">
<title>
- Section 2
+ Implementation Detail
<paragraph>
- Some text.
+ If the element containing the transition is invalid after replacing the
+ transition with a body element, the system_message is appended at the end
+ of the document (by the "universal.Messages" transform).
+ This check can lead to overcautious behaviour if there are other
+ validity violations (here: several misplaced transitions).
+ <system_message level="2" line="4" source="test data" type="WARNING">
+ <paragraph>
+ Document or section may not begin with a transition.
+ <system_message level="2" line="6" source="test data" type="WARNING">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
+ <system_message level="2" line="8" source="test data" type="WARNING">
+ <paragraph>
+ At least one body element must separate transitions; adjacent transitions are not allowed.
"""],
["""\
----------
@@ -326,23 +359,25 @@
----------
""",
+# The placement of <system_message>s in this sample is an implementation
+# detail, see the remarks in the preceding test nr. 11.
"""\
<document source="test data">
- <system_message level="3" line="1" source="test data" type="ERROR">
+ <transition>
+ <transition>
+ <transition>
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
+ Document may not end with a transition.
+ <system_message level="2" line="1" source="test data" type="WARNING">
+ <paragraph>
Document or section may not begin with a transition.
- <transition>
- <system_message level="3" line="3" source="test data" type="ERROR">
+ <system_message level="2" line="3" source="test data" type="WARNING">
<paragraph>
At least one body element must separate transitions; adjacent transitions are not allowed.
- <transition>
- <system_message level="3" line="5" source="test data" type="ERROR">
+ <system_message level="2" line="5" source="test data" type="WARNING">
<paragraph>
At least one body element must separate transitions; adjacent transitions are not allowed.
- <transition>
- <system_message level="3" line="5" source="test data" type="ERROR">
- <paragraph>
- Document may not end with a transition.
"""],
["""\
A paragraph.
@@ -355,7 +390,7 @@
<paragraph>
A paragraph.
<transition>
- <system_message level="3" line="3" source="test data" type="ERROR">
+ <system_message level="2" line="3" source="test data" type="WARNING">
<paragraph>
Document may not end with a transition.
"""],
@@ -362,5 +397,47 @@
])
+totest_x['transitions extra'] = ((Transitions,), [
+# currently, a <transition> is only valid inside <document> or <section>
+["""\
+<document>
+ <paragraph>Some text.</paragraph>
+ <transition />
+ <paragraph>Some text.</paragraph>
+ <block_quote>
+ <paragraph>Some text.</paragraph>
+ <transition />
+ <paragraph>Some text.</paragraph>
+ </block_quote>
+ <paragraph>A <transition /> in a paragraph.</paragraph>
+</document>
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Some text.
+ <transition>
+ <paragraph>
+ Some text.
+ <block_quote>
+ <paragraph>
+ Some text.
+ <transition>
+ <system_message level="2" line="7" source="test data" type="WARNING">
+ <paragraph>
+ Transition must be child of <document> or <section>.
+ <paragraph>
+ Some text.
+ <paragraph>
+ A \n\
+ <transition>
+ in a paragraph.
+ <system_message level="2" line="10" source="test data" type="WARNING">
+ <paragraph>
+ Transition must be child of <document> or <section>.
+"""],
+])
+
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|