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.
- class tests.sphinx.conftest.FormatType(*values)[source]ΒΆ
Bases:
EnumSphinx document format types and their file extensions.
- RST = '.rst'ΒΆ
- MYST = '.md'ΒΆ
- class tests.sphinx.conftest.SphinxAppWrapper(app, format_type)[source]ΒΆ
Bases:
objectWrapper 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_directivesopts the test app into theclick:*andpython:*directive families. Defaults toTruefor 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 toFalseexplicitly.- Return type:
Generator[SphinxAppWrapper|tuple[SphinxAppWrapper,Path],None,None]
- 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_appvariant whose format is supplied by the caller.Identical to
sphinx_app()but without the defaultparams: theFormatTypeis taken from the testβs indirect parametrization. Aparams-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, usually throughformat_params().
- tests.sphinx.conftest.sphinx_app_rst(tmp_path)[source]ΒΆ
Create a Sphinx application for testing RST format only.
The
click:*andpython:*directive families are enabled so tests can exercise them. Tests that explicitly verify the off-by- default opt-in gate construct their own app viaSphinxAppWrapper.create()withenable_exec_directives=False.
- tests.sphinx.conftest.sphinx_app_myst(tmp_path)[source]ΒΆ
Create a Sphinx application for testing MyST format only.
The
click:*andpython:*directive families are enabled: seesphinx_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:
objectTest case data for directive tests.
- format_type: FormatType | None = NoneΒΆ
- tests.sphinx.conftest.format_params(*test_cases)[source]ΒΆ
Pair each test case with every document format it is written for.
Feeds the indirect parametrization of
sphinx_app_for_format(), so a case is only ever built by an app whose format it can render: a case pinned to aFormatTypeyields that format alone, a format-agnostic one yields a parameter per format.- Return type:
- tests.sphinx.conftest.unescape_quotes(text)[source]ΒΆ
Replace quote entities with bare quotes, so both escapings compare equal.
Pygments 2.21.0 replaced its
escape_html()helper withhtml.escape(value, quote=False). Token text carries bare"and'since then, where older releases produced"and'. Both forms render the same, and thepygmentsextra declares a floor spanning that release, so HTML fragments are compared with quotes normalized.- Return type:
- tests.sphinx.conftest.plain_whitespace(text)[source]ΒΆ
Replace whitespace tokens with bare spaces, so both lexings compare equal.
Pygments 2.19.0 made the Python lexer emit some blanks of a
deforfromstatement as whitespace tokens, where older releases leave them as bare text. Both forms render the same, and thesphinxextra declares a floor below that release, so HTML fragments are compared with these tokens flattened.- Return type:
- tests.sphinx.conftest.python_block(*lines)[source]ΒΆ
Build expected Python highlight block.
- Return type:
tests.sphinx.test_sphinx moduleΒΆ
Fixtures and utilities for Sphinx testing.
- tests.sphinx.test_sphinx.test_import_without_myst_parser()[source]ΒΆ
The extension imports in a project that installs no myst-parser.
Sphinx does not depend on
myst-parser, so a project that installs Sphinx without thesphinxextra has none. A hard import of it inclick_extra.sphinxbreaks such a project outright.
- tests.sphinx.test_sphinx.imports_sphinx_package(node)[source]ΒΆ
Whether an import statement reaches
click_extra.sphinxor a module of it.- Return type:
- tests.sphinx.test_sphinx.is_sphinx_guard(call)[source]ΒΆ
Whether the call is
pytest.importorskip("sphinx", ...).- Return type:
- tests.sphinx.test_sphinx.unguarded_sphinx_imports(tree)[source]ΒΆ
Lines importing
click_extra.sphinxthat noimportorskip("sphinx")precedes.A guard covers the rest of the function it is called in, or the whole module when called at its top level.
- tests.sphinx.test_sphinx.test_imports_outside_this_tree_skip_without_sphinx()[source]ΒΆ
Outside
tests/sphinx/, a test skips itself before importing the extension.The
collect_ignore_globof this tree skips it on a builder shipping no Sphinx, and covers no test outside it. Such a test has to callpytest.importorskip("sphinx")before it importsclick_extra.sphinx, or it fails on that builder instead of skipping.
tests.sphinx.test_sphinx_announcement moduleΒΆ
Tests for the year count of an announcement banner.
- tests.sphinx.test_sphinx_announcement.anniversaries(start, day)[source]ΒΆ
Count the anniversaries of
startthatdayhas reached, one at a time.Counted apart from
years_since(), so the test does not grade a formula against itself.startcannot be a 29 February, whichdate.replacecannot move to a common year.- Return type:
- tests.sphinx.test_sphinx_announcement.test_years_since_on_every_day_of_a_leap_span()[source]ΒΆ
The count goes up on each anniversary, and never a day before it.
The span holds the leap days of 2024, 2028 and 2032. Each moves a count of days divided by 365 one day further ahead, which the last assertion checks the span catches.
- Return type:
tests.sphinx.test_sphinx_changelog moduleΒΆ
Tests for the anchors of changelog releases.
- tests.sphinx.test_sphinx_changelog.MYST_CHANGELOG = '# Changelog\n\nSee the [next release](#v1-5-0).\n\n## [`1.5.0.dev0` (unreleased)](https://example.com/compare/v1.4.2...main)\n\n- Plant a pear tree.\n\n## [`1.4.2` (2026-03-15)](https://example.com/compare/v1.4.1...v1.4.2)\n\n- Prune the apple trees.\n\n## `1.4.1` (2026-02-01)\n\n- Water the plums.\n'ΒΆ
A MyST changelog, one release titled as a link, one as plain text.
- tests.sphinx.test_sphinx_changelog.LETTERLESS_CHANGELOG = '# 2026\n\n## `1.4.2` (2026-03-15)\n\n- Prune the apple trees.\n\n## `1.4.1` (2026-02-01)\n\n- Water the plums.\n'ΒΆ
A MyST changelog whose headings all have no letters, so no heading slug.
- tests.sphinx.test_sphinx_changelog.RST_CHANGELOG = 'Changelog\n=========\n\n1.5.0.dev0 (unreleased)\n-----------------------\n\n- Plant a pear tree.\n\n1.4.2 (2026-03-15)\n------------------\n\n- Prune the apple trees.\n\n1.4.1 (2026-02-01)\n------------------\n\n- Water the plums.\n'ΒΆ
The same changelog in reStructuredText.
- tests.sphinx.test_sphinx_changelog.ORCHARD_PAGE = '# Orchard\n\nThe trees were [last pruned](changelog.md#v1-4-2).\n'ΒΆ
A MyST page linking to a release of the changelog page.
- tests.sphinx.test_sphinx_changelog.build(tmp_path, pages, *, anchors=None)[source]ΒΆ
Build
pages, a map of file names to sources, and return the output.anchorssetsRELEASE_ANCHORS_CONFIG, left to its default whenNone. Returns the output directory and the warning stream.
- tests.sphinx.test_sphinx_changelog.test_release_heading(title, version)[source]ΒΆ
Only a title made of a full version and a parenthesized label matches.
- tests.sphinx.test_sphinx_changelog.test_releases_are_anchored_on_their_version(tmp_path, page)[source]ΒΆ
Each release section takes its version as ID, the one in preparation too.
- tests.sphinx.test_sphinx_changelog.test_links_resolve_to_version_anchors(tmp_path)[source]ΒΆ
A link to a version anchor resolves, from the changelog and from another page.
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_for_format, test_case)[source]ΒΆ
Test standard directive functionalities in each format a case targets.
- 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.GENERATED_BLOCK_ANCHOR = 'from click_extra import command, echo'ΒΆ
First body line of the
GENERATED_BLOCK_LINE_CASESdocuments below.The line a generated block is expected to be attributed to, located in the document itself so editing a case moves the expectation with it.
- tests.sphinx.test_sphinx_click.test_generated_block_is_attributed_to_the_directive_body(sphinx_app_for_format, test_case)[source]ΒΆ
A block a directive generates is attributed to its first body line.
The generated lines exist nowhere in the document, so the parser has to be told which document line to hang a diagnostic raised inside them on. Both formats must answer the same way, and neither is free to fall back on its own default: docutils numbers an unlabelled block from the top of the file, and
myst-parsermeasures its offsets from the directive rather than the document.The last two cases carry both an option block and a body ending in blank lines, whose
content_offsetmyst-parser5.1.0and older over-counted by one.
- 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]ΒΆ
ClickRunnerforcesFORCE_COLORso Rich-based CLIs colorize underNO_COLOR.The runner already passes
color=True(Clickβs color system). But rich-click renders help through RichβsConsole, gated onFORCE_COLOR, whichcolor=Truenever reaches. The runner therefore also forcesFORCE_COLOR(clearing the disabling vars) around the executed command, then restores the environment.
- tests.sphinx.test_sphinx_click.test_clickrunner_sets_the_handlers_of_the_build_aside()[source]ΒΆ
ClickRunnertakes the handlers it found on the root logger off it while a documented command runs, then puts them back.A build shares its process with Sphinx, its extensions and its theme. A handler one of them gave the root logger would print each record of the command a second time, which the shell of a reader never does.
- tests.sphinx.test_sphinx_click.test_clickrunner_sets_the_level_of_the_build_aside(document_level, expected)[source]ΒΆ
ClickRunnergives the root logger the default level while a documented command runs, where the build left another one, then gives that one back.A command leaves the root logger at the level it found. The level of the build would so let through what a command logs before its verbosity options apply, which the shell of a reader never prints.
- tests.sphinx.test_sphinx_click.test_clickrunner_capture_mode_controls_fileno(capture, renders)[source]ΒΆ
ClickRunner(capture=...)decides whether a CLI callingfileno()renders.Clickβs
"sys"mode backs the captured stream with an in-memory buffer whosefileno()raisesio.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 theclick_extra_run_captureconf.py value) returns a copy of the original stdout descriptor, so the command runs and itsclick.echooutput renders. What it writes through that copy does not, seetest_clickrunner_captures_prep_path_stdout. On Windows, where fd-backed streams are not supported, the default falls back to"sys".
- tests.sphinx.test_sphinx_click.test_clickrunner_captures_prep_path_stdout(capture)[source]ΒΆ
A command writing to
-throughprep_pathrenders in every capture mode.Under
"fd",sys.stdout.fileno()returns a copy of the original stdout descriptor, so a stream opened on it writes past the capture.
- tests.sphinx.test_sphinx_click.test_program_from_command_line(command_line, expected)[source]ΒΆ
Only an interpreter prefix is dropped from a displayed command line.
- tests.sphinx.test_sphinx_click.test_clickrunner_keeps_a_multi_word_prog_name(monkeypatch)[source]ΒΆ
A subcommand-shaped program name reaches the command it runs, whole.
- tests.sphinx.test_sphinx_click.test_clickrunner_prompt_inlines_environment_assignments(monkeypatch)[source]ΒΆ
Variables are set on the invocation, the way the runner applies them.
CliRunnerscopesenvto the one call, so anexportline would advertise a persistence the next block does not inherit.
- tests.sphinx.test_sphinx_click.test_clickrunner_prompt_quotes_a_spaced_argument(monkeypatch)[source]ΒΆ
An argument holding spaces stays the single token a reader must type.
- tests.sphinx.test_sphinx_click.test_clickrunner_hide_prompt_drops_the_invocation(monkeypatch)[source]ΒΆ
_show_prompt=Falseleaves the output alone and drops the line above it.
- tests.sphinx.test_sphinx_click.test_clickrunner_prompt_past_the_input_aborts(monkeypatch, terminate_input)[source]ΒΆ
A prompt reading past the end of the input aborts, as it does under Click.
The read past the end returns no byte at all, which the echoing stream has to pass through rather than look for a
^Din.
- tests.sphinx.test_sphinx_click.test_click_run_prompt_options(sphinx_app_myst, options, prompted)[source]ΒΆ
:show-prompt:/:hide-prompt:gate the invocation line.
- tests.sphinx.test_sphinx_click.test_click_run_output_holding_a_fence_stays_in_its_block(sphinx_app_myst)[source]ΒΆ
Output carrying a code fence of its own renders whole in the result block.
A fixed three-backtick fence closes on the outputβs own bare fence line, and MyST then parses the rest of the output as part of the page.
- tests.sphinx.test_sphinx_click.test_code_fence_outgrows_the_fences_it_wraps(lines, fence)[source]ΒΆ
The fence is one backtick longer than any run opening a line, at least three.
- tests.sphinx.test_sphinx_click.test_click_run_hide_prompt_reaches_the_screenshot(sphinx_app_myst)[source]ΒΆ
A capture is drawn from the same lines, so it loses the prompt too.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_writes_the_asset(sphinx_app_myst)[source]ΒΆ
:screenshot:writes the capture beside the documentation.The image is a side effect: the page keeps its results code block, which inside Sphinx beats an image by staying selectable and searchable.
- tests.sphinx.test_sphinx_click.ANIMATED_SOURCE = '\n ```{click:source}\n :hide-source:\n from click_extra import SPINNERS, Spinner, Style, command, echo\n\n @command\n def greet():\n echo("Hello, papaya!")\n\n steeping = Spinner("Steeping", spinner=SPINNERS["moon"], style=Style(fg="green"))\n ```\n'ΒΆ
A spinner and a CLI, seeded for the animated-capture blocks below.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_stacks_a_spinner(sphinx_app_myst)[source]ΒΆ
:screenshot-animate:draws every frame of the spinner it names.The frames and the interval are taken off the spinner itself, so the picture and the animation cannot disagree about either.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_defines_every_class_it_uses(sphinx_app_myst)[source]ΒΆ
No frame names a class the animated capture leaves undefined.
A frame whose rules are missing does not vanish: it falls back to the presentation attributes and draws in the wrong face and the wrong color, which reads as the animation resetting its styling once a cycle.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_accepts_bare_frames(sphinx_app_myst)[source]ΒΆ
A sequence of texts animates too, timed by
:screenshot-interval:.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_line_numbers_give_every_frame_one_gutter(sphinx_app_myst)[source]ΒΆ
A frame reaching ten rows does not push its text a cell to the right.
Each frame counts its own rows, from one. Numbered on its own, the nine-row frame aligns its numbers on one digit and the ten-row frame on two, so every row moves between the two frames.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_bare_frames_need_an_interval(sphinx_app_myst)[source]ΒΆ
Bare frames carry no timing of their own, so one has to be stated.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_rejects_a_foreign_subject(sphinx_app_myst)[source]ΒΆ
Something that is neither a spinner nor frames fails the build.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_is_deterministic(sphinx_app_myst)[source]ΒΆ
A declared subject composes the same lines on every build.
This is what lets an animated capture be committed at all: a recording would time its frames a little differently on every run and dirty the tree.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_rewrites_a_declared_asset(sphinx_app_myst)[source]ΒΆ
A declared animation is regenerated on every build, like any capture.
It composes the same lines every time, so the file only changes with the code, and regenerating it is what keeps the asset from drifting away from that code. Gating the write on what the animation is would freeze out every change to how it is drawn.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_animate_carries_a_presentation_change(sphinx_app_myst)[source]ΒΆ
Restating how an animation is drawn reaches the committed asset.
The frames are untouched by a margin, so nothing about what the animation is moves. The picture still has to change.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_leaves_an_unchanged_asset_alone(sphinx_app_myst, name, options)[source]ΒΆ
A rebuild drawing the same capture does not write the file again.
Writing the same bytes would still move the modification time of the file, which a tool watching the documentation tree reads as a change. A capture that differs is still written.
- tests.sphinx.test_sphinx_click.RECORDED_SOURCE = '\n ```{click:source}\n :hide-source:\n from click_extra.capture.recording import Frame\n\n kettle = [Frame("filling", 0.2), Frame("boiled", 0.2)]\n ```\n'ΒΆ
A stand-in recording: frames carrying their own durations, as one does.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_record_writes_once(sphinx_app_myst)[source]ΒΆ
A recorded animation is written the first time and then left alone.
Which spinner glyph pairs with which screen is settled by the scheduler, so a recording cannot be reproduced and rewriting it would dirty the working tree for nothing anyone did.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_record_holds_its_last_frame(sphinx_app_myst)[source]ΒΆ
A recording pauses on its final screen before starting over.
An animation that ends somewhere is worth reading, and a loop restarting the instant it arrives never lets anyone.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_hold_overrides_the_pause(sphinx_app_myst)[source]ΒΆ
:screenshot-hold:states the pause a page would rather have.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_blank_closes_the_cycle(sphinx_app_myst)[source]ΒΆ
A recording ends on an empty beat, so the loopβs turnover is visible.
Without it, a loop jumping from its last frame back to its first reads as one long animation doing something odd rather than as a repetition.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_speed_scales_the_recorded_frames(sphinx_app_myst)[source]ΒΆ
:screenshot-speed:replays faster, leaving the pauses as stated.The pauses are how long a reader is given, not part of what is replayed, so they are stated in real seconds and speed does not touch them.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_emphasize_lines_bands_a_still(sphinx_app_myst)[source]ΒΆ
:screenshot-emphasize-lines:draws a band behind the lines it names.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_emphasize_lines_bands_an_animation(sphinx_app_myst)[source]ΒΆ
A band marks a row of the screen, so an animation keeps it throughout.
Drawn once behind every frame rather than per frame: the emphasis is on the row, not on whatever a given frame happened to put there.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_emphasize_lines_rejects_a_line_that_is_not_there(sphinx_app_myst)[source]ΒΆ
Naming a line the capture never drew fails the build rather than passing.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_background(sphinx_app_myst)[source]ΒΆ
:screenshot-background:draws the capture on the chrome it names.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_columns_auto(sphinx_app_myst)[source]ΒΆ
:screenshot-columns: autowidens the image to what the block printed.Click wraps a CLIβs own text at its fixed width whatever the option says. What it decides is the picture, and a line the CLI never wrapped (the prompt of a long invocation) is the one that needs the room.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_columns_rejects_an_unusable_width(value)[source]ΒΆ
A width narrower than the floor, or no width at all, is a build error.
The option reads through the parser the capture commands share, so the two reject the same widths with the same words.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_frame_options(sphinx_app_myst)[source]ΒΆ
The
:screenshot-*:options restate the window, the title included.The hex color is quoted because a directiveβs options are read as YAML, where an unquoted
#opens a comment and leaves the option empty.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_preset_swaps_the_prompt(sphinx_app_myst)[source]ΒΆ
A capture drawn as another terminal prompts the way that one does.
A block runs under a documentation build, so its own prompt is this platformβs
$. The picture is of a Windows terminal, whose shell prompts with something else entirely.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_preset_defaults_to_the_project_wide_one(sphinx_app_myst)[source]ΒΆ
A project drawing every capture as the same terminal states it once.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_carries_no_watermark_by_default(sphinx_app_myst)[source]ΒΆ
A capture a
click:runblock writes carries no credit line by default.The
screenshotcommand credits click-extra on every image it writes. A blockβs image sits on a page that already says what drew it.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_watermark(sphinx_app_myst)[source]ΒΆ
A project wanting its captures credited states the line once.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_opacity(sphinx_app_myst)[source]ΒΆ
A see-through window lets the page it is laid on show through its body.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_opacity_rejects_what_is_not_one(argument)[source]ΒΆ
Anything outside the zero-to-one range fails the build instead of clamping.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_timing_options_take_a_positive_number(option, argument, expected)[source]ΒΆ
A duration, a pace or a speed of zero or less fails the build.
- tests.sphinx.test_sphinx_click.test_click_run_screenshot_background_rejects_an_unknown_chrome()[source]ΒΆ
A typo names the chromes it could have been, instead of drawing a default.
- tests.sphinx.test_sphinx_click.test_click_run_mirror_region_round_trips()[source]ΒΆ
:mirror:inserts an image link below the fence, then leaves it alone.
- tests.sphinx.test_sphinx_click.test_click_run_mirror_needs_both_options()[source]ΒΆ
A block missing either option gets no region.
:screenshot:alone maintains an asset some other surface embeds, without putting it on this page;:mirror:alone has no capture to point at.
- tests.sphinx.test_sphinx_click.test_click_run_mirror_skips_a_nested_example()[source]ΒΆ
A
click:runshown inside a longer fence is documentation, not a block.
- tests.sphinx.test_sphinx_click.test_update_screenshot_blocks_writes_and_checks(tmp_path)[source]ΒΆ
The file-level refresher reports a stale page, then writes its region.
checkleaves the page alone, a write links the capture under the given directory, and a page already current is not reported again.
- tests.sphinx.test_sphinx_click.test_click_source_screenshot_pictures_its_own_code(sphinx_app_myst)[source]ΒΆ
A source blockβs
:screenshot:draws the code it declares.A directive that runs something has output worth committing; one that only declares code has none, so its subject is the code itself.
- tests.sphinx.test_sphinx_click.test_click_source_screenshot_takes_a_syntax_style(sphinx_app_myst)[source]ΒΆ
:screenshot-syntax-style:repaints the window along with the code.
- tests.sphinx.test_sphinx_click.test_click_source_screenshot_bands_its_emphasized_lines(sphinx_app_myst)[source]ΒΆ
:emphasize-lines:marks the same lines on the page and in the image.A source block has one content, so saying it twice would be the surprise.
- tests.sphinx.test_sphinx_click.test_click_source_screenshot_is_deterministic(sphinx_app_myst)[source]ΒΆ
Two builds of one source block write the same bytes.
Nothing here runs a command or reads a clock, so a committed asset stays put and leaves the working tree clean.
tests.sphinx.test_sphinx_click_config moduleΒΆ
Tests for the click:config Sphinx directive.
- class tests.sphinx.test_sphinx_click_config.BasketConfig(apples=3)[source]ΒΆ
Bases:
objectNested sub-table exercising the dotted-key expansion.
- class tests.sphinx.test_sphinx_click_config.MarketConfig(city='Lisbon', stalls=<factory>, basket=BasketConfig())[source]ΒΆ
Bases:
objectToy schema reused across tests.
Defined at module level (not inside a
click:sourceblock) soinspect.getsourcecan recover the attribute docstrings.- city: str = 'Lisbon'ΒΆ
City where the market is held.
The market moves to the main square during summer, and to the covered hall the rest of the year.
- basket: BasketConfigΒΆ
Parent table docstring, never rendered: only leaves get sections.
- tests.sphinx.test_sphinx_click_config.MARKET_SEED = '```{click:source}\n:hide-source:\nfrom tests.sphinx.test_sphinx_click_config import market\n```\n'ΒΆ
Seed block importing the module-level CLI into the runner namespace.
- class tests.sphinx.test_sphinx_click_config.PastryConfig(creme_brulee='vanilla|caramel', five_spice=5)[source]ΒΆ
Bases:
objectSchema whose keys need slugging and whose default needs escaping.
- tests.sphinx.test_sphinx_click_config.PASTRY_CONFIG = '\n```{click:config} PastryConfig\nfrom tests.sphinx.test_sphinx_click_config import PastryConfig\n```\n'ΒΆ
Directive documenting
PastryConfig.
- tests.sphinx.test_sphinx_click_config.test_click_config_default_and_toml_literal(value, default, literal)[source]ΒΆ
A default renders in the table, and as the literal of its TOML example.
- tests.sphinx.test_sphinx_click_config.test_click_config_renders_table_and_sections(sphinx_app_myst)[source]ΒΆ
The directive expands into a summary table + one section per option.
- tests.sphinx.test_sphinx_click_config.test_click_config_links_every_option_to_its_section(sphinx_app_myst)[source]ΒΆ
Each table link lands on the id docutils gives the optionβs heading.
make_idwrites the accented letters ofcrème-brûléeas their ASCII base, and drops the leading digit of5-spice.
- tests.sphinx.test_sphinx_click_config.test_click_config_keeps_a_piped_default_in_its_cell(sphinx_app_myst)[source]ΒΆ
A pipe in a default value stays text, rather than splitting its row.
- tests.sphinx.test_sphinx_click_config.test_click_config_toml_examples(sphinx_app_myst)[source]ΒΆ
Each option gets a TOML example pinned to its default value.
The section header defaults to
tool.{cli-name}, matching how click-extra and its downstream CLIs read their section frompyproject.toml.
- tests.sphinx.test_sphinx_click_config.test_click_config_section_override_and_suppress(sphinx_app_myst)[source]ΒΆ
:section:overrides the example header; an empty value drops it.
- tests.sphinx.test_sphinx_click_config.test_click_config_bare_schema_argument(sphinx_app_myst)[source]ΒΆ
A dataclass argument documents the schema without any CLI wired.
Without a CLI there is no name to derive the section header from, so the examples render bare assignments.
- tests.sphinx.test_sphinx_click_config.test_click_config_no_table_and_no_examples(sphinx_app_myst)[source]ΒΆ
:no-table:and:no-examples:drop their blocks.
- tests.sphinx.test_sphinx_click_config.test_click_config_exec_defined_schema_lacks_docstrings(sphinx_app_myst)[source]ΒΆ
A schema defined in an execβd block renders without descriptions.
- tests.sphinx.test_sphinx_click_config.test_click_config_errors_without_schema(sphinx_app_myst)[source]ΒΆ
A CLI with no
config_schemaraises a clear directive error.
- tests.sphinx.test_sphinx_click_config.test_click_config_errors_on_non_schema(sphinx_app_myst)[source]ΒΆ
Resolving the argument to a non-dataclass raises a clear error.
- tests.sphinx.test_sphinx_click_config.test_click_config_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_config.test_click_config_errors_in_rst(sphinx_app_rst)[source]ΒΆ
click:configraises a clear error when used in an rST document.
- tests.sphinx.test_sphinx_click_config.test_click_config_heading_offset_adapts_to_surrounding_section(sphinx_app_myst)[source]ΒΆ
Nested inside an
h2section, option headings render ath3.
- class tests.sphinx.test_sphinx_click_config.OrchardConfig(trees=12, rows=4, seasons=<factory>)[source]ΒΆ
Bases:
objectSchema whose docstrings make Markdown headings, or look like they do.
- tests.sphinx.test_sphinx_click_config.test_click_config_warns_on_docstring_heading(sphinx_app_myst)[source]ΒΆ
Each heading in an option docstring is reported at its docstring line.
The lone
=makes a setext heading of the paragraph above it,# Pruningis an ATX heading, and the lines of a code block are no heading at all.
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.Groupcommands.
- 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:sourceis 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: 1stops 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_summary_keeps_a_piped_description_in_its_cell(sphinx_app_myst)[source]ΒΆ
A pipe in a commandβs summary stays text, rather than splitting its row.
- tests.sphinx.test_sphinx_click_tree.test_click_tree_summary_shows_the_whole_description(sphinx_app_myst)[source]ΒΆ
A summary past Clickβs 45-character cut shows whole in its cell.
get_short_help_str()cuts there and appends an ellipsis, and the strip of the final period removed that ellipsis, which hid the cut. An ellipsis the author wrote stays.
- tests.sphinx.test_sphinx_click_tree.test_click_tree_links_every_command_to_its_own_section(sphinx_app_myst)[source]ΒΆ
Each row links to the id of its section, and no two rows share one.
The anchor is the id docutilsβ
make_idderives, which writes the accented letter ofcrèmeas its ASCII base. Slugged one name at a time,make_idwould also drop the leading digit of5-spiceand7-spice, and give both the anchor of aspicecommand.
- tests.sphinx.test_sphinx_click_tree.test_click_tree_walks_subcommands_like_the_tree_option(sphinx_app_myst)[source]ΒΆ
The walk lists what
Group.list_commandsreturns, as--treedoes.A lazy subcommand is documented although the group never registers it, in the order the group lists it, and a hidden one is left out.
- 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:treeraises 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 titlethe root renders ath2.A directive in 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
h3section, the root renders ath4.The default heading offset is computed from
state.memo.section_levelso 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_crosshair moduleΒΆ
Tests for the crosshair of two-axis tables.
- tests.sphinx.test_sphinx_crosshair.test_crosshair_ships_with_every_page(sphinx_app_myst)[source]ΒΆ
Every page links the stylesheet and the script, written from their sources.
The static folder they share with the table stylesheet is listed once.
- Return type:
- tests.sphinx.test_sphinx_crosshair.test_script_targets_corner_tables_only()[source]ΒΆ
The script selects the tables
click_extra.sphinx.tablesmarks.- Return type:
tests.sphinx.test_sphinx_doctrees moduleΒΆ
Tests for the document each node of a pickled page belongs to.
- tests.sphinx.test_sphinx_doctrees.test_pickled_nodes_belong_to_their_page(sphinx_app_myst, block)[source]ΒΆ
Every node of a pickled page belongs to the pageβs document.
Each block parses a list in a document of its own, then moves it into the page. docutils points the list at the page, and leaves each item below it pointing at the document it was parsed in.
tests.sphinx.test_sphinx_fail_on_warnings moduleΒΆ
Tests for failing a Sphinx build on the warning types a project lists.
- tests.sphinx.test_sphinx_fail_on_warnings.DEAD_LABEL_PAGE = 'Orchard\n=======\n\nSee :ref:`the-walled-garden`.\n'ΒΆ
A reStructuredText page whose one defect is an undefined label:
ref.ref.
- tests.sphinx.test_sphinx_fail_on_warnings.CLEAN_PAGE = 'Orchard\n=======\n\nApples ripen in autumn.\n'ΒΆ
The same page, without the defect.
- tests.sphinx.test_sphinx_fail_on_warnings.DEAD_FRAGMENT_PAGE = '# Orchard\n\nSee [the walled garden](#the-walled-garden).\n'ΒΆ
A MyST page whose one defect is a link to no anchor:
myst.xref_missing.
- tests.sphinx.test_sphinx_fail_on_warnings.build(tmp_path, page, *, listed=None, suppressed=None, suffix='.rst')[source]ΒΆ
Build a one-page project, and return its exit status and warning stream.
- tests.sphinx.test_sphinx_fail_on_warnings.test_listed_types_decide_the_exit_status(tmp_path, listed, suppressed, status)[source]ΒΆ
A warning fails the build only when its type is listed and not suppressed.
- tests.sphinx.test_sphinx_fail_on_warnings.test_clean_build_passes(tmp_path)[source]ΒΆ
A listed type fails nothing while no warning of that type is logged.
- tests.sphinx.test_sphinx_fail_on_warnings.test_error_counts_each_warning_once(tmp_path)[source]ΒΆ
The error names the matched type, and counts a replayed warning once.
tests.sphinx.test_sphinx_linkcheck moduleΒΆ
Tests for the github.com authentication of the linkcheck builder.
- tests.sphinx.test_sphinx_linkcheck.ORCHARD_AUTH = ('https://orchard\\.example\\.com/', ('gardener', 'spade'))ΒΆ
A
linkcheck_authentry a project declares in its ownconf.py.
- tests.sphinx.test_sphinx_linkcheck.linkcheck_auth(tmp_path, entries)[source]ΒΆ
Start a
linkcheckbuild of a project declaringentries.
- tests.sphinx.test_sphinx_linkcheck.test_auth_entry_follows_the_project_ones(tmp_path, monkeypatch)[source]ΒΆ
With a token, the github.com entry comes after the entries of
conf.py.Sphinx signs a request with the first entry matching its URL, so a project entry keeps precedence.
- Return type:
- tests.sphinx.test_sphinx_linkcheck.test_no_auth_entry_without_a_token(tmp_path, monkeypatch, token)[source]ΒΆ
Without a token,
linkcheck_authholds the entries ofconf.pyalone.- Return type:
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
scriptwrites the whole tree underman/.
- 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
scriptis 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
.1gets a.1.htmlnext 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=Falseskips the HTML pass even when a renderer is present, keeping the build to roff only.
- tests.sphinx.test_sphinx_manpages.test_manpages_directive_renders_one_link_per_command(tmp_path)[source]ΒΆ
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_links_are_ignored_by_linkcheck(tmp_path)[source]ΒΆ
linkcheckignores the links of the index instead of reporting them broken.Only an HTML build writes the pages they point at, while
linkchecklooks for a relative link in the source tree, where those pages never are.
- tests.sphinx.test_sphinx_manpages.test_manpages_directive_links_follow_the_builder_layout(tmp_path, builder, page_file, prefix)[source]ΒΆ
Links resolve from wherever the builder publishes the page.
A second builder reusing pickled doctrees still gets its own layout.
Sphinx does not invalidate its doctree cache when the builder changes, so the directive never re-runs on the second pass. A link resolved at parse time would keep the first builderβs layout and point at nothing.
tests.sphinx.test_sphinx_matrix moduleΒΆ
Tests for click_extra.sphinx.matrix.
Split in two halves: the dependency-light matrix-generation logic (git tag
walking, spec parsing, floor filtering) and the matrix Sphinx directive
that surfaces it. Both live under tests/sphinx/ because importing
click_extra.sphinx.matrix pulls in the Sphinx package; the sibling
conftest.py skips the whole tree when Sphinx or MyST-Parser is absent.
- tests.sphinx.test_sphinx_matrix.pytestmark = MarkDecorator(mark=Mark(name='skipif', args=(False,), kwargs={'reason': 'matrix generation walks git tags, so the whole module needs a git binary'}))ΒΆ
Skip the module when git is missing, instead of failing every test.
The sibling
conftest.pyskips the tree when Sphinx or MyST-Parser is absent. Git is the third thing this module needs, and the only one that is a binary rather than an import, so that guard cannot cover it.
- tests.sphinx.test_sphinx_matrix.MATRIX_MODULE = 'click_extra.sphinx.matrix'ΒΆ
Dotted path the PyPI lookup is patched through.
Importing the module object instead would put a
matrixname in scope, and ruff would then read every{matrix}fence in the fixtures as an f-string.
- tests.sphinx.test_sphinx_matrix.LABEL_DATE_RE = re.compile(' \\(\\d{4}-\\d{2}-\\d{2}\\)')ΒΆ
The first-release date a row label carries after its lower bound.
- tests.sphinx.test_sphinx_matrix.WIDGET_CORNER = '`proj` β΄ \\\\ `widget` β'ΒΆ
Top-left cell of a
projtable trackingwidget, backslash escaped.
- tests.sphinx.test_sphinx_matrix.offline_pypi(monkeypatch)[source]ΒΆ
Anchor every table on
uv.lock, with no call to PyPI.The fixtures track a made-up
widgetdependency, and a real project of that name on PyPI would move their columns. The tests of the PyPI anchor stub the lookup again with the releases they need.- Return type:
- tests.sphinx.test_sphinx_matrix.unreadable_pypi(monkeypatch)[source]ΒΆ
Make every PyPI lookup fail, over the read
offline_pypistubs.The lookup answers
requiredthe way the real one does: a required read raises, and any other read returns no release.- Return type:
- tests.sphinx.test_sphinx_matrix.git_repo(path)[source]ΒΆ
Initialize a bare-bones git repository at
path.Returns a
run(*args)helper executing commands in that working tree, so each fixture only spells out the commits and tags it cares about.
- tests.sphinx.test_sphinx_matrix.dated_tag(repo, tag, date)[source]ΒΆ
Commit the working tree of
repoondateand tag ittag.The dates decide when a range was superseded, which the undeclared cells of both axes read.
- Return type:
- tests.sphinx.test_sphinx_matrix.declare_python(repo, spec, *classifiers)[source]ΒΆ
Write a
pyproject.tomldeclaringrequires-pythonand classifiers.- Return type:
- tests.sphinx.test_sphinx_matrix.declare_widget(repo, spec)[source]ΒΆ
Write a
pyproject.tomlrequiringwidget{spec}.Picks whichever dialect can express the range: Poetryβs caret and tilde are not valid PEP 508, so they only ever appear in Poetryβs own table.
- Return type:
- tests.sphinx.test_sphinx_matrix.named_repo(path, pyproject)[source]ΒΆ
Tag one release in a git repository at
path, then leavepyprojectas its working-treepyproject.toml, or no such file forNone.The tagged file declares the Python support a matrix renders. The working-tree file is the one the default package label is read from.
- Return type:
- tests.sphinx.test_sphinx_matrix.table_cells(line)[source]ΒΆ
Split one line of a rendered GFM matrix into its stripped cells.
- tests.sphinx.test_sphinx_matrix.table_header(table)[source]ΒΆ
Return the header cells of a rendered GFM matrix, corner label first.
- tests.sphinx.test_sphinx_matrix.tagged_table_rows(table)[source]ΒΆ
Parse a rendered GFM matrix into
{row label: [cellsβ¦]}.Lets a test assert a whole row at once (spec, then the full
β/βvector) instead of probing the table for loose substrings. The key drops the first-release date of the label, since the fixtures tag their commits on the day the test runs.
- tests.sphinx.test_sphinx_matrix.test_python_versions_released_by_default_table()[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_versions_released_by_sorted_ascending()[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_versions_released_by_custom_table()[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_release_dates_shape()[source]ΒΆ
Every entry must be
X.Yβ ISO date string.- Return type:
- tests.sphinx.test_sphinx_matrix.synthetic_repo(tmp_path)[source]ΒΆ
Build a tiny git repo with two tagged commits declaring different Python support sets, so
python_matrix_groupssees an evolution.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_synthetic(synthetic_repo)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_returns_named_tuple(synthetic_repo)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_reads_a_tag_that_is_no_utf8(synthetic_repo)[source]ΒΆ
A tag name that does not decode as UTF-8 leaves the walk going.
The tag goes in
packed-refs: a loose ref is a file, and APFS refuses a file name that is no UTF-8.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_no_tags(tmp_path)[source]ΒΆ
A repo with no matching tags returns an empty list.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_version_floor(synthetic_repo)[source]ΒΆ
version_floordrops release tags below the bare version.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_ceiling_honored(tmp_path)[source]ΒΆ
A declared
<X.Yceiling excludes those versions fromβ.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_keeps_declared_spec(synthetic_repo)[source]ΒΆ
Each group carries its raw
requires-pythonnext to the set it attests, since the two drive different cells.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_groups_respelled_floor_continues_range(tmp_path)[source]ΒΆ
Re-spelling a floor-only
requires-pythondoes not end its range.The range lasts until
2.0.0, after Python 3.11 and 3.12 came out, so its capped support includes both. Split at the re-spelling, its older half would end in June 2022, before 3.11, and read 3.10 alone.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_cell_spec_shapes(spec, version, expected)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_three_states(tmp_path)[source]ΒΆ
A release claiming less than its floor allows renders all three cells.
The classifiers stop at 3.11 while
requires-pythononly rules out everything under 3.10, so 3.12 is neither supported nor forbidden.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_synthetic(synthetic_repo)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_show_date(synthetic_repo, show_date)[source]ΒΆ
show_datefollows each row label with its first release date.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_column_order(synthetic_repo, column_order)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_row_order(synthetic_repo, row_order)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_invalid_order(synthetic_repo)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_python_floor(synthetic_repo)[source]ΒΆ
python_floortrims the low Python columns from the header.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_empty(tmp_path)[source]ΒΆ
An empty repo produces the empty string, matching the
if not groups: return ""early exit.- Return type:
- tests.sphinx.test_sphinx_matrix.split_floor_repo(tmp_path)[source]ΒΆ
A repo raising its Python floor in the
1.0.1patch release.The newest release supports 3.11 and later, and
1.0.0only 3.9, so the support envelope starts at1.0.1, inside the1.0minor series.- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_envelope(split_floor_repo)[source]ΒΆ
The ranges below the oldest one supporting the floor or a later Python go.
The oldest columns, which no remaining range supports, go with them.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_python_matrix_table_full_history(split_floor_repo)[source]ΒΆ
The full history keeps every range and every column.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_matrix_directive_full_history_option(sphinx_app_myst, split_floor_repo, full_history)[source]ΒΆ
:full-history:keeps the releases the envelope leaves out.- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_full_history_marker(split_floor_repo, tmp_path)[source]ΒΆ
The
full-historymarker flag keeps the releases the envelope drops.- Return type:
- tests.sphinx.test_sphinx_matrix.test_matrix_python_directive_renders_table(sphinx_app_myst, synthetic_repo)[source]ΒΆ
{matrix} pythonrenders the generated table as a real<table>.- Return type:
- tests.sphinx.test_sphinx_matrix.test_matrix_python_directive_respects_floors(sphinx_app_myst, synthetic_repo)[source]ΒΆ
The hyphenated directive options map to the floor parameters.
- tests.sphinx.test_sphinx_matrix.test_matrix_python_directive_order_options(sphinx_app_myst, synthetic_repo)[source]ΒΆ
The
:column-order:/:row-order:options flip both axes.
- tests.sphinx.test_sphinx_matrix.test_matrix_python_directive_no_tags_renders_nothing(sphinx_app_myst, tmp_path)[source]ΒΆ
A repository with no release tags yields no table (a build warning).
- tests.sphinx.test_sphinx_matrix.test_matrix_python_directive_renders_embedded_table(sphinx_app_myst)[source]ΒΆ
An embedded table renders as a real
<table>without any git access.This is the self-updating steady state: the offline updater keeps the table in the source, and the build renders that copy verbatim.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_populates_empty_block(synthetic_repo, tmp_path)[source]ΒΆ
The updater fills an empty block, keeping options and surrounding text.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_idempotent(synthetic_repo, tmp_path)[source]ΒΆ
A second run over freshly written blocks reports no change.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_check_mode(synthetic_repo, tmp_path)[source]ΒΆ
check=Trueflags a stale block without writing to disk.- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_leaves_bad_path_untouched(tmp_path)[source]ΒΆ
A block whose git generation fails is left byte-for-byte unchanged.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_keeps_other_line_separators(tmp_path)[source]ΒΆ
Prose holding a line separator other than a newline is copied verbatim.
A Unicode line separator splits a line for
str.splitlines, not for a Markdown reader: a refresh writing it back as a newline would rewrite the page, and report it stale on every check.- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_leaves_an_unreadable_pypi_untouched(synthetic_dep_repo, tmp_path, unreadable_pypi)[source]ΒΆ
An unreachable PyPI is a generation failure, not a stale block.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_skips_examples_nested_in_code_block(synthetic_repo, tmp_path)[source]ΒΆ
Matrix examples shown inside a longer code fence are never refreshed.
Both forms are documented illustrations here, not live blocks, even though their generation would succeed: the fence-aware walk copies them verbatim.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_refresh_directives_cli(synthetic_repo, tmp_path)[source]ΒΆ
click-extra refresh-directivesrefreshes in place; βcheck gates CI.- Return type:
- tests.sphinx.test_sphinx_matrix.test_refresh_directives_cli_without_sphinx(tmp_path, monkeypatch)[source]ΒΆ
The command fails gracefully (not a traceback) when sphinx is absent.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_to_specifier_set(spec, member, nonmember)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_to_specifier_set_unparsable(spec)[source]ΒΆ
An unparsable specifier yields
None, which renders as an all-βrow rather than raising out of the Sphinx build.- Return type:
- tests.sphinx.test_sphinx_matrix.test_to_specifier_set_empty_matches_everything()[source]ΒΆ
An empty specifier is the universal set, not
None.Unreachable through the matrix itself, since a tag with no declared requirement is skipped before this point.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_spec_identity(spec, other, expected)[source]ΒΆ
Two specifiers share an identity when they accept the same versions.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_extract_requirement(declaration, expected)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_extract_requirement_canonicalizes_name()[source]ΒΆ
PEP 503 name normalization decides the match, so a dependency spelled with any separator is found under any other spelling.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_extract_requirement_from_setup_py()[source]ΒΆ
A
setup.pyrelease has no tables to read, so its string literals are harvested and filtered by the same PEP 508 parse.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_cell(spec, version, released, expected)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_cell_caps_later_majors(version, released, expected)[source]ΒΆ
A superseded range never attests a major newer than its cap.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_newest_major()[source]ΒΆ
The newest major out by a day, and none without a dated release.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_columns(rows, shown, expected)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_envelope(rows, full_history, expected)[source]ΒΆ
Rows come oldest first, and columns run from the oldest version.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_column_candidates(specs, releases, locked, expected)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_latest_locked_version(tmp_path, dep_name, expected)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_latest_locked_version_without_lockfile(tmp_path)[source]ΒΆ
A project with no
uv.locklocks nothing, rather than failing.- Return type:
- tests.sphinx.test_sphinx_matrix.stub_releases(monkeypatch, *versions, dates=None)[source]ΒΆ
Make PyPI list
versionsas the stable releases of every dependency.A release is undated unless
datesgives its ISO publication date, so a stub without dates never produces an undeclared cell.- Return type:
- tests.sphinx.test_sphinx_matrix.synthetic_dep_repo(tmp_path)[source]ΒΆ
A git repo whose
widgetdependency floor evolves across two tags, exercising both minor-grouped and patch-split column derivation.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_groups(synthetic_dep_repo)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_columns_and_cells(synthetic_dep_repo, monkeypatch)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.exotic_spec_repo(tmp_path)[source]ΒΆ
A repo whose
widgetrequirement takes a different exotic shape at every tag, so one render exercises the whole specifier vocabulary.The caret tag also migrates the declaration from Poetry to PEP 621 and back, the way a real projectβs history crosses packaging backends.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_exotic_specs(exotic_spec_repo, monkeypatch)[source]ΒΆ
Each specifier shape resolves to the right
β/βvector.The exclusion hole of
>=4.0,!=4.1.*isolates 4.1.0, and the 2.1.0 release no range accepts keeps its column between two that some do. The full history keeps the ranges the support envelope would leave out.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_merges_equivalent_specs(tmp_path)[source]ΒΆ
Consecutive tags differing only in spelling form a single range.
Poetryβs
^2.0and PEP 621βs>=2.0,<3.0.0describe the same set, so they group into one range instead of two identical rows. This is what a packaging-backend migration looks like in the history.- Return type:
- tests.sphinx.test_sphinx_matrix.narrowing_floor_repo(tmp_path)[source]ΒΆ
A repo whose
widgetfloor narrows across three tags, locked at 4.0.0.The caret range accepts 3.1 and the compatible-release range does not.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_merge_keeps_distinct_specs(tmp_path, monkeypatch, show_spec, expected)[source]ΒΆ
Ranges whose cells coincide merge, unless their specs differ.
Both ranges accept every release so far, and differ only above the newest one. A merged row shows the Spec cell of its oldest range, so merging them would claim
<4for releases that declared<5.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_bins_split_ranges(narrowing_floor_repo, monkeypatch)[source]ΒΆ
The releases between two floors tell the ranges apart on their cells.
- Return type:
- tests.sphinx.test_sphinx_matrix.pinned_widget_repo(tmp_path, name, spec)[source]ΒΆ
A one-tag repo pinning
widgettospec, locked at 2.4.0.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_pinned_spec(tmp_path, monkeypatch, spec, columns, cells)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_lone_ceiling(tmp_path)[source]ΒΆ
A lone ceiling anchors no column of its own.
Unlike a pin, it has no lower bound to place, so the only column left is the locked version, which the ceiling genuinely forbids. The all-β row is the honest rendering here, not a missing column.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_suffixed_poetry_floor(tmp_path, monkeypatch)[source]ΒΆ
A Poetry caret on a post-release translates like any other caret.
Its floor keeps the suffix, so the release it follows falls out of range, and its ceiling ignores it, so the later 2.x release stays in.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_shows_a_release_ahead_of_the_lock(tmp_path, monkeypatch)[source]ΒΆ
A release newer than the locked one gets a column of its own.
The table shows it before the lockfile adopts it, here as a major no range accepts yet. The locked version counts even when PyPI does not list it.
- Return type:
- tests.sphinx.test_sphinx_matrix.WIDGET_DATES = {'1.0.0': '2023-12-01', '2.0.0': '2024-05-01', '2.1.0': '2024-06-10', '3.0.0': '2025-01-01'}ΒΆ
Publication dates of the
widgetreleases the dated repository sees.
- tests.sphinx.test_sphinx_matrix.dated_dep_repo(tmp_path)[source]ΒΆ
A repo raising its
widgetfloor at each of three dated tags.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_undeclared_after_superseded(dated_dep_repo, monkeypatch)[source]ΒΆ
A release out after a range was superseded reads
βfor that range, though its specifier accepts it. So does a release of a major out after the last release of the range:1.0.0never metwidget2.x, and2.0.0never metwidget3.0.0.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_unmet_major_after_last_release(tmp_path, monkeypatch)[source]ΒΆ
A major out after the last release of a superseded range reads
β.widget1.5.0 and 2.0.0 both come out after1.1.0, the last release of the1.xrange, and before2.0.0supersedes it. Its open specifier accepts both, and the range met the 1.x major, so 1.5.0 readsβ. No release of the range ever met 2.0.0.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_envelope(dated_dep_repo, monkeypatch)[source]ΒΆ
The envelope stops at the oldest range supporting the floor or later.
A range supports a dated release it accepts only when the release came out while the range was current, from a major out by its last release. Neither older range ever met
widget3.0.0, the floor of the newest range, so both go, and the columns only they accepted too.- Return type:
- tests.sphinx.test_sphinx_matrix.ENVELOPE_WIDGET_DATES = {'1.0.0': '2021-12-01', '2.0.0': '2023-05-01', '3.0.0': '2024-12-01'}ΒΆ
Publication dates of the
widgetreleases the envelope repository sees.
- tests.sphinx.test_sphinx_matrix.envelope_repo(tmp_path)[source]ΒΆ
A repo declaring its Python support and a
widgetfloor at each tag.The Python envelope leaves out
1.0.0, which supports no Python from 3.11 on. Thewidgetone keeps every release.- Return type:
- tests.sphinx.test_sphinx_matrix.test_envelope_list_across_axes(envelope_repo, monkeypatch)[source]ΒΆ
The release bound is the strictest one, and each version bound is read again over the releases left in scope.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_envelope_list_without_cut(synthetic_dep_repo)[source]ΒΆ
With no envelope leaving out a release, the list has no release bound. An axis the history never declares is skipped, and a version of unknown date gets no date.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_envelope_region(envelope_repo, tmp_path, monkeypatch)[source]ΒΆ
The refresh fills an envelope region between its markers, and settles.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_leaves_an_envelope_region_untouched(envelope_repo, tmp_path, unreadable_pypi, args)[source]ΒΆ
An unreadable PyPI, or a region naming no axis, rewrites nothing.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_groups_respelled_spec_continues_range(tmp_path, monkeypatch)[source]ΒΆ
A re-spelled specifier continues its range.
widget1.5.0 came out after1.1.0re-spelled the specifier, while that range was still current, so it readsβfor the whole range. Split at the re-spelling,1.0.0would look superseded before 1.5.0 came out. The whole history keeps the range in the table, though it never met the 2.x major that the newest range floors.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_headers_read_in_column_order(synthetic_dep_repo, monkeypatch, column_order, expected)[source]ΒΆ
A header reads from the bound its neighbors continue: the newest one while the columns run newest first, the oldest one otherwise.
- Return type:
- tests.sphinx.test_sphinx_matrix.pypi(httpserver, monkeypatch)[source]ΒΆ
Serve PyPIβs JSON API from the local test server.
- tests.sphinx.test_sphinx_matrix.test_pypi_releases(pypi)[source]ΒΆ
The lookup asks for the normalized name and sorts the releases.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_pypi_releases_dates(pypi)[source]ΒΆ
A release is dated by the first upload among its files not yanked.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_pypi_releases_discards(pypi, tag, files)[source]ΒΆ
Pre-releases, yanked or empty releases and invalid versions are dropped.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_pypi_releases_unreadable(pypi, body, status)[source]ΒΆ
An error or a malformed answer costs the columns, not the table.
A caller that cannot use the fallback columns hears about the failure.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_to_specifier_set_poetry_conformance(spec, bounds)[source]ΒΆ
Every Poetry range translates to the interval Poetry documents.
The
0.xcaret is the one that matters in practice: Poetry caps it at the next minor, since a0.release is allowed to break on every minor.- Return type:
- tests.sphinx.test_sphinx_matrix.test_to_specifier_set_poetry_bare_wildcard()[source]ΒΆ
Poetryβs bare
*allows any version, so it has no bounds to check.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_show_date(synthetic_dep_repo, show_date)[source]ΒΆ
show_datedates the rows without changing how they merge.- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_column_order(synthetic_dep_repo, column_order)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_dependency_matrix_table_row_order(synthetic_dep_repo, row_order)[source]ΒΆ
- Return type:
- tests.sphinx.test_sphinx_matrix.test_matrix_dependency_directive_renders(sphinx_app_myst, synthetic_dep_repo)[source]ΒΆ
{matrix} <dep>renders the dependency matrix as a real<table>.
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_marker_form(synthetic_repo, tmp_path)[source]ΒΆ
The
<!-- matrix AXIS opts -->comment form refreshes to a raw table.- Return type:
- tests.sphinx.test_sphinx_matrix.test_walk_tags_dates_an_annotated_tag(tmp_path)[source]ΒΆ
A tagβs date is its commitβs author date, through an annotated tag too.
The tag object of an annotated tag carries a tagger date of its own, which is not the one the row shows.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_reads_git_twice_per_refresh(synthetic_repo, tmp_path, monkeypatch)[source]ΒΆ
One refresh lists the tags and reads their files once, whatever the blocks.
Two pages carrying three blocks, with floors of their own, share the same history: the tag listing is one
git for-each-refand every tagβs files onegit cat-file --batch.- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_marker_order_options(synthetic_repo, tmp_path)[source]ΒΆ
column-order/row-ordermarker options flip the refreshed table.- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_marker_show_date(synthetic_repo, tmp_path, flag)[source]ΒΆ
The
show-datemarker flag dates the refreshed rows.- Return type:
- tests.sphinx.test_sphinx_matrix.test_matrix_directive_show_date_option(sphinx_app_myst, synthetic_repo)[source]ΒΆ
The
:show-date:directive option dates the rendered rows.- Return type:
- tests.sphinx.test_sphinx_matrix.test_marker_form_renders_natively_in_sphinx(sphinx_app_myst)[source]ΒΆ
A marker regionβs raw table renders as a real
<table>with no directive involved (so it renders on GitHub the same way).- Return type:
- tests.sphinx.test_sphinx_matrix.test_resolve_root_relative_base_dir(synthetic_repo, monkeypatch)[source]ΒΆ
A relative
base_dirstill resolves to the real repo folder, so the default package label is never the emptyPath(".").name.- Return type:
- tests.sphinx.test_sphinx_matrix.test_render_block_default_package_label(tmp_path, pyproject, options, expected)[source]ΒΆ
Without a
packageoption, the label is the name the project declares in itspyproject.toml. The folder name is the fallback.- Return type:
- tests.sphinx.test_sphinx_matrix.test_update_matrix_blocks_label_ignores_checkout_name(tmp_path)[source]ΒΆ
A copy of a project under another folder name agrees with the table refreshed in the first checkout, so its check reports nothing stale.
- Return type:
- tests.sphinx.test_sphinx_matrix.test_render_block_raises_without_git(tmp_path, monkeypatch)[source]ΒΆ
With git absent from PATH, generation raises an error the callers catch.
- Return type:
tests.sphinx.test_sphinx_mermaid moduleΒΆ
Tests for the autoclasstree override that keeps d3 zoom off class diagrams.
- tests.sphinx.test_sphinx_mermaid.DIAGRAM = 'Class diagram of orchard.Pear.'ΒΆ
Text the stand-in
autoclasstreerenders for each diagram.
- class tests.sphinx.test_sphinx_mermaid.StubClassDiagram(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]ΒΆ
Bases:
DirectiveStand-in for the
autoclasstreedirective of sphinxcontrib-mermaid.- required_arguments = 1ΒΆ
Number of required directive arguments.
- tests.sphinx.test_sphinx_mermaid.stub_setup(app)[source]ΒΆ
Register what the override reads of sphinxcontrib-mermaid.
- tests.sphinx.test_sphinx_mermaid.mermaid_stub(monkeypatch)[source]ΒΆ
Serve a stand-in for sphinxcontrib-mermaid, which the test group lacks.
The stand-in only holds the directive and the config value the override reads.
- Return type:
- tests.sphinx.test_sphinx_mermaid.build(tmp_path, *, loaded, d3_zoom)[source]ΒΆ
Build a page, with an
autoclasstreediagram when the stand-in is loaded.click_extra.sphinxcomes first inextensions, before the directive it overrides is registered.d3_zoomsetsmermaid_d3_zoom, left to its default whenNone.
- tests.sphinx.test_sphinx_mermaid.test_class_diagrams_skip_the_zoom(tmp_path, loaded, d3_zoom, overridden)[source]ΒΆ
The override wraps each diagram only with sphinxcontrib-mermaid and zoom on.
The page then links the stylesheet the wrapper hooks into. Otherwise the directive renders as sphinxcontrib-mermaid draws it, or not at all.
- Return type:
tests.sphinx.test_sphinx_myst_docstrings moduleΒΆ
Tests for the MyST-to-reST docstring conversion hook.
- tests.sphinx.test_sphinx_myst_docstrings.test_colon_fence_conversion(myst, expected_fragments)[source]ΒΆ
- tests.sphinx.test_sphinx_myst_docstrings.test_colon_fence_blank_line_before_body()[source]ΒΆ
Converted directive inserts blank line between header and body.
- tests.sphinx.test_sphinx_myst_docstrings.test_backtick_fence_conversion(myst, expected_fragments)[source]ΒΆ
- tests.sphinx.test_sphinx_myst_docstrings.test_mixed_colon_outer_backtick_inner()[source]ΒΆ
Colon fence wrapping a backtick-fenced code block.
- tests.sphinx.test_sphinx_myst_docstrings.test_plain_code_fence_conversion(myst, expected_fragments)[source]ΒΆ
- tests.sphinx.test_sphinx_myst_docstrings.test_plain_code_fence_blank_line_before_body()[source]ΒΆ
Converted plain code fence inserts blank line between header and body.
- tests.sphinx.test_sphinx_myst_docstrings.test_plain_code_fence_not_directive()[source]ΒΆ
Plain code fences must not be confused with directive fences.
- tests.sphinx.test_sphinx_myst_docstrings.test_plain_code_fence_idempotent()[source]ΒΆ
Already-converted code-block directive passes through unchanged.
- tests.sphinx.test_sphinx_myst_docstrings.test_directive_options_follow_the_header(myst, expected)[source]ΒΆ
reST reads options on the lines right under the header, never after a blank line: a blank line there turns them into content.
- tests.sphinx.test_sphinx_myst_docstrings.test_role_opening_a_body_is_not_an_option()[source]ΒΆ
A body opening on a role keeps it as content: an option needs a space after its colon-wrapped name.
- tests.sphinx.test_sphinx_myst_docstrings.test_code_block_content_is_verbatim(myst, expected)[source]ΒΆ
Code is not prose: no backtick, role, link or footnote in it converts.
- tests.sphinx.test_sphinx_myst_docstrings.test_closing_fence_does_not_open_a_code_block()[source]ΒΆ
The bare line closing a directive fence pairs with that fence.
Read as the opener of a plain code fence instead, it would hold everything up to the next bare fence as code, the directive after it included.
- tests.sphinx.test_sphinx_myst_docstrings.test_footnote_reference_conversion(myst, expected)[source]ΒΆ
- tests.sphinx.test_sphinx_myst_docstrings.test_footnote_definition_conversion(myst, expected)[source]ΒΆ
- tests.sphinx.test_sphinx_myst_docstrings.test_footnote_ref_and_def_combined()[source]ΒΆ
Footnote reference and definition in the same docstring.
- tests.sphinx.test_sphinx_myst_docstrings.test_footnote_def_not_matched_as_ref()[source]ΒΆ
Footnote definition must not also produce a spurious reference.
- tests.sphinx.test_sphinx_myst_docstrings.test_link_strips_backticks_from_label(myst, expected)[source]ΒΆ
reST has no nested markup, so backticks are stripped from link labels.
- tests.sphinx.test_sphinx_myst_docstrings.test_double_backtick_span_keeps_its_backticks(myst, expected)[source]ΒΆ
A double-backtick span keeps its single backticks single.
Doubled, they would end the reST literal early: the conversion must parse into whole literals, with no warning.
- tests.sphinx.test_sphinx_myst_docstrings.test_inline_code_no_cross_contamination_with_xref(myst, expected)[source]ΒΆ
Closing backtick of a cross-ref must not pair with inline code.
- tests.sphinx.test_sphinx_myst_docstrings.test_leading_underscore_span_not_a_hyperlink_ref(myst, expected)[source]ΒΆ
A backtick span starting with
_must not be read as a hyperlink ref.The reST hyperlink-reference pattern
` `label`_ `would otherwise let the protection regex span the gap between two inline-code spans (consuming the first spanβs closing backtick and the second spanβs leading underscore), corrupting both. A hyperlink refβs opening backtick is anchored at a non-word boundary, but that alone is not enough: when the first spanβs content ends in a non-word character (`<stdout>`,`f()`), its closing backtick also clears that lookbehind. The refβs trailing marker (_/__) not being glued to an identifier is what rejects the false match while still matching real` `label`_ `references.
- tests.sphinx.test_sphinx_myst_docstrings.test_rst_literals_are_opaque(text)[source]ΒΆ
Double-backtick reST literals pass through every step verbatim.
- tests.sphinx.test_sphinx_myst_docstrings.test_nested_protected_spans_are_restored(text)[source]ΒΆ
A reST literal inside a span protected later comes back whole.
Both are stashed behind placeholders: restored in the wrong order, the inner one would leave its NUL-delimited placeholder in the output.
- tests.sphinx.test_sphinx_myst_docstrings.test_role_shaped_code_span_not_protected_as_role(myst, expected)[source]ΒΆ
Role-shaped text inside a code span is code, wherever the span holds it.
- tests.sphinx.test_sphinx_myst_docstrings.test_idempotent_already_converted()[source]ΒΆ
Running the converter twice produces the same result.
- tests.sphinx.test_sphinx_myst_docstrings.test_idempotent_full_rst_docstring()[source]ΒΆ
A complete reST docstring passes through unchanged.
- tests.sphinx.test_sphinx_myst_docstrings.test_mixed_myst_attribute_then_rst_metadata()[source]ΒΆ
Simulates generate_docstring() output: MyST attribute docstring concatenated with reST metadata lines.
- tests.sphinx.test_sphinx_myst_docstrings.test_all_conversions_combined()[source]ΒΆ
A docstring exercising every conversion step in one pass.
- tests.sphinx.test_sphinx_myst_docstrings.test_myst_inside_field_lists(myst, expected)[source]ΒΆ
MyST inline constructs inside field list entries are converted.
- tests.sphinx.test_sphinx_myst_docstrings.test_full_docstring_with_myst_field_lists()[source]ΒΆ
Realistic docstring with MyST in both prose and field list entries.
- tests.sphinx.test_sphinx_myst_docstrings.test_unsupported_constructs_pass_through(myst, description)[source]ΒΆ
Unsupported MyST constructs pass through unchanged.
- tests.sphinx.test_sphinx_myst_docstrings.test_curly_braces_in_inline_code()[source]ΒΆ
Inline code containing
{and}characters.A standalone
:word:in single backticks is safe: it gets doubled to{word}because the xref regex needs the:word:``targetpattern (two backtick-delimited spans). Double-backtick input also passes through.The dangerous case is
:word:``textwhere the braces plus adjacent backtick-delimited span mimics the xref pattern. Theconvert-to-mystcommand intentionally keeps these as double backticks to avoid this.
- tests.sphinx.test_sphinx_myst_docstrings.test_plain_code_fence_empty_body()[source]ΒΆ
Plain code fence with an empty body.
- tests.sphinx.test_sphinx_myst_docstrings.test_longer_fence_holds_a_shorter_one(myst, expected)[source]ΒΆ
A fence closes on a run of its own length, as in any MyST document.
- tests.sphinx.test_sphinx_myst_docstrings.test_blank_line_opening_a_body_goes_with_the_header()[source]ΒΆ
MyST drops the blank line opening a directive body, options or not.
- tests.sphinx.test_sphinx_myst_docstrings.test_nested_same_type_fences_not_supported()[source]ΒΆ
Nested fences of the same length are not reliably converted.
A colon fence inside a colon fence, or a backtick fence inside a backtick fence, may not parse correctly: a fence closes on the first bare run of its character at least as long as its opener.
- tests.sphinx.test_sphinx_myst_docstrings.test_directive_inside_field_list_not_supported()[source]ΒΆ
Fenced directives inside field list entries do not render correctly.
Field list entries in Sphinx are paragraph-level constructs. Block-level MyST content (admonitions, code blocks) inside them is converted by the regex but wonβt render correctly in Sphinx.
- tests.sphinx.test_sphinx_myst_docstrings.test_link_with_parentheses_in_url()[source]ΒΆ
A URL holding a balanced pair of parentheses is kept whole.
- tests.sphinx.test_sphinx_myst_docstrings.test_consecutive_field_list_entries_all_converted()[source]ΒΆ
Multiple consecutive field list entries each get their content converted.
- tests.sphinx.test_sphinx_myst_docstrings.test_empty_field_list_content()[source]ΒΆ
Field list entries with empty or whitespace-only content.
- tests.sphinx.test_sphinx_myst_docstrings.test_xref_adjacent_to_field_list_colon()[source]ΒΆ
Cross-reference immediately after the field list colon.
- tests.sphinx.test_sphinx_myst_docstrings.test_multiple_xrefs_in_single_field_entry()[source]ΒΆ
Multiple cross-references in one field list entry.
- tests.sphinx.test_sphinx_myst_docstrings.test_link_with_backtick_label_in_field_list()[source]ΒΆ
Markdown link with backtick-wrapped label inside a field list entry.
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:runcapturesprintoutput 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:sourceruns silently; a follow-uppython:runreuses its imports.
- tests.sphinx.test_sphinx_python.test_python_run_language_override(sphinx_app_myst)[source]ΒΆ
:language:overrides the defaulttextlexer for the result block.
- tests.sphinx.test_sphinx_python.test_python_run_screenshot_writes_the_asset(sphinx_app_myst)[source]ΒΆ
:screenshot:onpython:runwrites the capture, as onclick:run.The
:mirror:refresher links the asset below whichever directive names it, so the block has to write it or the page links an image that is not there.
- 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:renderpasses block-level raw HTML through unchanged.A naked
print('<div>...</div>')should reach the rendered page without any{raw} htmlwrapping. 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:renderparses 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:renderbecomes a real heading node.
- tests.sphinx.test_sphinx_python.test_python_render_host_rst_injects_admonition(sphinx_app_rst)[source]ΒΆ
python:renderin 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-mystforces 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-rstforces 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-mystworks 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-rstworks 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:*andpython:*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.sphinxto 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
printoutput 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 = Trueactivates 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.
- tests.sphinx.test_sphinx_python.test_mirror_src_rewrite_inserts_region()[source]ΒΆ
A mirror-src comment with no region yet gets one, generator kept hidden.
- tests.sphinx.test_sphinx_python.test_mirror_src_rewrite_is_idempotent()[source]ΒΆ
Re-running over an already-filled mirror-src region is a no-op.
- tests.sphinx.test_sphinx_python.test_mirror_src_first_sight_stops_at_the_next_generator()[source]ΒΆ
A new generator above a refreshed one gets its own region.
The terminator below the second generator closes that generatorβs region: read as the end of the first oneβs, it would replace the prose and the second generator between them.
- tests.sphinx.test_sphinx_python.test_mirror_src_via_update_mirror_blocks(tmp_path)[source]ΒΆ
The offline refresher fills a mirror-src region, then round-trips clean.
- tests.sphinx.test_sphinx_python.test_mirror_src_rewrite_skips_example_nested_in_code_block()[source]ΒΆ
A mirror-src comment shown inside a longer code-block fence is never run.
- tests.sphinx.test_sphinx_python.test_rewrite_mirrors_refreshes_every_mirror_src_spelling(opening)[source]ΒΆ
A comment the region walk accepts is refreshed, whatever space follows
<!--.
- tests.sphinx.test_sphinx_python.test_mirror_rewrite_inserts_region()[source]ΒΆ
A mirror block with no region yet gets one inserted below the fence.
- tests.sphinx.test_sphinx_python.test_mirror_rewrite_is_idempotent()[source]ΒΆ
Re-running over an already-mirrored document is a no-op.
- tests.sphinx.test_sphinx_python.test_mirror_rewrite_replaces_stale_region()[source]ΒΆ
A stale region is refreshed from the blockβs current output.
- tests.sphinx.test_sphinx_python.test_mirror_rewrite_skips_example_nested_in_code_block()[source]ΒΆ
A mirror block shown inside a longer code-block fence is never executed.
- tests.sphinx.test_sphinx_python.test_python_render_mirror_renders_fresh_without_touching_source(sphinx_app_myst)[source]ΒΆ
:mirror:renders the table once; the build never writes to the source.
- tests.sphinx.test_sphinx_python.test_update_mirror_blocks_populates_and_idempotent(tmp_path)[source]ΒΆ
The offline refresher inserts the region, then round-trips clean.
- tests.sphinx.test_sphinx_python.test_update_mirror_blocks_check_mode(tmp_path)[source]ΒΆ
check=Truereports the stale file without writing it.
- tests.sphinx.test_sphinx_python.test_update_mirror_blocks_imports_sibling_module(tmp_path)[source]ΒΆ
A mirror block imports a helper module living next to the page.
Matches the Sphinx build, where the
conf.pydirectory is importable, so adocs_update.py-style generator module works offline too. The path entry is scoped to the execution and removed afterwards.
- tests.sphinx.test_sphinx_python.test_refresh_directives_cli_refreshes_mirror_blocks(tmp_path)[source]ΒΆ
click-extra refresh-directivescovers mirror regions too.
tests.sphinx.test_sphinx_tables moduleΒΆ
Tests for the styling of corner-labeled tables.
- tests.sphinx.test_sphinx_tables.test_corner_tables_keep_their_first_column_whole(sphinx_app_myst)[source]ΒΆ
Only a table whose first header cell holds the corner label is marked.
The glyph in any other header cell marks nothing, and every page links the stylesheet the mark hooks into.
- Return type:
tests.sphinx.test_sphinx_tabs moduleΒΆ
Tests for the vertical layout of sphinx-design tab-sets.
- tests.sphinx.test_sphinx_tabs.test_vertical_tabs_stylesheet_is_linked(sphinx_app_myst)[source]ΒΆ
Every page links the stylesheet, which the build writes.
- Return type:
- tests.sphinx.test_sphinx_tabs.test_vertical_tabs_rules_stay_on_their_tab_set()[source]ΒΆ
Every rule targets a tab-set marked with the class, or a direct child of it.
Other tab-sets keep their layout, and so does a tab-set nested inside a pane of a vertical one.
- Return type:
- tests.sphinx.test_sphinx_tabs.test_vertical_tabs_class_is_deprecated(sphinx_app_myst, classes, warns)[source]ΒΆ
A tab-set marked with the class warns about its removal, other nodes do not.
A docutils
containertakes the classes that sphinx-design gives the node of atab-set, so the test needs no sphinx-design.- Return type:
tests.sphinx.test_sphinx_todos moduleΒΆ
Tests for the todolist deduplication hook and the unrendered-todo check.
- tests.sphinx.test_sphinx_todos.TODO_SOURCE_RE = re.compile('<p class="todo-source">\\(The <a class="reference internal" href="([^"]+)">.*?located in (.*?), line (\\d+)\\.\\)</p>', re.DOTALL)ΒΆ
Captures the page, the origin and the line of every rendered todo entry.
sphinx.ext.todoemits one such paragraph per entry it puts on atodolist, so counting them counts the entries.
- tests.sphinx.test_sphinx_todos.COMPOST_MODULE = '"""Turn fallen fruit into compost.\n\n.. todo::\n Turn the heap once a week.\n"""\n'ΒΆ
A module docstring with a todo on its third line.
- tests.sphinx.test_sphinx_todos.GRAFTING_MODULE = '"""Fruit grafting."""\n\n\ndef _graft(branch):\n """Join ``branch`` to a rootstock.\n\n .. todo::\n Seal the cut with wax.\n """\n return branch\n'ΒΆ
A module whose only todo sits in a private function, which
:members:skips.
- tests.sphinx.test_sphinx_todos.VARIETIES_MODULE = '"""Fruit varieties."""\n\n\nclass Fruit:\n """A fruit."""\n\n\nAPPLE = Fruit()\n"""A crisp apple.\n\n.. todo::\n Pick the reddest one first.\n"""\n\nAPPLE.__doc__ = """A crisp apple.\n\n.. todo::\n Pick the reddest one first.\n"""\n'ΒΆ
A module whose attribute docstring the instance carries too.
A registry of documented instances copies it this way, so that autodoc finds the docstring under a path that re-exports the attribute, where no source carries it. autodoc labels each rendering with the path it documented.
- tests.sphinx.test_sphinx_todos.VARIETIES_INIT = '"""An orchard."""\n\nfrom .varieties import APPLE\n\n__all__ = ["APPLE"]\n'ΒΆ
A package re-exporting the attribute of
VARIETIES_MODULE.
- tests.sphinx.test_sphinx_todos.BOWLS_MODULE = '"""Fruit bowls."""\n\n\nclass Fruit:\n """A fruit."""\n\n\nBOWL = Fruit()\n\nPEAR = BOWL\n"""A pear.\n\n.. todo::\n Wait for autumn.\n"""\n\nQUINCE = BOWL\n"""A quince.\n\n.. todo::\n Cook it first.\n"""\n'ΒΆ
Two attributes bound to one object, each with a todo of its own on one line.
- tests.sphinx.test_sphinx_todos.UNRENDERED_RE = re.compile('(\\S+):(\\d+): WARNING: click_extra\\.sphinx: no page renders the docstring of (\\S+), so no todolist can list this todo\\.')ΒΆ
Captures the file, the line and the owner of every unrendered-todo warning.
- tests.sphinx.test_sphinx_todos.build_project(tmp_path, package, pages, *, files=None, conf=(), dedupe=None, todo_extension=True)[source]ΒΆ
Build a throwaway project documenting
package, and return the build.pagesmaps a docname to its reStructuredText body. Atodospage carrying thetodolistis always appended, and every page is wired into the root toctree.packagenames the generated package, and must differ between tests: the modules are imported by autodoc into the running interpreter, wheresys.moduleswould otherwise serve the first testβs copy to every later one.filesmaps a path inside the package to its source, written over the orchardβs own__init__.pyandharvest.py.confappends lines to the generatedconf.py.Returns the output directory, the warning stream and the exit status.
- tests.sphinx.test_sphinx_todos.build_orchard(tmp_path, package, pages, **options)[source]ΒΆ
Build a project with
build_project, and return its todo entries.Returns the
(page, origin, line)triples thetodolistpage rendered, in document order.
- tests.sphinx.test_sphinx_todos.unrendered_todos(warnings)[source]ΒΆ
Return the
(file name, line, owner)of each unrendered-todo warning.
- tests.sphinx.test_sphinx_todos.automodule(target, no_index=False)[source]ΒΆ
Render an
automoduleblock fortarget.
- tests.sphinx.test_sphinx_todos.fake_node(source, line=1)[source]ΒΆ
A
todonode reduced to the two attributes the identity helpers read.
- tests.sphinx.test_sphinx_todos.test_todo_identity_ignores_the_import_path_of_a_docstring()[source]ΒΆ
Two renderings of one docstring share an identity whatever reached it.
- tests.sphinx.test_sphinx_todos.test_todo_identity_reads_the_source_form_without_a_file()[source]ΒΆ
A source autodoc wrote without a file yields its label like one with a file.
- tests.sphinx.test_sphinx_todos.test_is_reexport(source, expected)[source]ΒΆ
Only a docstring reached through a package
__init__ranks as re-exported.
- tests.sphinx.test_sphinx_todos.test_full_api_page_and_feature_page_yield_one_entry_each(tmp_path)[source]ΒΆ
A module documented twice across pages lists each todo once.
- tests.sphinx.test_sphinx_todos.test_reexported_members_yield_one_entry_each(tmp_path)[source]ΒΆ
A member documented under both its package and its module lists once.
- tests.sphinx.test_sphinx_todos.test_surviving_entry_attributes_to_the_defining_module(tmp_path)[source]ΒΆ
The kept rendering names the module defining the object, not the package.
- tests.sphinx.test_sphinx_todos.test_reexported_attribute_yields_one_entry(tmp_path)[source]ΒΆ
An attribute documented under its package and its module lists once.
The two renderings of its docstring carry different labels, the paths autodoc documented: only the object behind both labels matches them.
- tests.sphinx.test_sphinx_todos.test_attributes_sharing_an_object_keep_an_entry_each(tmp_path)[source]ΒΆ
Two docstrings of one object keep their entries, though the object matches.
- tests.sphinx.test_sphinx_todos.test_dedupe_switched_off_restores_every_rendering(tmp_path)[source]ΒΆ
click_extra_dedupe_todos = Falsegives Sphinxβs raw output back.
- tests.sphinx.test_sphinx_todos.test_distinct_todos_all_survive(tmp_path)[source]ΒΆ
Deduplication collapses repeats, never two different directives.
- tests.sphinx.test_sphinx_todos.test_build_succeeds_without_the_todo_extension(tmp_path)[source]ΒΆ
The hook is inert on a project that never registered the todo domain.
- tests.sphinx.test_sphinx_todos.test_docstring_todos(source, expected)[source]ΒΆ
Each todo is found at its line, under the path autodoc labels it with.
- tests.sphinx.test_sphinx_todos.test_docstring_todos_rejects_invalid_source()[source]ΒΆ
A module that does not parse raises, for the caller to skip it.
- tests.sphinx.test_sphinx_todos.test_package_modules_walks_without_importing(tmp_path, monkeypatch)[source]ΒΆ
Every module of a package is found, private ones included, none imported.
- tests.sphinx.test_sphinx_todos.test_unrendered_todos_warn_at_their_line(tmp_path)[source]ΒΆ
A todo in a docstring no page renders is reported at its own line.
- tests.sphinx.test_sphinx_todos.test_rendered_todos_do_not_warn(tmp_path)[source]ΒΆ
No todo a page renders is reported, a re-exported one included.
- tests.sphinx.test_sphinx_todos.test_todo_rendered_under_another_path_does_not_warn(tmp_path)[source]ΒΆ
A docstring autodoc labels with another path still counts as rendered.
With its
__module__overridden,pickis labeled with the path of the package, not with the path of the module that defines it.
tests.sphinx.test_sphinx_viewcode moduleΒΆ
Tests for the sphinx.ext.viewcode pages a build publishes.
- tests.sphinx.test_sphinx_viewcode.FRUITS_MODULE = 'import re\n\nSEED = re.compile(r"\\d+")\n"""Pattern of a seed count."""\n\n\ndef ripen(fruit):\n """Ripen a fruit."""\n'ΒΆ
A module documenting a constant whose value is an instance of
re.Pattern.viewcode looks for
SEEDin the module of that class,re, and finds nothing to link to there.
- tests.sphinx.test_sphinx_viewcode.PUBLISHED_PAGES = ['_modules/fruits.html', '_modules/index.html']ΒΆ
The module page of
fruits, and the index linking to it.
- tests.sphinx.test_sphinx_viewcode.write_project(srcdir)[source]ΒΆ
Write a project whose last document read documents
fruits.No later document purges the unused
reentry, so a serial read keeps it too.- Return type:
- tests.sphinx.test_sphinx_viewcode.module_pages(outdir)[source]ΒΆ
List the viewcode pages of a build, relative to its output directory.
- tests.sphinx.test_sphinx_viewcode.test_serial_read_publishes_linked_modules_only(tmp_path, monkeypatch)[source]ΒΆ
A serial read publishes no page for the module it read for nothing.
- tests.sphinx.test_sphinx_viewcode.test_parallel_read_publishes_the_pages_of_a_serial_one(tmp_path)[source]ΒΆ
A parallel read publishes the same pages as a serial one.
Its workers merge their entries after every purge has run, which is the case of sphinx-doc/sphinx#14675. The build runs in a process of its own: forking the test process, which runs other threads, can deadlock the workers.