Как запустить doctest с примерами в блоках кода уценки для mkdocs?

Я использую mkdocs и mkdocstring для создания документации и включения примеров кода в строки документации. Я также использую doctest (через pytest --doctest-modules), чтобы проверить все эти примеры.

Вариант 1 – формат документации

Если я отформатирую свою документацию следующим образом:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples:
    --------
    ```
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    ```
    """

Затем он хорошо отображается в документации, но doctest завершается с ошибкой:

Expected:
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    ```
Got:
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

Это имеет смысл, поскольку doctest обрабатывает все до тех пор, пока не появится пустая строка, как ожидаемый результат, и стремится точно соответствовать

Вариант 2 – формат для доктеста

Если я отформатирую строку документации для doctest без блоков кода:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples:
    --------
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    """

затем doctest проходит, но документация отображается

[x для x в Flatten([1,2,[3,4,[5],6],7,[8,9]])][1, 2, 3, 4, 5, 6, 7, 8 , 9]

Обходной путь? - добавить пустую строку для doctest

Если я отформатирую его с дополнительной пустой строкой перед концом кодового блока:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples:
    --------
    ```
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    ```
    """

Затем документация проходит, но

  1. в документации внизу примера есть пустая строка (некрасиво)
  2. Мне нужно не забыть добавить пустую строку в конце каждого примера (может привести к ошибкам и раздражает).

Кто-нибудь знает лучшее решение?

🤔 А знаете ли вы, что...
В Python есть инструменты для создания графиков и визуализации данных, такие как библиотеки Matplotlib и Seaborn.


1
147
2

Ответы:

Решено

Исправление регулярного выражения, которое doctest использует для идентификации кодовых блоков, решило эту проблему. Документирую это здесь для тех, кто наткнется на это в будущем...

Поскольку я не хочу регулярно делать это в проектах (!), я создал pytest-doctest-mkdocstrings в качестве плагина pytest, чтобы делать это за меня, и включил некоторые дополнительные проверки работоспособности, параметры конфигурации и т. д.

pip install pytest-doctest-mkdocstrings
pytest --doctest-mdcodeblocks --doctest-modules --doctest-glob = "*.md"

Для тех, кто ищет здесь ответ в коде, который можно использовать самостоятельно, необходимо внести следующие изменения:


    _MD_EXAMPLE_RE = re.compile(
        r"""
            # Source consists of a PS1 line followed by zero or more PS2 lines.
            (?P<source>
                (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line
                (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines
            \n?
            # Want consists of any non-blank lines that do not start with PS1.
            (?P<want> (?:(?![ ]*$)    # Not a blank line
                        (?![ ]*```)  # Not end of a code block
                        (?![ ]*>>>)  # Not a line starting with PS1
                        .+$\n?       # But any other line
                    )*)
            """,
        re.MULTILINE | re.VERBOSE,
    )

    doctest.DocTestParser._EXAMPLE_RE = _MD_EXAMPLE_RE

Конкретно я включил (?![ ]*```) # Not end of a code block в обозначение "хочу"


mkdocstrings (в частности, Griffe) поддерживает необработанные фрагменты pycon в разделах «Примеры». Однако ваш раздел «Примеры», вероятно, не распознается как таковой из-за дополнительного двоеточия в конце заголовка (Examples:). Попробуйте удалить его, а также обратные галочки:

    """
    Recursively flattens a nested iterable (including strings!) and returns all elements in order left to right.

    Examples
    --------
    >>> [x for x in flatten([1,2,[3,4,[5],6],7,[8,9]])]
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    """

Теперь, возможно, doctest все еще хочет пустую строку перед закрытием """, не уверен.

Кроме того, обратите внимание, что я создал расширение Python-Markdown, которое распознает необработанный pycon код где угодно, а не только в разделах «Примеры»: https://pawamoy.github.io/markdown-pycon/ (на данный момент доступно только спонсорам) письма).