tests.sphinx package

Submodules

tests.sphinx.conftest module

Fixtures and helpers for Sphinx tests.

Separated from the root tests/conftest.py so that the Sphinx dependency (and its ecosystem: myst-parser, docutils, etc.) is only imported when running the tests in this subdirectory. Downstream packagers can skip these tests with --ignore=tests/sphinx without affecting the rest of the test suite.

tests.sphinx.conftest.MYST_HAS_NATIVE_ALERTS = True

Flip-switch reused by tests to branch between the two alert rendering paths: click_extra’s regex converter (pre-5.1) and myst-parser’s native "alert" extension (>=5.1). Both paths must produce the same admonition HTML.

class tests.sphinx.conftest.FormatType(*values)[source]

Bases: Enum

Sphinx document format types and their file extensions.

RST = '.rst'
MYST = '.md'
class tests.sphinx.conftest.SphinxAppWrapper(app, format_type)[source]

Bases: object

Wrapper around Sphinx application with additional testing methods.

classmethod create(format_type, tmp_path, return_srcdir=False, enable_exec_directives=True)[source]

Factory method to create a SphinxAppWrapper with given format.

enable_exec_directives opts the test app into the click:* and python:* directive families. Defaults to True for every fixture-built app because the test suite primarily exercises those directives. Tests that verify the off-by-default production gate flip the flag back to False explicitly.

Return type:

Generator[SphinxAppWrapper | tuple[SphinxAppWrapper, Path], None, None]

build_document(content)[source]

Build a Sphinx document with content and return the HTML output.

Automatically detects the format from the app configuration and uses the appropriate file extension (.rst or .md).

Return type:

str | None

generate_test_content(test_case)[source]

Generate content for a test case based on the app’s format type.

Return type:

str

tests.sphinx.conftest.sphinx_app(request, tmp_path)[source]

Create a Sphinx application for testing.

tests.sphinx.conftest.sphinx_app_for_format(request, tmp_path)[source]

sphinx_app variant whose format is supplied by the caller.

Identical to sphinx_app() but without the default params: the FormatType is taken from the test’s indirect parametrization. A params-bearing fixture cannot also be parametrized by a test (pytest rejects it as a duplicate parametrization), so a test that drives the format per case parametrizes this variant instead.

tests.sphinx.conftest.sphinx_app_rst(tmp_path)[source]

Create a Sphinx application for testing RST format only.

The click:* and python:* directive families are enabled so tests can exercise them. Tests that explicitly verify the off-by- default opt-in gate construct their own app via SphinxAppWrapper.create() with enable_exec_directives=False.

tests.sphinx.conftest.sphinx_app_myst(tmp_path)[source]

Create a Sphinx application for testing MyST format only.

The click:* and python:* directive families are enabled: see sphinx_app_rst() for the rationale.

tests.sphinx.conftest.sphinx_app_myst_with_include(tmp_path)[source]

Create a Sphinx application for testing MyST format with include files.

class tests.sphinx.conftest.DirectiveTestCase(name, format_type=None, source_block=None, run_block=None, document=None, html_matches=None)[source]

Bases: object

Test case data for directive tests.

name: str
format_type: FormatType | None = None
source_block: str | None = None
run_block: str | None = None
document: str | None = None
html_matches: Sequence[str] | str | None = None
supports_format(format_type)[source]

Check if this test case supports the given format type.

Todo

Get rid of this method, and make the test case provide its own sphinx_app.

Return type:

bool

tests.sphinx.conftest.python_block(*lines)[source]

Build expected Python highlight block.

Return type:

str

tests.sphinx.conftest.shell_block(*lines)[source]

Build expected shell session block.

Return type:

str

tests.sphinx.conftest.admonition_block(admonition_type, content)[source]

Build expected admonition block.

Parameters:
  • admonition_type (str) – The type of admonition (note, tip, warning, etc.)

  • content (str) – The inner HTML content of the admonition (without the title)

Return type:

str

tests.sphinx.test_sphinx module

Fixtures and utilities for Sphinx testing.

tests.sphinx.test_sphinx.test_sphinx_extension_setup(sphinx_app)[source]

Test that the Sphinx extension is properly loaded.

tests.sphinx.test_sphinx.test_resolve_any_xref(sphinx_app)[source]

Test that resolve_any_xref is implemented and returns an empty list.

tests.sphinx.test_sphinx_alerts module

Tests for GitHub alert syntax conversion in Sphinx with MyST parser.

tests.sphinx.test_sphinx_alerts.test_all_alert_types(alert_type)[source]

Test all supported alert types are converted correctly.

tests.sphinx.test_sphinx_alerts.test_alert_conversion(text, expected)[source]

Test GitHub alerts are converted to MyST admonitions.

When expected is None, no conversion should occur.

tests.sphinx.test_sphinx_alerts.test_sphinx_integration(sphinx_app, test_case)[source]

Integration-critical tests that verify Sphinx rendering behavior.

tests.sphinx.test_sphinx_alerts.test_github_alert_no_colon_fence(tmp_path)[source]

Test that ConfigError is raised when colon_fence is not enabled.

tests.sphinx.test_sphinx_alerts.test_github_alert_in_included_files(sphinx_app_myst_with_include, included_files, main_content, expected_fragments, unexpected_fragments)[source]

Test GitHub alerts in included files with various configurations.

tests.sphinx.test_sphinx_click module

Tests for Sphinx directives click:source and click:run in rST and MyST formats.

tests.sphinx.test_sphinx_click.test_directive_functionality(sphinx_app, test_case)[source]

Test standard directive functionalities in both rST and MyST.

tests.sphinx.test_sphinx_click.test_directive_option_format(sphinx_app_rst)[source]

rST will fail to render if an :option: is not followed by an empty line.

tests.sphinx.test_sphinx_click.test_directive_option_language_override(sphinx_app)[source]

Test that language override works for click:run directive.

tests.sphinx.test_sphinx_click.test_sphinx_directive_state_persistence(sphinx_app)[source]

Test that state persists between declare and run directives in real Sphinx.

tests.sphinx.test_sphinx_click.test_directive_variable_conflict(var_name, sphinx_app_for_format, content, directive_lineno, error_lineno)[source]

Test that variable conflicts are properly detected in real Sphinx environment.

tests.sphinx.test_sphinx_click.test_exit_exception_percolate(sphinx_app)[source]

Test directives that handle command errors and exit codes.

tests.sphinx.test_sphinx_click.test_clickrunner_forces_color(monkeypatch)[source]

ClickRunner forces FORCE_COLOR so Rich-based CLIs colorize under NO_COLOR.

The runner already passes color=True (Click’s color system). But rich-click renders help through Rich’s Console, gated on FORCE_COLOR, which color=True never reaches. The runner therefore also forces FORCE_COLOR (clearing the disabling vars) around the executed command, then restores the environment.

tests.sphinx.test_sphinx_click.test_clickrunner_capture_mode_controls_fileno(capture, renders)[source]

ClickRunner(capture=...) decides whether a fileno-writing CLI renders.

Click’s "sys" mode backs the captured stream with an in-memory buffer whose fileno() raises io.UnsupportedOperation, so a documented command that re-opens its descriptor (a common UTF-8-on-Windows guard) aborts. "fd" (the default on Unix, also exposed as the click_extra_run_capture conf.py value) backs it with a real descriptor, so the command renders. On Windows, where fd-backed streams are not supported, the default falls back to "sys".

tests.sphinx.test_sphinx_click_tree module

Tests for the click:tree Sphinx directive.

tests.sphinx.test_sphinx_click_tree.KITCHEN_CLI = '```{click:source}\n:hide-source:\nfrom click import command, echo, group, option\n\n@group\ndef kitchen():\n    """Manage kitchen tools and recipes."""\n\n@kitchen.command\n@option("--minutes", type=int, default=5)\ndef boil(minutes):\n    """Boil water for tea."""\n    echo(f"Boiling for {minutes} minutes.")\n\n@kitchen.group\ndef pantry():\n    """Inspect pantry contents."""\n\n@pantry.command\ndef jars():\n    """List jars on the shelf."""\n    echo("Olives, honey, pickles.")\n```\n'

Toy CLI reused across tests. Defines a multi-level group so the walk exercises the recursive descent into nested click.Group commands.

tests.sphinx.test_sphinx_click_tree.test_click_tree_renders_summary_table_and_help_blocks(sphinx_app_myst)[source]

The directive expands into a GFM table + one help capture per command.

tests.sphinx.test_sphinx_click_tree.test_click_tree_inline_import_in_body(sphinx_app_myst)[source]

The directive body runs as a preamble, so a seed click:source is optional.

tests.sphinx.test_sphinx_click_tree.test_click_tree_no_table_and_no_root(sphinx_app_myst)[source]

:no-table: and :no-root: drop the summary table and root block.

tests.sphinx.test_sphinx_click_tree.test_click_tree_max_depth_truncates_walk(sphinx_app_myst)[source]

:max-depth: 1 stops the walk at one level below the root.

tests.sphinx.test_sphinx_click_tree.test_click_tree_label_and_anchor_prefix_override(sphinx_app_myst)[source]

:label-prefix: and :anchor-prefix: override the defaults.

tests.sphinx.test_sphinx_click_tree.test_click_tree_errors_on_non_command(sphinx_app_myst)[source]

Resolving the argument to a non-Command raises a clear directive error.

tests.sphinx.test_sphinx_click_tree.test_click_tree_errors_on_unknown_name(sphinx_app_myst)[source]

An expression that can’t be evaluated raises a clear directive error.

tests.sphinx.test_sphinx_click_tree.test_click_tree_errors_in_rst(sphinx_app_rst)[source]

click:tree raises a clear error when used in an rST document.

tests.sphinx.test_sphinx_click_tree.test_click_tree_heading_offset_defaults_to_top_level(sphinx_app_myst)[source]

Below a single # Doc title the root renders at h2.

Preserves the historical default behavior: a directive at the document body (inside the title’s h1 section) emits its root one level below.

tests.sphinx.test_sphinx_click_tree.test_click_tree_heading_offset_adapts_to_surrounding_section(sphinx_app_myst)[source]

Nested inside an h3 section, the root renders at h4.

The default heading offset is computed from state.memo.section_level so the document outline stays consistent regardless of where the directive is placed.

tests.sphinx.test_sphinx_click_tree.test_click_tree_heading_offset_explicit_override(sphinx_app_myst)[source]

An explicit :heading-offset: wins over the auto-detected default.

Surrounding headings establish a deep level so the override’s effect is clearly observable in the rendered HTML (without MyST normalizing skipped heading levels).

tests.sphinx.test_sphinx_manpages module

Tests for click_extra.sphinx.manpages.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_writes_tree_into_outdir(tmp_path)[source]

An entry with just script writes the whole tree under man/.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_honors_prog_name_and_output_dir(tmp_path)[source]

An entry can override both the basename and the subdirectory.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_skips_non_html_builder(tmp_path)[source]

Non-HTML builders (like linkcheck) must not emit man pages.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_empty_config_is_noop(tmp_path)[source]

An empty list leaves the build untouched.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_skips_entry_without_script(tmp_path)[source]

An entry missing script is skipped (logged as a warning) instead of aborting the build.

tests.sphinx.test_sphinx_manpages.test_manpages_module_help_documents_config_shape()[source]

The module docstring spells out every supported key.

A safety net against silent removal: distributors and downstream projects depend on the docstring as the canonical reference, since it is what help(click_extra.sphinx.manpages) prints.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_emits_html_siblings(tmp_path)[source]

When a renderer is available, every .1 gets a .1.html next to it whose body carries the section headings from the source roff.

tests.sphinx.test_sphinx_manpages.test_manpages_hook_respects_render_html_opt_out(tmp_path)[source]

render_html=False skips the HTML pass even when a renderer is present, keeping the build to roff only.

The directive emits a bullet list with one entry per (sub)command of every script declared in click_extra_manpages.

tests.sphinx.test_sphinx_manpages.test_manpages_directive_is_noop_when_config_empty(tmp_path)[source]

An empty config means no bullet list, no warning, build still finishes.

tests.sphinx.test_sphinx_manpages.test_manpages_directive_renders_inline_literals_as_code(tmp_path)[source]

Inline reST literals in a command’s short_help land as <code> spans in the rendered index, not as raw backticks rendered like quotes.

tests.sphinx.test_sphinx_python module

Tests for the python:* Sphinx directive family.

Covers python:source, python:run, and the three render variants:

  • python:render (host parser)

  • python:render-myst (forced MyST, regardless of host)

  • python:render-rst (forced reST, regardless of host)

tests.sphinx.test_sphinx_python.test_python_run_renders_stdout(sphinx_app_myst)[source]

python:run captures print output and renders it in a code block.

tests.sphinx.test_sphinx_python.test_python_source_seeds_namespace_for_python_run(sphinx_app_myst)[source]

python:source runs silently; a follow-up python:run reuses its imports.

tests.sphinx.test_sphinx_python.test_python_run_language_override(sphinx_app_myst)[source]

:language: overrides the default text lexer for the result block.

tests.sphinx.test_sphinx_python.test_python_run_emphasize_lines_split(sphinx_app_myst)[source]

:emphasize-lines: highlights source only; :emphasize-result-lines: highlights result only: independently, on the same block.

tests.sphinx.test_sphinx_python.test_python_render_passes_block_level_html(sphinx_app_myst)[source]

python:render passes block-level raw HTML through unchanged.

A naked print('<div>...</div>') should reach the rendered page without any {raw} html wrapping. Locks down the natural-form pattern so a future MyST upgrade or extension reordering can’t silently regress it.

tests.sphinx.test_sphinx_python.test_python_render_host_myst_injects_table(sphinx_app_myst)[source]

python:render parses captured stdout with the host (MyST) parser.

tests.sphinx.test_sphinx_python.test_python_render_host_myst_injects_heading(sphinx_app_myst)[source]

A heading printed by python:render becomes a real heading node.

tests.sphinx.test_sphinx_python.test_python_render_host_rst_injects_admonition(sphinx_app_rst)[source]

python:render in an rST host: stdout is parsed as reST.

tests.sphinx.test_sphinx_python.test_python_render_myst_in_rst_host(sphinx_app_rst)[source]

python:render-myst forces MyST parsing inside an rST host document.

This is the headline use case: an rST file embeds Python that prints MyST markup and the directive parses it as MyST regardless of host.

tests.sphinx.test_sphinx_python.test_python_render_rst_in_myst_host(sphinx_app_myst)[source]

python:render-rst forces reST parsing inside a MyST host document.

tests.sphinx.test_sphinx_python.test_python_render_myst_in_myst_host_still_works(sphinx_app_myst)[source]

python:render-myst works in MyST hosts too; it always picks MyST.

tests.sphinx.test_sphinx_python.test_python_render_rst_in_rst_host_still_works(sphinx_app_rst)[source]

python:render-rst works in rST hosts too; it always picks reST.

tests.sphinx.test_sphinx_python.test_exec_directives_disabled_by_default(tmp_path)[source]

Without the opt-in flag, click:* and python:* are not registered.

The Sphinx build still succeeds but neither family’s directive body is ever executed. This is the desired security default: a project that adds click_extra.sphinx to its extensions list does not silently gain build-time arbitrary Python execution.

The exact rendering of an unrecognized directive is parser-dependent (MyST silently swallows it; reST emits a system message), so the assertion focuses on the security-relevant invariant: the directive body’s print output never reaches the rendered HTML.

tests.sphinx.test_sphinx_python.test_exec_directives_enabled_with_opt_in(tmp_path)[source]

Setting click_extra_enable_exec_directives = True activates them.

tests.sphinx.test_sphinx_python.test_python_runner_isolated_from_click_runner(sphinx_app_myst)[source]

The Python and Click runners hold independent namespaces.