SF.net SVN: docutils:[10312 ] trunk/docutils
milde--- via Docutils-checkins <[email protected]> Fri, 17 Apr 2026 17:54:15 +0000
| Newsgroups | gmane.text.docutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
Revision: 10312
http://sourceforge.net/p/docutils/code/10312
Author: milde
Date: 2026-04-17 17:54:14 +0000 (Fri, 17 Apr 2026)
Log Message:
-----------
Ensure and test backwards compatible auto-id-prefix behaviour.
Only derive IDs from duplicate names if the setting
"auto_id_prefix" ends in "%".
Sphinx still forces `auto_id_prefix = 'id"` and
`tests/test_intl/test_intl.py::test_xml_label_targets` failed
because an ID changed from "id1" to "explicit-target".
Add test cases for `auto_id_prefix = 'id"` and `legacy_ids = True`.
Modified Paths:
--------------
trunk/docutils/docutils/nodes.py
trunk/docutils/test/test_parsers/test_rst/test_targets.py
Modified: trunk/docutils/docutils/nodes.py
===================================================================
--- trunk/docutils/docutils/nodes.py 2026-04-10 07:39:10 UTC (rev 10311)
+++ trunk/docutils/docutils/nodes.py 2026-04-17 17:54:14 UTC (rev 10312)
@@ -2023,7 +2023,8 @@
# disambiguate name-derived ID
# TODO: remove second condition after announcing change
prefix = id + '-'
- elif node['dupnames'] and make_id(node['dupnames'][0]):
+ elif (node['dupnames'] and auto_id_prefix.endswith('%')
+ and make_id(node['dupnames'][0])):
prefix = make_id(node['dupnames'][0]) + '-'
else:
prefix = id_prefix + auto_id_prefix
Modified: trunk/docutils/test/test_parsers/test_rst/test_targets.py
===================================================================
--- trunk/docutils/test/test_parsers/test_rst/test_targets.py 2026-04-10 07:39:10 UTC (rev 10311)
+++ trunk/docutils/test/test_parsers/test_rst/test_targets.py 2026-04-17 17:54:14 UTC (rev 10312)
@@ -25,16 +25,19 @@
class ParserTestCase(unittest.TestCase):
maxDiff = None
+ mysettings = get_default_settings(Parser)
+ mysettings.legacy_ids = False # will become default in 2.0
+ mysettings.warning_stream = ''
def test_parser(self):
parser = Parser()
- settings = get_default_settings(Parser)
- settings.legacy_ids = False
- settings.warning_stream = ''
- for name, cases in totest.items():
+ for name, (settings_overrides, cases) in totest.items():
+ settings = self.mysettings.copy()
+ for k, v in settings_overrides.items():
+ setattr(settings, k, v)
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())
+ document = new_document('test data', settings)
parser.parse(case_input, document)
output = document.pformat()
self.assertEqual(case_expected, output)
@@ -42,7 +45,7 @@
totest = {}
-totest['targets'] = [
+totest['targets'] = ({}, [
["""\
.. _target:
@@ -523,10 +526,240 @@
<target ids="escaped-colon" names="escaped\\ colon:" refuri="OK">
<target ids="unescaped-colon-quoted" names="unescaped\\ colon,\\ quoted:" refuri="OK">
"""],
-]
+])
-totest['anonymous_targets'] = [
+
+# Backwards compatibiltiy IDs (default up to Docutils 2.0):
+totest['legacy-ids'] = ({'legacy_ids': True}, [
["""\
+Duplicate external targets (embedded/explicit, same URIs):
+
+See the `example <example.rst>`_
+
+See the example_
+
+.. _example: example.rst
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (embedded/explicit, same URIs):
+ <paragraph>
+ See the \n\
+ <reference name="example" refuri="example.rst">
+ example
+ <target ids="example" names="example" refuri="example.rst">
+ <paragraph>
+ See the \n\
+ <reference name="example" refname="example">
+ example
+ <system_message level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Duplicate name "example" for external target "example.rst".
+ <target dupnames="example" ids="example-1" refuri="example.rst">
+"""],
+["""\
+Duplicate implicit targets.
+
+Title
+=====
+
+Paragraph.
+
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+ <section dupnames="title" ids="title-1">
+ <title>
+ Title
+ <system_message backrefs="title-1" level="1" line="9" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "title".
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Duplicate implicit/explicit targets.
+
+Title
+=====
+
+.. _title:
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit/explicit targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <system_message level="1" line="6" source="test data" type="INFO">
+ <paragraph>
+ Target name overrides implicit target name "title".
+ <target ids="title-1" names="title">
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Duplicate implicit/directive targets.
+
+Title
+=====
+
+.. note:: remember remember
+ :name: title
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit/directive targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <note ids="title-1" names="title">
+ <system_message backrefs="title-1" level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Target name overrides implicit target name "title".
+ <paragraph>
+ remember remember
+"""],
+["""\
+Duplicate explicit targets.
+
+.. _title:
+
+First.
+
+.. _title:
+
+Second.
+
+.. _title:
+
+Third.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate explicit targets.
+ <target dupnames="title" ids="title">
+ <paragraph>
+ First.
+ <system_message level="2" line="7" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+ <target dupnames="title" ids="title-1">
+ <paragraph>
+ Second.
+ <system_message level="2" line="11" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+ <target dupnames="title" ids="title-2">
+ <paragraph>
+ Third.
+"""],
+["""\
+Duplicate targets:
+
+Target
+======
+
+Implicit section header target.
+
+.. [TARGET] Citation target.
+
+.. [#target] Autonumber-labeled footnote target.
+
+.. _target:
+
+Explicit internal target.
+
+.. _target: Explicit_external_target
+
+| Do not insert <system_message> element for duplicate
+| _`target`, if this results in an invalid doctree.
+
+.. rubric:: directive with target
+ :name: Target
+
+:field list: with
+:_`target`: in a field name
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate targets:
+ <section dupnames="target" ids="target">
+ <title>
+ Target
+ <paragraph>
+ Implicit section header target.
+ <citation dupnames="target" ids="target-1">
+ <label>
+ TARGET
+ <system_message backrefs="target-1" level="1" line="8" source="test data" type="INFO">
+ <paragraph>
+ Target name overrides implicit target name "target".
+ <paragraph>
+ Citation target.
+ <footnote auto="1" dupnames="target" ids="target-2">
+ <system_message backrefs="target-2" level="2" line="10" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <paragraph>
+ Autonumber-labeled footnote target.
+ <system_message level="2" line="12" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="target-3">
+ <paragraph>
+ Explicit internal target.
+ <system_message level="2" line="16" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="target-4" refuri="Explicit_external_target">
+ <line_block>
+ <line>
+ Do not insert <system_message> element for duplicate
+ <line>
+ <target dupnames="target" ids="target-5">
+ target
+ , if this results in an invalid doctree.
+ <rubric dupnames="target" ids="target-6">
+ directive with target
+ <field_list>
+ <field>
+ <field_name>
+ field list
+ <field_body>
+ <paragraph>
+ with
+ <field>
+ <field_name>
+ <target dupnames="target" ids="target-7">
+ target
+ <field_body>
+ <paragraph>
+ in a field name
+"""],
+])
+
+
+totest['anonymous_targets'] = ({}, [
+["""\
Anonymous external hyperlink target:
.. __: http://w3c.org/
@@ -633,8 +866,346 @@
<comment xml:space="preserve">
_
"""],
-]
+])
+# keep stable IDs with legacy auto-ID setting (still default in Sphinx)
+totest['legacy auto-id prefix'] = ({'auto_id_prefix': 'id',
+ 'legacy_ids': True}, [
+["""\
+Duplicate external targets (different URIs):
+
+.. _target: first
+
+.. _target: second
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (different URIs):
+ <target dupnames="target" ids="target" refuri="first">
+ <system_message level="2" line="5" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id1" refuri="second">
+"""],
+["""\
+Duplicate external targets (same URIs):
+
+.. _target: first
+
+.. _target: first
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (same URIs):
+ <target ids="target" names="target" refuri="first">
+ <system_message level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ Duplicate name "target" for external target "first".
+ <target dupnames="target" ids="id1" refuri="first">
+"""],
+["""\
+Duplicate external targets (embedded/explicit, same URIs):
+
+See the `example <example.rst>`_
+
+See the example_
+
+.. _example: example.rst
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate external targets (embedded/explicit, same URIs):
+ <paragraph>
+ See the \n\
+ <reference name="example" refuri="example.rst">
+ example
+ <target ids="example" names="example" refuri="example.rst">
+ <paragraph>
+ See the \n\
+ <reference name="example" refname="example">
+ example
+ <system_message level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Duplicate name "example" for external target "example.rst".
+ <target dupnames="example" ids="id1" refuri="example.rst">
+"""],
+["""\
+Duplicate indirect _`targets` (same refname):
+
+.. _link: targets_
+
+.. _link: targets_
+
+do not conflict. The reference name can be used in a link_.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate indirect \n\
+ <target ids="targets" names="targets">
+ targets
+ (same refname):
+ <target ids="link" names="link" refname="targets">
+ <system_message level="1" line="5" source="test data" type="INFO">
+ <paragraph>
+ Duplicate name "link" for external target "targets".
+ <target dupnames="link" ids="id1" refname="targets">
+ <paragraph>
+ do not conflict. The reference name can be used in a \n\
+ <reference name="link" refname="link">
+ link
+ .
+"""],
+["""\
+Duplicate implicit targets.
+
+Title
+=====
+
+Paragraph.
+
+Title
+=====
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <paragraph>
+ Paragraph.
+ <section dupnames="title" ids="id1">
+ <title>
+ Title
+ <system_message backrefs="id1" level="1" line="9" source="test data" type="INFO">
+ <paragraph>
+ Duplicate implicit target name: "title".
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Duplicate implicit/explicit targets.
+
+Title
+=====
+
+.. _title:
+
+Paragraph.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit/explicit targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <system_message level="1" line="6" source="test data" type="INFO">
+ <paragraph>
+ Target name overrides implicit target name "title".
+ <target ids="id1" names="title">
+ <paragraph>
+ Paragraph.
+"""],
+["""\
+Duplicate implicit/directive targets.
+
+Title
+=====
+
+.. note:: remember remember
+ :name: title
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate implicit/directive targets.
+ <section dupnames="title" ids="title">
+ <title>
+ Title
+ <note ids="id1" names="title">
+ <system_message backrefs="id1" level="1" line="7" source="test data" type="INFO">
+ <paragraph>
+ Target name overrides implicit target name "title".
+ <paragraph>
+ remember remember
+"""],
+["""\
+Duplicate explicit targets.
+
+.. _title:
+
+First.
+
+.. _title:
+
+Second.
+
+.. _title:
+
+Third.
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate explicit targets.
+ <target dupnames="title" ids="title">
+ <paragraph>
+ First.
+ <system_message level="2" line="7" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+ <target dupnames="title" ids="id1">
+ <paragraph>
+ Second.
+ <system_message level="2" line="11" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "title".
+ <target dupnames="title" ids="id2">
+ <paragraph>
+ Third.
+"""],
+["""\
+Duplicate explicit/directive targets.
+
+.. _title:
+
+First.
+
+.. rubric:: this is a title too
+ :name: title
+
+The system message is left dangling
+(to be handled by the "universal.Messages" transform).
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate explicit/directive targets.
+ <target dupnames="title" ids="title">
+ <paragraph>
+ First.
+ <rubric dupnames="title" ids="id1">
+ this is a title too
+ <paragraph>
+ The system message is left dangling
+ (to be handled by the "universal.Messages" transform).
+"""],
+["""\
+Duplicate targets:
+
+Target
+======
+
+Implicit section header target.
+
+.. [TARGET] Citation target.
+
+.. [#target] Autonumber-labeled footnote target.
+
+.. _target:
+
+Explicit internal target.
+
+.. _target: Explicit_external_target
+
+| Do not insert <system_message> element for duplicate
+| _`target`, if this results in an invalid doctree.
+
+.. rubric:: directive with target
+ :name: Target
+
+:field list: with
+:_`target`: in a field name
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Duplicate targets:
+ <section dupnames="target" ids="target">
+ <title>
+ Target
+ <paragraph>
+ Implicit section header target.
+ <citation dupnames="target" ids="id1">
+ <label>
+ TARGET
+ <system_message backrefs="id1" level="1" line="8" source="test data" type="INFO">
+ <paragraph>
+ Target name overrides implicit target name "target".
+ <paragraph>
+ Citation target.
+ <footnote auto="1" dupnames="target" ids="id2">
+ <system_message backrefs="id2" level="2" line="10" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <paragraph>
+ Autonumber-labeled footnote target.
+ <system_message level="2" line="12" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id3">
+ <paragraph>
+ Explicit internal target.
+ <system_message level="2" line="16" source="test data" type="WARNING">
+ <paragraph>
+ Duplicate explicit target name: "target".
+ <target dupnames="target" ids="id4" refuri="Explicit_external_target">
+ <line_block>
+ <line>
+ Do not insert <system_message> element for duplicate
+ <line>
+ <target dupnames="target" ids="id5">
+ target
+ , if this results in an invalid doctree.
+ <rubric dupnames="target" ids="id6">
+ directive with target
+ <field_list>
+ <field>
+ <field_name>
+ field list
+ <field_body>
+ <paragraph>
+ with
+ <field>
+ <field_name>
+ <target dupnames="target" ids="id7">
+ target
+ <field_body>
+ <paragraph>
+ in a field name
+"""],
+["""\
+Anonymous external hyperlink target:
+
+__ http://w3c.org/
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous external hyperlink target:
+ <target anonymous="1" ids="id1" refuri="http://w3c.org/">
+"""],
+["""\
+Anonymous indirect hyperlink target:
+
+.. __: reference_
+""",
+"""\
+<document source="test data">
+ <paragraph>
+ Anonymous indirect hyperlink target:
+ <target anonymous="1" ids="id1" refname="reference">
+"""],
+])
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.