11

I am currently working developing a C++-based module for Python. I have found that Boost::Python is working quite well for what I want to accomplish. However, I am now running into some issues with the docstring that is being generated by Boost::Python. Given the following Boost::Python definitions:

BOOST_PYTHON_MODULE(gcsmt)
{
class_<gcsmt::Units>("Units", "Sets the units used as input.", no_init)
    .def("PrintSupported", &gcsmt::Units::printSupported, "Print out all supported units.")
    .def("SetDefault", &gcsmt::Units::setDefaultUnit, "Sets the default unit to be used for inputs/outputs.")
    .staticmethod("PrintSupported")
    .staticmethod("SetDefault")
    .def(self_ns::str(self_ns::self))
    ;
}

If I compile, load my module in Python, and get help on the gscmt.Units class, the output is the following:

>>> help(gcsmt.Units)

Help on class Units in module gcsmt:

class Units(Boost.Python.instance)
 |  Sets the units used as input.
 |  
 |  Method resolution order:
 |      Units
 |      Boost.Python.instance
 |      __builtin__.object
 |  
 |  Methods defined here:
 |  
 |  __reduce__ = <unnamed Boost.Python function>(...)
 |  
 |  __str__(...)
 |      __str__( (Units)arg1) -> object :
 |      
 |          C++ signature :
 |              _object* __str__(gcsmt::Units {lvalue})
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  PrintSupported(...)
 |      PrintSupported() -> None :
 |          Print out all supported units.
 |      
 |          C++ signature :
 |              void PrintSupported()
 |  
 |  SetDefault(...)
 |      SetDefault( (UnitType)arg1, (str)arg2) -> None :
 |          Sets the default unit to be used for inputs/outputs.
 |      
 |          C++ signature :
 |              void SetDefault(gcsmt::unitType,std::string)
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __init__ = <built-in function __init__>
 |      Raises an exception
 |      This class cannot be instantiated from Python
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from Boost.Python.instance:
 |  
 |  __dict__
 |  
 |  __weakref__
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from Boost.Python.instance:
 |  
 |  __new__ = <built-in method __new__ of Boost.Python.class object>
 |      T.__new__(S, ...) -> a new object with type S, a subtype of T

While much of the documentation being output is valuable to me as a developer, most of it would be noise, or even worse, confusing, to an end user. (E.g.- my users don't care what the C++ signature of a given method is, nor do they need to see the Method resolution order, or additional hidden methods that are shown). Is there any way to override, and reduce the level/verbosity of the documentation set up by Boost::Python? Ideally, I'd like my documentation to look something like:

>>> help(gcsmt.Units)

Help on class Units in module gcsmt:

class Units
 |  Sets the units used as input.
 |  
 |  PrintSupported() -> None :
 |      Print out all supported units.
 |  
 |  SetDefault( (UnitType)arg1, (str)arg2) -> None :
 |      Sets the default unit to be used for inputs/outputs.

1 Answer 1

22
  • Use the boost::python::docstring_options class to define your auto-created docstring options.
  • All def functions take a docstring as the last parameter.
  • All class_ definitions take the class docstring as the last parameter

I.e.:

using boost::python;
BOOST_PYTHON_MODULE(foo)
{
  // This will enable user-defined docstrings and python signatures,
  // while disabling the C++ signatures
  docstring_options local_docstring_options(true, true, false);

  class_<Bar>("Bar", init<>(), "Bar class" /* class docstring here */ )
    .def("foobar", &Bar::foobar, "foobar function" /* function docstring here */);
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks aleksey. The docstring_options got me most of the way there. It looks like the help module in python adds a bunch of extra info to classes, but that looks like it isn't a boost issue.
docstring_options is a class that overrides the options in the ctor and restores them in the dtor, effectively changing the options in the current scope. Therefore it does not suffice to create a temporary docstring_options, you must create a local variable to keep it alive, e.g. docstring_options doc_opts(true, true, false);.
still a useful answer in 2017. note that the docstrings for class_ are slightly different than above. it goes class_<T>("PyName","class docstring",init<>(), "Init docstring"). see here
my previous comment was indicating that this answer is useful, but i meant at that time for the ordering of arguments to class_. regarding turning off C++ signatures, I just tried this answer to no avail.
however, by inspecting minieigen, i was able to see that docstring_options docopt; docopt.enable_all(); docopt.disable_cpp_signatures(); is what i needed, and confirmed works

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.