Инструменты документирования исследований

Лев Коваленко — Senior DS Engineer
Тимур Салимов — Techlead DS

Введение

Data Science проекты по сути своей всегда комплексные. Они включают в себя различные этапы, такие как исследование исходных данных, очистка данных, отбор признаков, построение модели и интерпретация результатов экспериментов. Каждый из этих шагов предполагает использование различных инструментов и методов, что само по себе уже требует пояснений.

Кроме того прозрачная и доступная всем заинтересованным лицам документация позволяет синхронизироваться в терминологии, в используемых методах, в целях проекта и в том, каким образом мы к этим целям двигаемся.

Что входит в документацию проекта DS?

  • Статичные файлы исследований на естественном языке.
  • Помимо исследований, к концу проекта будет также огромная кодовая база вспомогательных функций и скриптов, которая точно также нуждается в описании и пояснениях. Здесь в игру вступает документация кода.
  • А также, специфично для DS, это использование Jupyter-like инструментов, то есть интерактивных документов, которые позволяют вам писать код и совмещать его с текстовым описанием.
  • В итоге, на самом деле, в документации DS инструменты одновременно (или отдельно) должны решать три задачи:
    • Документация кода
    • Генерация статичного файла на основе интерактивных документов (Jupyter-like)
    • Генерация итоговой документации из статичных файлов, включая в том числе файлы на естественном языке.

Основные понятия

Markdown(CommonMark)

commonmark-example.png

reStructuredText

reStructuredText-example.png

Docstrings

  • Пример docstring:
    •   def complex(real=0.0, imag=0.0):
            """Form a complex number.
      
            Keyword arguments:
            real -- the real part (default 0.0)
            imag -- the imaginary part (default 0.0)
            """
            if imag == 0.0 and real == 0.0:
                return complex_zero
            ...
  • reStructuredText
    •   def add(a, b):
            """
            Суммирует два числа.
      
            :param a: Первое число
            :param b: Второе число
            :return: Сумма двух чисел
            """
            return a + b
  • numpy/scipy
    •   def add(a, b):
            """
            Суммирует два числа.
      
            Parameters
            ----------
            a : int
                Первое число
            b : int
                Второе число
      
            Returns
            -------
            int
                Сумма двух чисел
            """
            return a + b
  • google
    •   def add(a, b):
            """
            Суммирует два числа.
      
            Args:
                a (int): Первое число
                b (int): Второе число
      
            Returns:
                int: Сумма двух чисел
            """
            return a + b

Инструменты документирования

Sphinx

  • Sphinx — это генератор документации или инструмент, который переводит набор исходных текстовых файлов (обычно reStructuredText) в различные выходные форматы, автоматически создавая перекрестные ссылки, индексы и т. д.
  • Sphinx фокусируется на документации, в частности на рукописной документации, однако Sphinx также можно использовать для создания блогов, документации кода и даже книг.
  • Цель этого раздела — познакомить вас с Sphinx, дав вам краткое представление о том, что он из себя представляет и как можно его просто использовать, без углубления в возможности кастомизации.

Установка Sphinx

  • Установка с PyPI
    •       pip install -U sphinx
  • Установка с conda-forge
    •       conda install -c conda-forge sphinx

Создание проекта

  • Развернуть шаблон:
    • (docs-example) timur@linux:~$ sphinx-quickstart
      Welcome to the Sphinx 7.2.6 quickstart utility.
      
      Selected root path: .
      
      > Separate source and build directories (y/n) [n]: y
      
      > Project name: Docs Example
      > Author name(s): Timur Salimov
      > Project release []: 0.0.1
      
      > Project language [en]: en,ru
      
      Finished: An initial directory structure has been created.
      
      You should now populate your master file /docs-example/source/index.rst 
      and create other documentation source files. 
      
      Use the Makefile to build the docs, like so:
         make builder
      where "builder" is one of the supported builders, e.g. html, latex or linkcheck.
  • Итоговая структура:
    •     .
          └── docs-example/
              ├── build/
              ├── sourse/
              │   ├── _static/
              │   ├── _template/
              │   ├── conf.py
              │   └── index.rst
              ├── Makefile
              └── make.bat

Конфигурация

  • В корне проекта создадим папку src с модулем my_module и функцией add, в которой напишем docstring в google формате.
  • В conf.py необходимо указать путь до корня проекта из папки source:
    • import os
      import sys
      
      sys.path.insert(0, os.path.abspath(".."))
  • А также необходимо подключить несколько встроенных расширений:
    •     extensions = [
              "sphinx.ext.autodoc", # Генерация документации кода
              "sphinx.ext.viewcode", # Кнопка для просмотра исходного кода
              "sphinx.ext.napoleon", # Обработка google/numpy формата docstring
          ]

Сборка документации

  • Сборка документации кода:
    •     sphinx-apidoc -o source src/
  • Включение документации модулей в общую документацию (index.rst):
    • .. toctree::
         :maxdepth: 2
         :caption: Contents:
      
         modules
  • Сборка итоговой документации
    •     sphinx-build -b html source build

Итог: Главная страница

sphinx-example.png

Итог: Документация кода

sphinx-code-example.png

Итог: Исходный код

sphinx-viewcode-example.png

Поддержка markdown

  • Конфигурация в Sphinx:
    • Добавление плагина в conf.py:
      •     extensions = [
                ...,
                "myst_parser",
            ]
    • Расширение синтаксиса markdown в conf.py через параметр плагина:
      •     myst_enable_extensions = ["dollarmath"]
    • В том числе можно строго установить следование CommonMark:
      •     myst_commonmark_only = True

Генерация документации на основе Jupyter notebooks

  • Конфигурация в Sphinx:
    • Сразу стоит сделать ремакру, что myst-nb содержит в себе полностью myst-parser, поэтому в случае, если используете первый, обязательно отключите второй. Иначе получите ошибку, так как оба эти модуля регистрируются одинаково.
    • Добавление плагина в conf.py:
      •     extensions = [
                ...,
                "myst_nb",
            ]
    • Расширение синтаксиса markdown в conf.py через параметр плагина:
      •     myst_enable_extensions = ["dollarmath"]
    • В том числе можно строго установить следование CommonMark:
      •     myst_commonmark_only = True

Пример Jupyter notebook в итоговой документации

sphinx-myst-nb-example.png

MkDocs

MkDocs — это быстрый, простой и “совершенно великолепный”(по их собственным словам) генератор статических сайтов, предназначенный для создания проектной документации. Исходные файлы документации написаны в Markdown и настраиваются с помощью одного файла конфигурации YAML. В качестве основного парсера они используют парсер на основе CommonMark.

Установка MkDocs

  • Установка с PyPI
    •     pip install -U mkdocs mkdocs-material mkdocstrings-python
  • Установка с conda-forge
    •      conda install -c conda-forge mkdocs mkdocs-material mkdocstrings-python

Создание проекта

  • Развернуть шаблон:
    •     (docs-example) timur@linux:~$ mkdocs new .
          INFO    -  Writing config file: ./mkdocs.yml
          INFO    -  Writing initial docs: ./docs/index.md
  • Итоговая структура:
    •     .
          └── docs-example/
              ├── mkdocs.yml
              └── docs/
                  └── index.md

Конфигурация

  • Конфигурация в mkdocs.yml:
    • site_name: Docs Example
      
      theme:
        name: "material"
      
      plugins:
        - search
        - mkdocstrings:
            handlers:
              python:
                options:
                  docstring_style: google
                  docstring_options:
                    returns_named_value: False
      nav:
        - 'index.md'
        - Reference: 'reference.md'
  • Создадим отдельный файл для референсов – reference.md:
    • Основные ссылки на рабочие модули.
      
      ::: src.my_module

Сборка документации

  • В отличие от sphinx, в mkdocs есть встроенный тестовый сервер, поэтому можно запускать сразу этот сервер и, редактирую документацию, в реальном времени видеть, как она обновляется:
    •     mkdocs serve
  • Но есть и простая статичная сборка:
    •     mkdocs build

Итог: Главная страница

mkdocs-example.png

Итог: Документация кода

mkdocs-code-example.png

Итог: Исходный код

mkdocs-viewcode-example.png

Поддержка Jupyter notebooks

  • Для этого тоже есть отдельный плагин – mkdocs-jupyter, который позволяет добавлять в виде отдельных страниц полноценные jupyter тетради, при этом есть возможность кастомизировать результат.
  • Конфигурация в mkdocs.yml:
    • plugins:
        - search
        ...
        - mkdocs-jupyter:
            execute: true
            allow_errors: false
      
      nav:
        - EDA: basic.ipynb

Пример Jupyter notebook в итоговой документации

mkdocs-jupyter-example.png

Quarto

Quarto — это система публикации/рендеринга отчетов и статей. Quarto является надстройкой над pandoc и полностью поддерживает markdown (с некоторыми расширениями) для написания отчетов.

Как это работает:

qmd-how-it-works.png

Установка Quarto

  • Quarto рекомендуется устанавливать с использованием их бинарных релизов, которые они выкладывают у себя на сайте под разные платформы.
  • Установка с PyPI
    •     pip install -U quarto-cli jupyter
  • Установка с conda-forge
    •      conda install -c conda-forge quarto jupyter

Создание проекта

  • Создание quarto website project:
    •     quarto create project website --no-open "docs"
  • Итоговая структура:
    •     .
          └── docs-example/
              └── docs/
                  ├── _quarto.yml
                  ├── index.qmd
                  ├── about.qmd
                  └── styles.css

Конфигурация: Создание Quarto тетради

Пример Quarto тетради:

quarto-basic-example.png

Конфигурация: Добавление Quarto тетради к навигации сайта

project:
    type: website
    
website:
    title: "Docs"
    navbar:
        left:
        - href: index.qmd
            text: Home
        - href: quarto-basics.html
            text: Quarto Basics
        - about.qmd
    
format:
    html:
        theme: cosmo
        css: styles.css
        toc: true

Конфигурация: Расширение в vscode для работы с Quarto тетрадями

python-vscode.png

Сборка документации

  • При необходимости есть возможность запускать встроенный сервер, чтобы писать документацию и сразу видеть изменения:
    •     quarto preview docs
  • И естественно есть возможно собрать целиком весь сайт:
    •     quarto render docs

Итог: Главная страница

quarto-example.png

Итог: Quarto (или Jupyter) тетрадь

quarto-notebook-example.png

Поддержка документации кода

  • Quarto в целом себя позиционировал именно как инструмент написания статей, поэтому механизма работы с docstring на данный момент в нём нет, однако, один из авторов Quarto разработал для него расширение – quartodoc.
  • Настройка в _quarto.yml:
    • # tell quarto to read the generated sidebar
      metadata-files:
        - _sidebar.yml
      
      quartodoc:
        # the name used to import the package you want to create reference docs for
        package: src
      
        # A directory where source files to be documented live. 
        # This is only necessary if you are not documenting a package, 
        # but collection of scripts. 
        source_dir: src
      
        # write sidebar data to this file
        sidebar: _sidebar.yml
      
        # Parser settings
        parser: google
      
        sections:
          - title: Some functions
            desc: Functions to inspect docstrings.
            contents:
              # the functions being documented in the package.
              # you can refer to anything: class methods, modules, etc..
              - my_module.add
  • После этого, как в Sphinx, в начале делаем сборку docstring в qmd:
    •     quartodoc build --config="docs/_quarto.yml"
  • А затем уже собираем всю документацию целиком:
    •     quarto render docs

Итог: Документация кода

quartodoc-example.png

Сборка в Gitlab-CI на примере Quarto

stages:
    - pages
    
default:
    image: mambaorg/micromamba
    before_script:
        - micromamba create -n pages python=3.11 quarto jupyter -c conda-forge
        - micromamba run -n pages python -m ipykernel install --user --name python3
    cache:
        key: generated-reports
        paths:
        - docs/_site
    
pages:
    stage: pages
    script:
        - micromamba run -n pages quarto render docs
        - cp -r docs/_site public
    artifacts:
        paths:
        - public
    rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Вывод