Monday, July 9, 2007

Boost.Python: docstrings in enums

For quite some time I wanted to add docstrings to enums exposed with Boost.Python as my project's API docs seemed incomplete. Let's see how I found the solution eventually:

Enum we want to expose:
// Nice enum!
enum Foo
{
    blah
};

While exposing the enum itself couldn't be any simpler:
BOOST_PYTHON_MODULE(enum_test)
{
    bp::enum_<Foo> enum_foo("Foo");
    enum_foo.value("blah", blah);
    ...
... adding __doc__ is completly another story.

First (silly) attempt:
...
    PyObject_SetAttrString(enum_foo.ptr(), "__doc__",
        PyString_FromString("Nice enum!"));
};
"It must work" I thought, but what I got on import then was far from satisfying:

TypeError: attribute '__doc__' of 'type' objects is not writable

After digging in Boost.Python, Python C API docs and harassing people at #python:
...
    PyTypeObject * pto = reinterpret_cast(enum_foo.ptr());
    pto->tp_doc = "Nice enum!";
};
Thils looked really promising... and what? Nothing at all! Changing tp_doc had no effect whatsoever, and only after some more digging, it turned out it was too late to change it and the right way is:
...
    PyTypeObject * pto = reinterpret_cast(enum_foo.ptr());
    PyDict_SetItemString(pto->tp_dict, "__doc__",
        PyString_FromString("Nice enum!"));
};
Boost.Python and Python C API are fun ;)