Skip to main content

Additions to Sybil, the documentation testing tool.

Project description

Build Status codecov PyPI

sybil-extras

Add ons for Sybil.

Installation

$ pip install sybil-extras

Evaluators

MultiEvaluator

"""Use MultiEvaluator to run multiple evaluators on the same parser."""

from sybil import Example, Sybil
from sybil.evaluators.python import PythonEvaluator
from sybil.parsers.rest.codeblock import CodeBlockParser
from sybil.typing import Evaluator

from sybil_extras.evaluators.multi import MultiEvaluator


def _evaluator_1(example: Example) -> None:
    """Check that the example is long enough."""
    minimum_length = 50
    assert len(example.parsed) >= minimum_length


evaluators: list[Evaluator] = [_evaluator_1, PythonEvaluator()]
multi_evaluator = MultiEvaluator(evaluators=evaluators)
parser = CodeBlockParser(language="python", evaluator=multi_evaluator)
sybil = Sybil(parsers=[parser])

pytest_collect_file = sybil.pytest()

ShellCommandEvaluator

"""Use ShellCommandEvaluator to run shell commands against the code block."""

import sys

from sybil import Sybil
from sybil.parsers.rest.codeblock import CodeBlockParser

from sybil_extras.evaluators.shell_evaluator import ShellCommandEvaluator

evaluator = ShellCommandEvaluator(
    args=[sys.executable, "-m", "mypy"],
    # The code block is written to a temporary file
    # with these suffixes.
    tempfile_suffixes=[".example", ".py"],
    # Pad the temporary file with newlines so that the
    # line numbers in the error messages match the
    # line numbers in the source document.
    pad_file=True,
    # Don't write any changes back to the source document.
    # This option is useful when running a linter or formatter
    # which modifies the code.
    write_to_file=False,
    # Use a pseudo-terminal for running commands.
    # This can be useful e.g. to get color output, but can also break
    # in some environments.
    use_pty=True,
)
parser = CodeBlockParser(language="python", evaluator=evaluator)
sybil = Sybil(parsers=[parser])

pytest_collect_file = sybil.pytest()

Parsers

CustomDirectiveSkipParser

"""Use CustomDirectiveSkipParser to skip code blocks with a custom marker."""

from sybil import Sybil
from sybil.parsers.rest.codeblock import PythonCodeBlockParser

# Similar parsers are available at
# sybil_extras.parsers.markdown.custom_directive_skip and
# sybil_extras.parsers.myst.custom_directive_skip.
from sybil_extras.parsers.rest.custom_directive_skip import (
    CustomDirectiveSkipParser,
)

skip_parser = CustomDirectiveSkipParser(directive="custom-marker-skip")
code_block_parser = PythonCodeBlockParser()

sybil = Sybil(parsers=[skip_parser, code_block_parser])

pytest_collect_file = sybil.pytest()

This allows you to skip code blocks in the same way as described in the Sybil documentation for skipping examples in reStructuredText, Markdown , and MyST files, but with custom text, e.g. custom-marker-skip replacing the word skip.

GroupedCodeBlockParser

"""Use GroupedCodeBlockParser to group code blocks by a custom directive."""

import sys
from pathlib import Path

from sybil import Sybil
from sybil.example import Example
from sybil.parsers.rest.codeblock import PythonCodeBlockParser

# Similar parsers are available at
# sybil_extras.parsers.markdown.grouped_code_block and
# sybil_extras.parsers.myst.grouped_code_block.
from sybil_extras.parsers.rest.grouped_code_block import GroupedCodeBlockParser


def evaluator(example: Example) -> None:
    """Evaluate the code block by printing it."""
    sys.stdout.write(example.parsed)


group_parser = GroupedCodeBlockParser(
    directive="group",
    evaluator=evaluator,
    # Pad the groups with newlines so that the
    # line number differences between blocks in the output match the
    # line number differences in the source document.
    # This is useful for error messages that reference line numbers.
    # However, this is detrimental to commands that expect the file
    # to not have a bunch of newlines in it, such as formatters.
    pad_groups=True,
)
code_block_parser = PythonCodeBlockParser()

sybil = Sybil(parsers=[code_block_parser, group_parser])

document = sybil.parse(path=Path("CHANGELOG.rst"))

for item in document.examples():
    # One evaluate call will evaluate a code block with the contents of all
    # code blocks in the group.
    item.evaluate()

This makes Sybil act as though all of the code blocks within a group are a single code block, to be evaluated with the evaluator given to GroupedCodeBlockParser.

Only code blocks parsed by another parser in the same Sybil instance will be grouped.

A group is defined by a pair of comments, group: start and group: end. The group: end example is expanded to include the contents of the code blocks in the group.

A reStructuredText example:

.. code-block:: python

   """Code block outside the group."""

   x = 1
   assert x == 1

.. group: start

.. code-block:: python

    """Define a function to use in the next code block."""

    import sys


    def hello() -> None:
        """Print a greeting."""
        sys.stdout.write("Hello, world!")


    hello()

.. code-block:: python

    """Run a function which is defined in the previous code block."""

    # We don't run ``hello()`` yet - ``doccmd`` does not support groups

.. group: end

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sybil_extras-2025.3.5.tar.gz (33.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sybil_extras-2025.3.5-py2.py3-none-any.whl (18.2 kB view details)

Uploaded Python 2Python 3

File details

Details for the file sybil_extras-2025.3.5.tar.gz.

File metadata

  • Download URL: sybil_extras-2025.3.5.tar.gz
  • Upload date:
  • Size: 33.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for sybil_extras-2025.3.5.tar.gz
Algorithm Hash digest
SHA256 37f1e2e6e53818a614f2d4989f498d335606a5014e2f2124910ddfa26f771b71
MD5 0d413687b632e53fe10532cbd24b5280
BLAKE2b-256 9e93ac95437589ee6a837154fcffc7fd03551d6b3a7acf355f98edcb39430ce5

See more details on using hashes here.

Provenance

The following attestation bundles were made for sybil_extras-2025.3.5.tar.gz:

Publisher: release.yml on adamtheturtle/sybil-extras

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sybil_extras-2025.3.5-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for sybil_extras-2025.3.5-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 25829d9583fdabb00cbf05b48b85b3dfc2d2ef82c1e1b48a4a3c2ddd2134ba90
MD5 94a7fae954f15109fdef13093b1bd6b0
BLAKE2b-256 ed24eb6b558bbfc132a36af6b025a8232e2414b58660773f2900426cc46a38af

See more details on using hashes here.

Provenance

The following attestation bundles were made for sybil_extras-2025.3.5-py2.py3-none-any.whl:

Publisher: release.yml on adamtheturtle/sybil-extras

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page