Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 47 additions & 39 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,61 @@

import re

import pytest
from docutils import __version_info__ as docutils_version_info

DOCUTILS_0_22_PLUS = docutils_version_info >= (0, 22)


def normalize_doctree_xml(text: str) -> str:
@pytest.fixture
def normalize_doctree_xml():
"""Normalize docutils XML output for cross-version compatibility.

In docutils 0.22+, boolean attributes are serialized as "1"/"0"
instead of "True"/"False". This function normalizes to the old format
for consistent test fixtures.
"""
if DOCUTILS_0_22_PLUS:
# Normalize new format (1/0) to old format (1/0)
# Only replace when it's clearly a boolean attribute value
# Pattern: attribute="1" or attribute="0"
attrs = [
"force",
"glob",
"hidden",
"id_link",
"includehidden",
"inline",
"internal",
"is_div",
"linenos",
"multi_line_parameter_list",
"multi_line_trailing_comma",
"no-contents-entry",
"no-index",
"no-index-entry",
"no-typesetting",
"no-wrap",
"nocontentsentry",
"noindex",
"noindexentry",
"nowrap",
"refexplicit",
"refspecific",
"refwarn",
"sorted",
"titlesonly",
"toctree",
"translatable",
]
text = re.sub(rf' ({"|".join(attrs)})="1"', r' \1="True"', text)
text = re.sub(rf' ({"|".join(attrs)})="0"', r' \1="False"', text)
# numbered is changed in math_block, but not in toctree, so we have to be more precise
text = re.sub(r' numbered="1" xml:space', r' numbered="True" xml:space', text)
return text

def _normalize(text: str) -> str:
if DOCUTILS_0_22_PLUS:
# Normalize new format (1/0) to old format (1/0)
# Only replace when it's clearly a boolean attribute value
# Pattern: attribute="1" or attribute="0"
attrs = [
"force",
"glob",
"hidden",
"id_link",
"includehidden",
"inline",
"internal",
"is_div",
"linenos",
"multi_line_parameter_list",
"multi_line_trailing_comma",
"no-contents-entry",
"no-index",
"no-index-entry",
"no-typesetting",
"no-wrap",
"nocontentsentry",
"noindex",
"noindexentry",
"nowrap",
"refexplicit",
"refspecific",
"refwarn",
"sorted",
"titlesonly",
"toctree",
"translatable",
]
text = re.sub(rf' ({"|".join(attrs)})="1"', r' \1="True"', text)
text = re.sub(rf' ({"|".join(attrs)})="0"', r' \1="False"', text)
# numbered is changed in math_block, but not in toctree, so we have to be more precise
text = re.sub(
r' numbered="1" xml:space', r' numbered="True" xml:space', text
)
return text

return _normalize
3 changes: 1 addition & 2 deletions tests/test_html/test_html_to_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from myst_parser.config.main import MdParserConfig
from myst_parser.mdit_to_docutils.html_to_nodes import html_to_nodes
from tests.conftest import normalize_doctree_xml

FIXTURE_PATH = Path(__file__).parent

Expand All @@ -30,7 +29,7 @@ def _run_directive(name: str, first_line: str, content: str, position: int):


@pytest.mark.param_file(FIXTURE_PATH / "html_to_nodes.md")
def test_html_to_nodes(file_params, mock_renderer):
def test_html_to_nodes(file_params, mock_renderer, normalize_doctree_xml):
output = nodes.container()
output += html_to_nodes(file_params.content, line_number=0, renderer=mock_renderer)
file_params.assert_expected(normalize_doctree_xml(output.pformat()), rstrip=True)
15 changes: 9 additions & 6 deletions tests/test_renderers/test_fixtures_docutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from typing import Any

import pytest
from conftest import normalize_doctree_xml
from docutils import __version_info__ as docutils_version
from docutils.core import Publisher, publish_doctree
from pytest_param_files import ParamTestData
Expand All @@ -22,7 +21,9 @@


@pytest.mark.param_file(FIXTURE_PATH / "docutil_syntax_elements.md")
def test_syntax_elements(file_params: ParamTestData, monkeypatch):
def test_syntax_elements(
file_params: ParamTestData, monkeypatch, normalize_doctree_xml
):
"""Test conversion of Markdown to docutils AST (before transforms are applied)."""

def _apply_transforms(self):
Expand All @@ -47,7 +48,7 @@ def _apply_transforms(self):


@pytest.mark.param_file(FIXTURE_PATH / "docutil_link_resolution.md")
def test_link_resolution(file_params: ParamTestData):
def test_link_resolution(file_params: ParamTestData, normalize_doctree_xml):
"""Test that Markdown links resolve to the correct target, or give the correct warning."""
settings = settings_from_cmdline(file_params.description)
report_stream = StringIO()
Expand All @@ -70,7 +71,7 @@ def test_link_resolution(file_params: ParamTestData):


@pytest.mark.param_file(FIXTURE_PATH / "docutil_roles.md")
def test_docutils_roles(file_params: ParamTestData, monkeypatch):
def test_docutils_roles(file_params: ParamTestData, monkeypatch, normalize_doctree_xml):
"""Test conversion of Markdown to docutils AST (before transforms are applied)."""

def _apply_transforms(self):
Expand All @@ -90,7 +91,9 @@ def _apply_transforms(self):


@pytest.mark.param_file(FIXTURE_PATH / "docutil_directives.md")
def test_docutils_directives(file_params: ParamTestData, monkeypatch):
def test_docutils_directives(
file_params: ParamTestData, monkeypatch, normalize_doctree_xml
):
"""Test output of docutils directives."""
if "SKIP" in file_params.description: # line-block directive not yet supported
pytest.skip(file_params.description)
Expand All @@ -112,7 +115,7 @@ def _apply_transforms(self):


@pytest.mark.param_file(FIXTURE_PATH / "docutil_syntax_extensions.txt")
def test_syntax_extensions(file_params: ParamTestData):
def test_syntax_extensions(file_params: ParamTestData, normalize_doctree_xml):
"""The description is parsed as a docutils commandline"""
settings = settings_from_cmdline(file_params.description)
report_stream = StringIO()
Expand Down
60 changes: 47 additions & 13 deletions tests/test_renderers/test_fixtures_sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
from sphinx_pytest.plugin import CreateDoctree

from myst_parser.mdit_to_docutils.sphinx_ import SphinxRenderer
from tests.conftest import normalize_doctree_xml

FIXTURE_PATH = Path(__file__).parent.joinpath("fixtures")


@pytest.mark.param_file(FIXTURE_PATH / "sphinx_syntax_elements.md")
def test_syntax_elements(
file_params: ParamTestData, sphinx_doctree: CreateDoctree, monkeypatch
file_params: ParamTestData,
sphinx_doctree: CreateDoctree,
monkeypatch,
normalize_doctree_xml,
):
sphinx_doctree.set_conf({"extensions": ["myst_parser"], "show_warning_types": True})

Expand Down Expand Up @@ -52,7 +54,9 @@ def _apply_transforms(self):


@pytest.mark.param_file(FIXTURE_PATH / "sphinx_link_resolution.md")
def test_link_resolution(file_params: ParamTestData, sphinx_doctree: CreateDoctree):
def test_link_resolution(
file_params: ParamTestData, sphinx_doctree: CreateDoctree, normalize_doctree_xml
):
sphinx_doctree.set_conf(
{"extensions": ["myst_parser"], **settings_from_json(file_params.description)}
)
Expand All @@ -78,7 +82,11 @@ def settings_from_json(string: str | None):


@pytest.mark.param_file(FIXTURE_PATH / "tables.md")
def test_tables(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree):
def test_tables(
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
sphinx_doctree_no_tr.set_conf({"extensions": ["myst_parser"]})
result = sphinx_doctree_no_tr(file_params.content, "index.md")
file_params.assert_expected(
Expand All @@ -88,7 +96,9 @@ def test_tables(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree)

@pytest.mark.param_file(FIXTURE_PATH / "directive_options.md")
def test_directive_options(
file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
sphinx_doctree_no_tr.set_conf({"extensions": ["myst_parser"]})
result = sphinx_doctree_no_tr(file_params.content, "index.md")
Expand All @@ -99,7 +109,9 @@ def test_directive_options(

@pytest.mark.param_file(FIXTURE_PATH / "sphinx_directives.md")
def test_sphinx_directives(
file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
# TODO fix skipped directives
# TODO test domain directives
Expand All @@ -117,7 +129,11 @@ def test_sphinx_directives(


@pytest.mark.param_file(FIXTURE_PATH / "sphinx_roles.md")
def test_sphinx_roles(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree):
def test_sphinx_roles(
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
if file_params.title.startswith("SKIP"):
pytest.skip(file_params.title)

Expand All @@ -140,7 +156,11 @@ def test_sphinx_roles(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDo


@pytest.mark.param_file(FIXTURE_PATH / "dollarmath.md")
def test_dollarmath(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree):
def test_dollarmath(
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
sphinx_doctree_no_tr.set_conf(
{"extensions": ["myst_parser"], "myst_enable_extensions": ["dollarmath"]}
)
Expand All @@ -152,7 +172,10 @@ def test_dollarmath(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoct

@pytest.mark.param_file(FIXTURE_PATH / "amsmath.md")
def test_amsmath(
file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree, monkeypatch
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
monkeypatch,
normalize_doctree_xml,
):
monkeypatch.setattr(SphinxRenderer, "_random_label", lambda self: "mock-uuid")
sphinx_doctree_no_tr.set_conf(
Expand All @@ -166,7 +189,10 @@ def test_amsmath(

@pytest.mark.param_file(FIXTURE_PATH / "containers.md")
def test_containers(
file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree, monkeypatch
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
monkeypatch,
normalize_doctree_xml,
):
monkeypatch.setattr(SphinxRenderer, "_random_label", lambda self: "mock-uuid")
sphinx_doctree_no_tr.set_conf(
Expand All @@ -180,7 +206,9 @@ def test_containers(

@pytest.mark.param_file(FIXTURE_PATH / "eval_rst.md")
def test_evalrst_elements(
file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
sphinx_doctree_no_tr.set_conf({"extensions": ["myst_parser"]})
result = sphinx_doctree_no_tr(file_params.content, "index.md")
Expand All @@ -191,7 +219,9 @@ def test_evalrst_elements(

@pytest.mark.param_file(FIXTURE_PATH / "definition_lists.md")
def test_definition_lists(
file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
sphinx_doctree_no_tr.set_conf(
{"extensions": ["myst_parser"], "myst_enable_extensions": ["deflist"]}
Expand All @@ -203,7 +233,11 @@ def test_definition_lists(


@pytest.mark.param_file(FIXTURE_PATH / "attributes.md")
def test_attributes(file_params: ParamTestData, sphinx_doctree_no_tr: CreateDoctree):
def test_attributes(
file_params: ParamTestData,
sphinx_doctree_no_tr: CreateDoctree,
normalize_doctree_xml,
):
sphinx_doctree_no_tr.set_conf(
{
"extensions": ["myst_parser"],
Expand Down
3 changes: 1 addition & 2 deletions tests/test_renderers/test_include_directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from pathlib import Path

import pytest
from conftest import normalize_doctree_xml
from docutils.core import publish_doctree

from myst_parser.parsers.docutils_ import Parser
Expand All @@ -12,7 +11,7 @@


@pytest.mark.param_file(FIXTURE_PATH / "mock_include.md")
def test_render(file_params, tmp_path, monkeypatch):
def test_render(file_params, tmp_path, monkeypatch, normalize_doctree_xml):
monkeypatch.chdir(tmp_path)

tmp_path.joinpath("other.md").write_text("a\nb\nc")
Expand Down
3 changes: 1 addition & 2 deletions tests/test_renderers/test_myst_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from pathlib import Path

import pytest
from conftest import normalize_doctree_xml
from docutils import __version_info__ as docutils_version
from docutils.core import Publisher, publish_string
from pytest_param_files import ParamTestData
Expand All @@ -17,7 +16,7 @@


@pytest.mark.param_file(FIXTURE_PATH / "myst-config.txt")
def test_cmdline(file_params: ParamTestData):
def test_cmdline(file_params: ParamTestData, normalize_doctree_xml):
"""The description is parsed as a docutils commandline"""
if file_params.title == "attrs_image" and docutils_version < (0, 22):
# loose system messages are also output to ast in 0.22 https://github.com/live-clones/docutils/commit/dc4e16315b4fbe391417a6f7aad215b9389a9c74
Expand Down
2 changes: 1 addition & 1 deletion tests/test_renderers/test_myst_refs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import sys

import pytest
from conftest import normalize_doctree_xml
from sphinx.util.console import strip_colors
from sphinx_pytest.plugin import CreateDoctree

Expand Down Expand Up @@ -42,6 +41,7 @@ def test_parse(
should_warn: bool,
sphinx_doctree: CreateDoctree,
file_regression,
normalize_doctree_xml,
):
sphinx_doctree.set_conf({"extensions": ["myst_parser"], "show_warning_types": True})
result = sphinx_doctree(text, "index.md")
Expand Down
3 changes: 1 addition & 2 deletions tests/test_sphinx/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ def test_basic(app, status, warning, get_sphinx_app_output):
from docutils import nodes

from myst_parser._compat import findall
from tests.conftest import normalize_doctree_xml

SOURCE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "sourcedirs"))

Expand Down Expand Up @@ -95,7 +94,7 @@ def read(


@pytest.fixture
def get_sphinx_app_doctree(file_regression):
def get_sphinx_app_doctree(file_regression, normalize_doctree_xml):
def read(
app,
docname="index",
Expand Down
Loading