Fork me on GitHub
8/9/2006

Документируй это

У Python есть одна замечательная особенность - у него есть встроенные средства документирования кода. Так называемые docstring'и. О них и пойдет речь...

Docstring - (сокращение от documentation string, строка документации) встроенное средство документирования модулей, функций, классов и методов. Делается очень просто - сразу после определения указывается строковое значение, которое и будет docstring'ом.

>>> def test():
...    "This is the test's docstring"
...    print "opa"

Получить доступ к docstring можно так:

>>> test.__doc__
"This is the test's docstring"

Либо так:

>>> help(test)
Help on function test in module __main__:

test()
    This is the test's docstring

Существуют инструменты, которые позволяют извлекать docstring не по одиночке, а для целого модуля/пакета. О них и пойдет речь.

pydoc

Pydoc входит в стандартную поставку Python. Для того, чтобы сгенерировать HTML-документацию для модуля, достаточно выполнить:

pydoc -w module_name

и Вы на выходе получите module_name.html. Одна интересная возможность pydoc - использование его как http-сервера для документации по всем установленным модулям. Достаточно запустить pydoc с параметром -g:

pydoc -g

PyDoc показывает docstring как есть, он не использует какие-либо правила форматирования.

HappyDoc

HappyDoc - достаточно популярный инструмент (используется в достаточно крупных проектах, например NumPy), хотя прекратил свое развитие где-то три года назад. В отличии от pydoc, использующего интроспекцию (т.е. импортирует модуль и "обходит" все объекты) для создания документации, HappyDoc самостоятельно разбирает Python-исходники и уже по результатам разбора составляет документацию. Такой подход имеет как свои плюсы, так и минусы. Положительные стороны:

  • можно обрабатывать модули, у которых не удовлетворены зависимости, либо не желательно их импортировать
  • есть возможно обрабатывать комментарии, которые при интроспекции "теряются"

Отрицательные:

  • нет возможности обрабатывать C-модули
  • сложности в обработки модуля, "хитрым" образом меняющего пространство имен, или, например, генерирующегося "на лету"

HappyDoc достаточно гибок - поддерживает различные типы разметок (StructuredText, StructuredTextNG, plain text, raw text), можно создать свой собственный.

pudge

Pudge - в отличии от остальных упомянутых инструментов, ориентирован, в первую очередь, для публикации API-документации в интернете. Также возможна интеграция с Trac. Внешний вид готовой документации задается шаблонами kid. Для построения документации использует как разбор кода собственным парсером, так и интроспекцию. Внутри docstring'ов позволяет форматировать текст по правилам reStructuredText. Одна из особенностей pudge - помимо представления информации из docsting'ов, он сохраняет в html весь код модуля.

Из недостатков могу отметить "неровности" в процессе установки - кое-где приходится "напильником" дорабатывать. Однако автор сразу предупреждает о том, что pudge находится в процессе активной доработки.

epydoc

Epydoc - на мой взгляд, наиболее интересный инструмент для создания API-документации. Я рассмотрю версию 3.0, которая обладает более широкими возможностями, чем предыдущая 2.1.

Умеет сохранять "расцвеченный" код модуля, для построения документации использует и интроспекцию, и разбор кода. В этом плане он схож с pudge. Шаблоны он не использует, лишь при помощи css можно менять цветовую схему. Помимо html умеет выводить в LaTeX и pdf. Из отличительных особенностей отмечу использование собственной разметки epytext, хотя поддерживаются reStructuredText и JavaDoc. Далее, при помощи graphviz умеет строить UML-диаграммы классов.

В целом, мне он понравился больше всех. В скором времени расскажу об epydoc чуть подробнее.

Примеры

Для примера написал ничего-не-делающий модуль foo:

"""Module's docstring"""

__docformat__ = "restructuredtext"

CONST='Opa-la' #: doccomment for CONST

def bar(x):
    """bar - returns repr(x)"""

    return repr(x)

class Foo(object):
    """Example of class'es doctstring"""

    classattr = "Class attribute" #: doccomment for class attribute

    def __init__(self, arg):
        """
        Constructor for foo object

        :param arg: Dummy argument for constructor
        :type arg: basestring
        """
        self.arg = arg

    def go(self, parm):
        """

        Dummy action for object Foo

        :param parm: Dummy parameter of method

        :return: Returns parm
        """
        x = repr(parm) #: doccomment for x: x is a representation of parm
        return parm

И обработал его каждым из упомянутых инструментов. Результат можете взять здесь

Комментарии

Все статьи