#! /usr/bin/env python3 # $Id: test_include.py 10134 2025-05-19 21:12:34Z milde $ # Author: David Goodger # Copyright: This module has been placed in the public domain. """ Tests for misc.py "include" directive. """ from pathlib import Path import os.path import unittest import sys if __name__ == '__main__': # prepend the "docutils root" to the Python library path # so we import the local `docutils` package. sys.path.insert(0, str(Path(__file__).resolve().parents[4])) from docutils import core, parsers, utils from docutils.frontend import get_default_settings from docutils.parsers.rst import Parser from docutils.utils import new_document from docutils.utils.code_analyzer import with_pygments from test.test_parsers.test_rst.test_directives.test_code \ import PYGMENTS_2_14_PLUS FILE_DIR = Path(__file__).resolve().parent TEST_ROOT = FILE_DIR.parents[2] # optional 3rd-party markdown parser md_parser_name = 'pycmark' try: # check availability md_parser_class = parsers.get_parser_class(md_parser_name) except ImportError: md_parser_class = None class ParserTestCase(unittest.TestCase): maxDiff = None def test_parser(self): parser = Parser() settings = get_default_settings(Parser) settings.warning_stream = '' settings.halt_level = 5 for name, cases in totest.items(): if name == 'with transforms': continue # see test_publish() below for casenum, (case_input, case_expected) in enumerate(cases): with self.subTest(id=f'totest[{name!r}][{casenum}]'): # eventually skip optional parts: if name == 'include_markdown' and not md_parser_class: self.skipTest('no markdown parser available') if name == 'include_parsed_code' and not with_pygments: self.skipTest('syntax highlight requires pygments') document = new_document('test data', settings.copy()) parser.parse(case_input, document) output = document.pformat() self.assertEqual(case_expected, output) def test_publish(self): # Special case for tests of issue reporting. # To see the system message from the duplicate id, we need transforms. settings = {'_disable_config': True, 'output_encoding': 'unicode', 'warning_stream': '', } name = 'with transforms' for casenum, (sample, expected) in enumerate(totest[name]): with self.subTest(id=f'totest[{name!r}][{casenum}]'): output = core.publish_string(sample, source_path='test data', parser=Parser(), settings_overrides=settings) self.assertEqual(expected, output) try: chr(0x11111111) except ValueError as detail: unichr_exception = f'{detail.__class__.__name__}: {detail}' else: unichr_exception = '' # prepend this directory (relative to the cwd): def mydir(path): return os.path.relpath(os.path.join(FILE_DIR, path), os.getcwd()).replace('\\', '/') include1 = mydir('include1.rst') include2 = mydir('include2.rst') include3 = mydir('include3.rst') include5 = mydir('includes/include5.rst') include6 = mydir('includes/more/include6.rst') include8 = mydir('include8.rst') include10 = mydir('include10.rst') include11 = mydir('include 11.rst') include12 = mydir('include12.rst') include13 = mydir('include13.rst') include14 = mydir('includes/include14.rst') include15 = mydir('includes/include15.rst') include16 = mydir('includes/include16.rst') include_literal = mydir('include_literal.rst') include_md = mydir('include.md') include_xml = mydir('includes/include.xml') include = TEST_ROOT/'data/include.rst' latin2 = TEST_ROOT/'data/latin2.rst' utf_16_file = TEST_ROOT/'data/utf-16-le-sig.rst' utf_16_error_str = ("UnicodeDecodeError: 'ascii' codec can't decode byte 0xff " "in position 0: ordinal not in range(128)") rst_states_dir = os.path.dirname(parsers.rst.states.__file__) # TODO fix case normalisation bug on Windows in utils.relative_path() # nonexistent = os.path.relpath( # os.path.join(rst_states_dir, 'include', 'nonexistent'), # os.getcwd()).replace('\\', '/') nonexistent = utils.relative_path( os.path.join(os.getcwd(), 'dummy'), os.path.join(rst_states_dir, 'include', 'nonexistent') ) # Different error for path with 8bit chars with locale == C or None: try: open('\u043c\u0438\u0440.rst') except UnicodeEncodeError: errstr_8bit_path = """\ Cannot encode input file path "\u043c\u0438\u0440.rst" (wrong locale?).\ """ except FileNotFoundError: errstr_8bit_path = """\ InputError: [Errno 2] No such file or directory: '\u043c\u0438\u0440.rst'.\ """ totest = {} totest['include'] = [ [f"""\ Include Test ============ .. include:: {include1} A paragraph. """, """\
Include Test <section ids="inclusion-1" names="inclusion\\ 1"> <title> Inclusion 1 <paragraph> This file is used by \n\ <literal> test_include.py . <paragraph> A paragraph. """], [f"""\ Include Test ============ .. include:: {include1} :literal: :class: test :name: my name A paragraph. """, f"""\ <document source="test data"> <section ids="include-test" names="include\\ test"> <title> Include Test <literal_block classes="test" ids="my-name" names="my\\ name" source="{include1}" xml:space="preserve"> Inclusion 1 ----------- \n\ This file is used by ``test_include.py``. <paragraph> A paragraph. """], [f"""\ Literal include, add line numbers .. include:: {include1} :literal: :number-lines: """, f"""\ <document source="test data"> <paragraph> Literal include, add line numbers <literal_block source="{include1}" xml:space="preserve"> <inline classes="ln"> 1 \n\ Inclusion 1 <inline classes="ln"> 2 \n\ ----------- <inline classes="ln"> 3 \n\ \n\ <inline classes="ln"> 4 \n\ This file is used by ``test_include.py``. """], [f"""\ Include code .. include:: {include1} :code: :class: test :name: my name """, f"""\ <document source="test data"> <paragraph> Include code <literal_block classes="code test" ids="my-name" names="my\\ name" source="{include1}" xml:space="preserve"> Inclusion 1 ----------- \n\ This file is used by ``test_include.py``. """], [f"""\ Include code, add line numbers .. include:: {include1} :code: :number-lines: """, f"""\ <document source="test data"> <paragraph> Include code, add line numbers <literal_block classes="code" source="{include1}" xml:space="preserve"> <inline classes="ln"> 1 \n\ Inclusion 1 <inline classes="ln"> 2 \n\ ----------- <inline classes="ln"> 3 \n\ \n\ <inline classes="ln"> 4 \n\ This file is used by ``test_include.py``. """], [f"""\ Include with unknown parser. .. include:: {include1} :parser: sillyformat A paragraph. """, f"""\ <document source="test data"> <paragraph> Include with unknown parser. <system_message level="3" line="3" source="test data" type="ERROR"> <paragraph> Error in "include" directive: invalid option value: (option: "parser"; value: \'sillyformat\') Parser "sillyformat" not found. No module named 'sillyformat'. <literal_block xml:space="preserve"> .. include:: {include1} :parser: sillyformat <paragraph> A paragraph. """], [f"""\ Let's test the parse context. This paragraph is in a block quote. .. include:: {include2} The included paragraphs should also be in the block quote. """, """\ <document source="test data"> <paragraph> Let's test the parse context. <block_quote> <paragraph> This paragraph is in a block quote. <paragraph> Here are some paragraphs that can appear at any level. <paragraph> This file (include2.rst) is used by <literal> test_include.py . <paragraph> The included paragraphs should also be in the block quote. """], ["""\ Include Test ============ .. include:: nonexistent.rst A paragraph. """, """\ <document source="test data"> <section ids="include-test" names="include\\ test"> <title> Include Test <system_message level="4" line="4" source="test data" type="SEVERE"> <paragraph> Problems with "include" directive path: InputError: [Errno 2] No such file or directory: 'nonexistent.rst'. <literal_block xml:space="preserve"> .. include:: nonexistent.rst <paragraph> A paragraph. """], [f"""\ Include Test ============ .. include:: {include1} .. include:: {include1} A paragraph. """, f"""\ <document source="test data"> <section ids="include-test" names="include\\ test"> <title> Include Test <section dupnames="inclusion\\ 1" ids="inclusion-1"> <title> Inclusion 1 <paragraph> This file is used by \n\ <literal> test_include.py . <section dupnames="inclusion\\ 1" ids="inclusion-1-1"> <title> Inclusion 1 <system_message backrefs="inclusion-1-1" level="1" line="2" source="{include1}" type="INFO"> <paragraph> Duplicate implicit target name: "inclusion 1". <paragraph> This file is used by \n\ <literal> test_include.py . <paragraph> A paragraph. """], [f"""\ Include Test ============ .. include:: {include1} ---------- .. include:: {include1} A paragraph. """, f"""\ <document source="test data"> <section ids="include-test" names="include\\ test"> <title> Include Test <section dupnames="inclusion\\ 1" ids="inclusion-1"> <title> Inclusion 1 <paragraph> This file is used by \n\ <literal> test_include.py . <transition> <section dupnames="inclusion\\ 1" ids="inclusion-1-1"> <title> Inclusion 1 <system_message backrefs="inclusion-1-1" level="1" line="2" source="{include1}" type="INFO"> <paragraph> Duplicate implicit target name: "inclusion 1". <paragraph> This file is used by \n\ <literal> test_include.py . <paragraph> A paragraph. """], [f"""\ Recursive inclusions: adapt paths. In test data .. include:: {include3} """, f"""\ <document source="test data"> <paragraph> Recursive inclusions: adapt paths. <paragraph> In test data <paragraph> In include3.rst <paragraph> In includes/include4.rst <paragraph> In includes/include5.rst <paragraph> In includes/more/include6.rst <paragraph> In includes/sibling/include7.rst <literal_block source="{include5}" xml:space="preserve"> In includes/include5.rst \n\ .. include:: more/include6.rst <table> <tgroup cols="2"> <colspec colwidth="50"> <colspec colwidth="50"> <tbody> <row> <entry> <paragraph> In <entry> <paragraph> includes/sibling/include7.rst """], [f"""\ Recursive inclusion with specified parser. In test data .. include:: {include3} :parser: rst """, f"""\ <document source="test data"> <paragraph> Recursive inclusion with specified parser. <paragraph> In test data <paragraph> In include3.rst <paragraph> In includes/include4.rst <paragraph> In includes/include5.rst <paragraph> In includes/more/include6.rst <paragraph> In includes/sibling/include7.rst <literal_block source="{include5}" xml:space="preserve"> In includes/include5.rst \n\ .. include:: more/include6.rst <table> <tgroup cols="2"> <colspec colwidth="50"> <colspec colwidth="50"> <tbody> <row> <entry> <paragraph> In <entry> <paragraph> includes/sibling/include7.rst """], [f"""\ In test data Section ======= (Section contents in nested parse; slice of input_lines ViewList.) .. include:: {include3} """, f"""\ <document source="test data"> <paragraph> In test data <section ids="section" names="section"> <title> Section <paragraph> (Section contents in nested parse; slice of input_lines ViewList.) <paragraph> In include3.rst <paragraph> In includes/include4.rst <paragraph> In includes/include5.rst <paragraph> In includes/more/include6.rst <paragraph> In includes/sibling/include7.rst <literal_block source="{include5}" xml:space="preserve"> In includes/include5.rst \n\ .. include:: more/include6.rst <table> <tgroup cols="2"> <colspec colwidth="50"> <colspec colwidth="50"> <tbody> <row> <entry> <paragraph> In <entry> <paragraph> includes/sibling/include7.rst """], [f"""\ Testing relative includes: .. include:: {include8} """, """\ <document source="test data"> <paragraph> Testing relative includes: <paragraph> In include8.rst <paragraph> In ../includes/include9.rst. <paragraph> Here are some paragraphs that can appear at any level. <paragraph> This file (include2.rst) is used by <literal> test_include.py . """], [f"""\ Encoding: .. include:: {utf_16_file} :encoding: utf-16 """, """\ <document source="test data"> <paragraph> Encoding: <paragraph> Grüße """], [f"""\ Include file is UTF-16-encoded, and is not valid ASCII. .. include:: {utf_16_file} :encoding: ascii """, f"""\ <document source="test data"> <paragraph> Include file is UTF-16-encoded, and is not valid ASCII. <system_message level="4" line="3" source="test data" type="SEVERE"> <paragraph> Problem with "include" directive: {utf_16_error_str} <literal_block xml:space="preserve"> .. include:: {utf_16_file} :encoding: ascii """], ["""\ cyrillic filename: .. include:: \u043c\u0438\u0440.rst """, f"""\ <document source="test data"> <paragraph> cyrillic filename: <system_message level="4" line="3" source="test data" type="SEVERE"> <paragraph> Problems with "include" directive path: {errstr_8bit_path} <literal_block xml:space="preserve"> .. include:: \u043c\u0438\u0440.rst """], [f"""\ Testing errors in included file: .. include:: {include10} """, f"""\ <document source="test data"> <paragraph> Testing errors in included file: <system_message level="3" line="1" source="{include10}" type="ERROR"> <paragraph> Invalid character code: 0x11111111 {unichr_exception} <literal_block xml:space="preserve"> unicode:: 0x11111111 <system_message level="2" line="1" source="{include10}" type="WARNING"> <paragraph> Substitution definition "bad" empty or invalid. <literal_block xml:space="preserve"> .. |bad| unicode:: 0x11111111 <section dupnames="hi" ids="hi"> <title> hi <block_quote> <paragraph> indent <system_message level="2" line="7" source="{include10}" type="WARNING"> <paragraph> Block quote ends without a blank line; unexpected unindent. <paragraph> error <section dupnames="hi" ids="hi-1"> <title> hi <system_message backrefs="hi-1" level="1" line="10" source="{include10}" type="INFO"> <paragraph> Duplicate implicit target name: "hi". <system_message level="4" line="12" source="{include10}" type="SEVERE"> <paragraph> Problems with "include" directive path: InputError: [Errno 2] No such file or directory: '{nonexistent}'. <literal_block xml:space="preserve"> .. include:: <nonexistent> <system_message level="3" line="14" source="{include10}" type="ERROR"> <paragraph> Content block expected for the "note" directive; none found. <literal_block xml:space="preserve"> .. note:: <system_message level="3" line="16" source="{include10}" type="ERROR"> <paragraph> Content block expected for the "admonition" directive; none found. <literal_block xml:space="preserve"> .. admonition:: without title <system_message level="3" line="19" source="{include10}" type="ERROR"> <paragraph> Content block expected for the "epigraph" directive; none found. <literal_block xml:space="preserve"> .. epigraph:: <system_message level="3" line="21" source="{include10}" type="ERROR"> <paragraph> Content block expected for the "highlights" directive; none found. <literal_block xml:space="preserve"> .. highlights:: <system_message level="3" line="23" source="{include10}" type="ERROR"> <paragraph> Content block expected for the "pull-quote" directive; none found. <literal_block xml:space="preserve"> .. pull-quote:: <system_message level="3" line="25" source="{include10}" type="ERROR"> <paragraph> Invalid context: the "date" directive can only be used within a substitution definition. <literal_block xml:space="preserve"> .. date:: <paragraph> not a definition list: <system_message level="3" line="29" source="{include10}" type="ERROR"> <paragraph> Unexpected indentation. <block_quote> <paragraph> as a term may only be one line long. <system_message level="3" line="31" source="{include10}" type="ERROR"> <paragraph> Error in "admonition" directive: 1 argument(s) required, 0 supplied. <literal_block xml:space="preserve"> .. admonition:: \n\ without title and content following a blank line <section ids="section-underline-too-short" names="section\\ underline\\ too\\ short"> <title> section underline too short <system_message level="2" line="36" source="{include10}" type="WARNING"> <paragraph> Title underline too short. <literal_block xml:space="preserve"> section underline too short ----- <table> <tgroup cols="2"> <colspec colwidth="14"> <colspec colwidth="6"> <thead> <row> <entry> <paragraph> A simple table <entry> <paragraph> cell 2 <tbody> <row> <entry> <paragraph> cell 3 <entry> <paragraph> cell 4 <system_message level="2" line="43" source="{include10}" type="WARNING"> <paragraph> Blank line required after table. <paragraph> No blank line after table. <system_message level="3" line="45" source="{include10}" type="ERROR"> <paragraph> Error in "unicode" directive: 1 argument(s) required, 0 supplied. <literal_block xml:space="preserve"> unicode:: <system_message level="2" line="45" source="{include10}" type="WARNING"> <paragraph> Substitution definition "empty" empty or invalid. <literal_block xml:space="preserve"> .. |empty| unicode:: <system_message level="3" line="47" source="{include10}" type="ERROR"> <paragraph> Error in "topic" directive: 1 argument(s) required, 0 supplied. <literal_block xml:space="preserve"> .. topic:: <system_message level="3" line="49" source="{include10}" type="ERROR"> <paragraph> Error in "rubric" directive: 1 argument(s) required, 0 supplied. <literal_block xml:space="preserve"> .. rubric:: <rubric> A rubric has no content <comment xml:space="preserve"> _`target: No matching backquote. <system_message level="2" line="52" source="{include10}" type="WARNING"> <paragraph> malformed hyperlink target. <comment xml:space="preserve"> __malformed: no good <system_message level="2" line="53" source="{include10}" type="WARNING"> <paragraph> malformed hyperlink target. <definition_list> <definition_list_item> <term> A literal block:: <definition> <system_message level="1" line="56" source="{include10}" type="INFO"> <paragraph> Blank line missing before literal block (after the "::")? Interpreted as a definition list item. <paragraph> with no blank line above. <literal_block xml:space="preserve"> > A literal block. <system_message level="3" line="61" source="{include10}" type="ERROR"> <paragraph> Inconsistent literal block quoting. <paragraph> $ with inconsistent quoting. <paragraph> <problematic ids="problematic-1" refid="system-message-1"> :unknown-role:`role` \n\ and \n\ <problematic ids="problematic-2" refid="system-message-2"> * unbalanced <problematic ids="problematic-3" refid="system-message-3"> ` inline <problematic ids="problematic-4" refid="system-message-4"> ** markup <system_message level="1" line="63" source="{include10}" type="INFO"> <paragraph> No role entry for "unknown-role" in module "docutils.parsers.rst.languages.en". Trying "unknown-role" as canonical role name. <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="63" source="{include10}" type="ERROR"> <paragraph> Unknown interpreted text role "unknown-role". <system_message backrefs="problematic-2" ids="system-message-2" level="2" line="63" source="{include10}" type="WARNING"> <paragraph> Inline emphasis start-string without end-string. <system_message backrefs="problematic-3" ids="system-message-3" level="2" line="63" source="{include10}" type="WARNING"> <paragraph> Inline interpreted text or phrase reference start-string without end-string. <system_message backrefs="problematic-4" ids="system-message-4" level="2" line="63" source="{include10}" type="WARNING"> <paragraph> Inline strong start-string without end-string. <block_quote> <paragraph> A block quote with \n\ <problematic ids="problematic-5" refid="system-message-5"> * inline warning <system_message backrefs="problematic-5" ids="system-message-5" level="2" line="68" source="{include10}" type="WARNING"> <paragraph> Inline emphasis start-string without end-string. <attribution> attribution with \n\ <problematic ids="problematic-6" refid="system-message-6"> * inline warning <system_message backrefs="problematic-6" ids="system-message-6" level="2" line="70" source="{include10}" type="WARNING"> <paragraph> Inline emphasis start-string without end-string. <paragraph> <problematic ids="problematic-7" refid="system-message-7"> :PEP:`-1` <system_message backrefs="problematic-7" ids="system-message-7" level="3" line="72" source="{include10}" type="ERROR"> <paragraph> PEP number must be a number from 0 to 9999; "-1" is invalid. <system_message level="1" line="70" source="{include10}" type="INFO"> <paragraph> No directive entry for "unknown" in module "docutils.parsers.rst.languages.en". Trying "unknown" as canonical directive name. <system_message level="3" line="74" source="{include10}" type="ERROR"> <paragraph> Unknown directive type "unknown". <literal_block xml:space="preserve"> .. unknown:: directive (TODO: info still reported with wrong line) <system_message level="3" line="76" source="{include10}" type="ERROR"> <paragraph> Malformed table. No bottom table border found. <literal_block xml:space="preserve"> ============== ====== A simple table with no bottom border \n\ .. end of inclusion from "{include10}" """], [f"""\ Inclusion 1 =========== Name clash: The included file uses the same section title. .. include:: {include1} :parser: rst """, f"""\ <document source="test data"> <section dupnames="inclusion\\ 1" ids="inclusion-1"> <title> Inclusion 1 <paragraph> Name clash: The included file uses the same section title. <section dupnames="inclusion\\ 1" ids="inclusion-1-1"> <title> Inclusion 1 <system_message backrefs="inclusion-1-1" level="1" line="2" source="{include1}" type="INFO"> <paragraph> Duplicate implicit target name: "inclusion 1". <paragraph> This file is used by \n\ <literal> test_include.py . """], [f"""\ Include file with whitespace in the path: .. include:: {include11} """, """\ <document source="test data"> <paragraph> Include file with whitespace in the path: <paragraph> some text """], ["""\ Standard include data file: .. include:: <isogrk4.txt> """, """\ <document source="test data"> <paragraph> Standard include data file: <comment xml:space="preserve"> This data file has been placed in the public domain. <comment xml:space="preserve"> Derived from the Unicode character mappings available from <http://www.w3.org/2003/entities/xml/>. Processed by unicode2rstsubs.py, part of Docutils: <https://docutils.sourceforge.io>. <substitution_definition names="b.Gammad"> \u03dc <substitution_definition names="b.gammad"> \u03dd """], ["""\ Nonexistent standard include data file: .. include:: <nonexistent> """, f"""\ <document source="test data"> <paragraph> Nonexistent standard include data file: <system_message level="4" line="3" source="test data" type="SEVERE"> <paragraph> Problems with "include" directive path: InputError: [Errno 2] No such file or directory: '{nonexistent}'. <literal_block xml:space="preserve"> .. include:: <nonexistent> """], [f"""\ Include start-line/end-line Test .. include:: {include2} :start-line: 3 :end-line: 4 """, """\ <document source="test data"> <paragraph> Include start-line/end-line Test <paragraph> This file (include2.rst) is used by """], [f"""\ Include start-line/end-line + start-after Test .. include:: {include12} :start-line: 2 :end-line: 5 :start-after: here Text search is limited to the specified lines. """, """\ <document source="test data"> <paragraph> Include start-line/end-line + start-after Test <paragraph> In include12.rst (after "start here", before "stop here") <paragraph> Text search is limited to the specified lines. """], [f"""\ Include start-after/end-before Test .. include:: {include12} :start-after: .. start here :end-before: .. stop here A paragraph. """, """\ <document source="test data"> <paragraph> Include start-after/end-before Test <paragraph> In include12.rst (after "start here", before "stop here") <paragraph> A paragraph. """], [f"""\ Include start-after/end-before Test, single option variant .. include:: {include12} :end-before: .. start here .. include:: {include12} :start-after: .. stop here A paragraph. """, """\ <document source="test data"> <paragraph> Include start-after/end-before Test, single option variant <paragraph> In include12.rst (but before "start here") <paragraph> In include12.rst (after "stop here") <paragraph> A paragraph. """], [f"""\ Include start-after/end-before multi-line test. .. include:: {include13} :start-after: From: me To: you :end-before: ------- -- mork of ork .. include:: {include13} :start-after: From: me To: you :end-before: ------- -- mork of ork A paragraph. """, f"""\ <document source="test data"> <paragraph> Include start-after/end-before multi-line test. <system_message level="4" line="3" source="test data" type="SEVERE"> <paragraph> Problem with "end-before" option of "include" directive: Text not found. <literal_block xml:space="preserve"> .. include:: {include13} :start-after: From: me To: you :end-before: ------- -- mork of ork <paragraph> In include13.rst (between header and signature) <paragraph> A paragraph. """], [f"""\ Error handling test; "end-before" error handling tested in previous test. .. include:: {include13} :start-after: bad string :end-before: mork of ork """, f"""\ <document source="test data"> <paragraph> Error handling test; "end-before" error handling tested in previous test. <system_message level="4" line="3" source="test data" type="SEVERE"> <paragraph> Problem with "start-after" option of "include" directive: Text not found. <literal_block xml:space="preserve"> .. include:: {include13} :start-after: bad string :end-before: mork of ork """], [f"""\ Default TAB expansion with literal include: .. include:: {include_literal} :literal: """, f"""\ <document source="test data"> <paragraph> Default TAB expansion with literal include: <literal_block source="{include_literal}" xml:space="preserve"> Literal included this should **not** be *marked* `up`. <- leading raw tab. \n\ Newlines are normalized. """], [f"""\ Custom TAB expansion with literal include: .. include:: {include_literal} :literal: :tab-width: 2 """, f"""\ <document source="test data"> <paragraph> Custom TAB expansion with literal include: <literal_block source="{include_literal}" xml:space="preserve"> Literal included this should **not** be *marked* `up`. <- leading raw tab. \n\ Newlines are normalized. """], [f"""\ No TAB expansion with literal include: .. include:: {include_literal} :literal: :tab-width: -1 """, f"""\ <document source="test data"> <paragraph> No TAB expansion with literal include: <literal_block source="{include_literal}" xml:space="preserve"> Literal included this should **not** be *marked* `up`. \t<- leading raw tab. \n\ Newlines are normalized. """], ] totest['include_parsed_code'] = [ [f"""\ Included code .. include:: {include1} :code: rst """, f"""\ <document source="test data"> <paragraph> Included code <literal_block classes="code rst" source="{include1}" xml:space="preserve"> <inline classes="generic heading"> Inclusion 1 \n\ <inline classes="generic heading"> ----------- \n\ <inline classes="whitespace"> \n\ This file is used by \n\ <inline classes="literal string"> ``test_include.py`` . """ if PYGMENTS_2_14_PLUS else f"""\ <document source="test data"> <paragraph> Included code <literal_block classes="code rst" source="{include1}" xml:space="preserve"> <inline classes="generic heading"> Inclusion 1 \n\ <inline classes="generic heading"> ----------- \n\ \n\ This file is used by \n\ <inline classes="literal string"> ``test_include.py`` . """], [f"""\ Included code .. include:: {include1} :code: rst :number-lines: """, f"""\ <document source="test data"> <paragraph> Included code <literal_block classes="code rst" source="{include1}" xml:space="preserve"> <inline classes="ln"> 1 \n\ <inline classes="generic heading"> Inclusion 1 \n\ <inline classes="ln"> 2 \n\ <inline classes="generic heading"> ----------- \n\ <inline classes="ln"> 3 \n\ <inline classes="whitespace"> \n\ <inline classes="ln"> 4 \n\ <inline classes="whitespace"> This file is used by \n\ <inline classes="literal string"> ``test_include.py`` . """ if PYGMENTS_2_14_PLUS else f"""\ <document source="test data"> <paragraph> Included code <literal_block classes="code rst" source="{include1}" xml:space="preserve"> <inline classes="ln"> 1 \n\ <inline classes="generic heading"> Inclusion 1 \n\ <inline classes="ln"> 2 \n\ <inline classes="generic heading"> ----------- \n\ <inline classes="ln"> 3 \n\ \n\ <inline classes="ln"> 4 \n\ This file is used by \n\ <inline classes="literal string"> ``test_include.py`` . """], [f"""\ Default TAB expansion with included code: .. include:: {include_literal} :code: rst """, f"""\ <document source="test data"> <paragraph> Default TAB expansion with included code: <literal_block classes="code rst" source="{include_literal}" xml:space="preserve"> Literal included this should \n\ <inline classes="generic strong"> **not** be \n\ <inline classes="generic emph"> *marked* \n\ <inline classes="name variable"> `up` . <inline classes="whitespace"> \n\ <- leading raw tab. <inline classes="whitespace"> \n\ \n\ Newlines <inline classes="whitespace"> \n\ are <inline classes="whitespace"> \n\ normalized. """ if PYGMENTS_2_14_PLUS else f"""\ <document source="test data"> <paragraph> Default TAB expansion with included code: <literal_block classes="code rst" source="{include_literal}" xml:space="preserve"> Literal included this should \n\ <inline classes="generic strong"> **not** be \n\ <inline classes="generic emph"> *marked* \n\ <inline classes="name variable"> `up` . <- leading raw tab. \n\ Newlines are normalized. """], [f"""\ Custom TAB expansion with included code: .. include:: {include_literal} :code: rst :tab-width: 2 """, f"""\ <document source="test data"> <paragraph> Custom TAB expansion with included code: <literal_block classes="code rst" source="{include_literal}" xml:space="preserve"> Literal included this should \n\ <inline classes="generic strong"> **not** be \n\ <inline classes="generic emph"> *marked* \n\ <inline classes="name variable"> `up` . <inline classes="whitespace"> \n\ <- leading raw tab. <inline classes="whitespace"> \n\ \n\ Newlines <inline classes="whitespace"> \n\ are <inline classes="whitespace"> \n\ normalized. """ if PYGMENTS_2_14_PLUS else f"""\ <document source="test data"> <paragraph> Custom TAB expansion with included code: <literal_block classes="code rst" source="{include_literal}" xml:space="preserve"> Literal included this should \n\ <inline classes="generic strong"> **not** be \n\ <inline classes="generic emph"> *marked* \n\ <inline classes="name variable"> `up` . <- leading raw tab. \n\ Newlines are normalized. """], [f"""\ No TAB expansion with included code: .. include:: {include_literal} :code: rst :tab-width: -1 """, f"""\ <document source="test data"> <paragraph> No TAB expansion with included code: <literal_block classes="code rst" source="{include_literal}" xml:space="preserve"> Literal included this should \n\ <inline classes="generic strong"> **not** be \n\ <inline classes="generic emph"> *marked* \n\ <inline classes="name variable"> `up` . <inline classes="whitespace"> \n\ \t<- leading raw tab. <inline classes="whitespace"> \n\ \n\ Newlines <inline classes="whitespace"> \n\ are <inline classes="whitespace"> \n\ normalized. """ if PYGMENTS_2_14_PLUS else f"""\ <document source="test data"> <paragraph> No TAB expansion with included code: <literal_block classes="code rst" source="{include_literal}" xml:space="preserve"> Literal included this should \n\ <inline classes="generic strong"> **not** be \n\ <inline classes="generic emph"> *marked* \n\ <inline classes="name variable"> `up` . \t<- leading raw tab. \n\ Newlines are normalized. """], [f"""\ Including includes/include14.rst .. include:: {include14} """, f"""\ <document source="test data"> <paragraph> Including includes/include14.rst <paragraph> Including more/include6.rst as rst-code from includes/include14.rst: <literal_block classes="code rst" source="{include6}" xml:space="preserve"> In includes/more/include6.rst <inline classes="whitespace"> \n\ \n\ <inline classes="punctuation"> .. \n\ <inline classes="operator word"> include <inline classes="punctuation"> :: ../sibling/include7.rst """ if PYGMENTS_2_14_PLUS else f"""\ <document source="test data"> <paragraph> Including includes/include14.rst <paragraph> Including more/include6.rst as rst-code from includes/include14.rst: <literal_block classes="code rst" source="{include6}" xml:space="preserve"> In includes/more/include6.rst \n\ <inline classes="punctuation"> .. \n\ <inline classes="operator word"> include <inline classes="punctuation"> :: ../sibling/include7.rst """], [f"""\ Circular inclusion .. include:: {include15} """, f"""\ <document source="test data"> <paragraph> Circular inclusion <paragraph> File "include15.rst": example of rekursive inclusion. <paragraph> File "include16.rst": example of rekursive inclusion. <system_message level="2" line="3" source="{include16}" type="WARNING"> <paragraph> circular inclusion in "include" directive: {include15} > {include16} > {include15} > test data <literal_block xml:space="preserve"> .. include:: include15.rst <paragraph> No loop when clipping before the "include" directive: <paragraph> File "include15.rst": example of rekursive inclusion. """], [f"""\ Circular inclusion with clipping. .. include:: {include16} :start-line: 2 """, f"""\ <document source="test data"> <paragraph> Circular inclusion with clipping. <paragraph> File "include15.rst": example of rekursive inclusion. <paragraph> File "include16.rst": example of rekursive inclusion. <system_message level="2" line="3" source="{include16}" type="WARNING"> <paragraph> circular inclusion in "include" directive: {include15} > {include16} > {include15} > {include16} > test data <literal_block xml:space="preserve"> .. include:: include15.rst <paragraph> No loop when clipping before the "include" directive: <paragraph> File "include15.rst": example of rekursive inclusion. <paragraph> No loop when clipping before the "include" directive: <paragraph> File "include15.rst": example of rekursive inclusion. """], [f"""\ Circular inclusion with specified parser. .. include:: {include15} :parser: rst """, f"""\ <document source="test data"> <paragraph> Circular inclusion with specified parser. <paragraph> File "include15.rst": example of rekursive inclusion. <paragraph> File "include16.rst": example of rekursive inclusion. <system_message level="2" line="3" source="{include16}" type="WARNING"> <paragraph> circular inclusion in "include" directive: {include15} > {include16} > {include15} <literal_block xml:space="preserve"> .. include:: include15.rst <paragraph> No loop when clipping before the "include" directive: <paragraph> File "include15.rst": example of rekursive inclusion. """], [f"""\ No circular inclusion. .. list-table:: * - .. include:: {include} - .. include:: {include} """, """\ <document source="test data"> <paragraph> No circular inclusion. <table> <tgroup cols="2"> <colspec colwidth="50"> <colspec colwidth="50"> <tbody> <row> <entry> <paragraph> Some include text. <entry> <paragraph> Some include text. """], ] # Parsing with Markdown is an optional feature depending on 3rd-party modules: totest['include_markdown'] = [ [f"""\ Include Markdown source. .. include:: {include_md} :parser: {md_parser_name} A paragraph. """, """\ <document source="test data"> <paragraph> Include Markdown source. <section depth="1" ids="section-1"> <title> Title 1 <paragraph> <emphasis> emphasis and \n\ <emphasis> also emphasis <paragraph> No whitespace required around a <reference refuri="/uri"> phrase reference . <target ids="phrase-reference" names="phrase\\ reference" refuri="/uri"> <paragraph> A paragraph. """], ] # Transforms are required for these tests: The system_message about # duplicate name/id is appended by the "universal.Messages" transform. totest['with transforms'] = [ [f"""\ .. _common id: Include Docutils XML file: .. include:: {include_xml} :parser: xml """, f"""\ <document source="test data"> <target refid="common-id"> <paragraph ids="common-id" names="common\\ id"> Include Docutils XML file: <section> <title names="nice\\ heading"> nice heading <paragraph> Text with \n\ <strong ids="common-id"> strong statement and more text. <section classes="system-messages"> <title> Docutils System Messages <system_message level="3" line="3" source="{include_xml}" type="ERROR"> <paragraph> Duplicate ID: "common-id" used by <target ids="common-id" names="common\\ id"> and <strong ids="common-id"> """], [f"""\ Inclusion 1 =========== Name clash: The included file uses the same section title `inclusion 1`_. .. include:: {include1} :parser: rst Inclusion 2 =========== """, """\ <document source="test data"> <section dupnames="inclusion\\ 1" ids="inclusion-1"> <title> Inclusion 1 <paragraph> Name clash: The included file uses the same section title \n\ <problematic ids="problematic-1" refid="system-message-1"> `inclusion 1`_ . <section dupnames="inclusion\\ 1" ids="inclusion-1-1"> <title> Inclusion 1 <paragraph> This file is used by \n\ <literal> test_include.py . <section ids="inclusion-2" names="inclusion\\ 2"> <title> Inclusion 2 <section classes="system-messages"> <title> Docutils System Messages <system_message backrefs="problematic-1" ids="system-message-1" level="3" line="3" source="test data" type="ERROR"> <paragraph> Duplicate target name, cannot be used as a unique reference: "inclusion 1". """], ] if __name__ == '__main__': unittest.main()