@@ -228,6 +228,58 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
228228 return 0 ;
229229}
230230
231+ object function::signature (bool show_return_type) const
232+ {
233+ py_function const & impl = m_fn;
234+
235+ python::detail::signature_element const * return_type = impl.signature ();
236+ python::detail::signature_element const * s = return_type + 1 ;
237+
238+ list formal_params;
239+ if (impl.max_arity () == 0 )
240+ formal_params.append (" void" );
241+
242+ for (unsigned n = 0 ; n < impl.max_arity (); ++n)
243+ {
244+ if (s[n].basename == 0 )
245+ {
246+ formal_params.append (" ..." );
247+ break ;
248+ }
249+
250+ str param (s[n].basename );
251+ if (s[n].lvalue )
252+ param += " {lvalue}" ;
253+
254+ if (m_arg_names) // None or empty tuple will test false
255+ {
256+ object kv (m_arg_names[n]);
257+ if (kv)
258+ {
259+ char const * const fmt = len (kv) > 1 ? " %s=%r" : " %s" ;
260+ param += fmt % kv;
261+ }
262+ }
263+
264+ formal_params.append (param);
265+ }
266+
267+ if (show_return_type)
268+ return " %s(%s) -> %s" % make_tuple (
269+ m_name, str (" , " ).join (formal_params), return_type->basename );
270+ return " %s(%s)" % make_tuple (
271+ m_name, str (" , " ).join (formal_params));
272+ }
273+
274+ object function::signatures (bool show_return_type) const
275+ {
276+ list result;
277+ for (function const * f = this ; f; f = f->m_overloads .get ()) {
278+ result.append (f->signature (show_return_type));
279+ }
280+ return result;
281+ }
282+
231283void function::argument_error (PyObject* args, PyObject* /* keywords*/ ) const
232284{
233285 static handle<> exception (
@@ -244,50 +296,7 @@ void function::argument_error(PyObject* args, PyObject* /*keywords*/) const
244296 }
245297 message += str (" , " ).join (actual_args);
246298 message += " )\n did not match C++ signature:\n " ;
247-
248- list signatures;
249- for (function const * f = this ; f; f = f->m_overloads .get ())
250- {
251- py_function const & impl = f->m_fn ;
252-
253- python::detail::signature_element const * s
254- = impl.signature () + 1 ; // skip over return type
255-
256- list formal_params;
257- if (impl.max_arity () == 0 )
258- formal_params.append (" void" );
259-
260- for (unsigned n = 0 ; n < impl.max_arity (); ++n)
261- {
262- if (s[n].basename == 0 )
263- {
264- formal_params.append (" ..." );
265- break ;
266- }
267-
268- str param (s[n].basename );
269- if (s[n].lvalue )
270- param += " {lvalue}" ;
271-
272- if (f->m_arg_names ) // None or empty tuple will test false
273- {
274- object kv (f->m_arg_names [n]);
275- if (kv)
276- {
277- char const * const fmt = len (kv) > 1 ? " %s=%r" : " %s" ;
278- param += fmt % kv;
279- }
280- }
281-
282- formal_params.append (param);
283- }
284-
285- signatures.append (
286- " %s(%s)" % make_tuple (f->m_name , str (" , " ).join (formal_params))
287- );
288- }
289-
290- message += str (" \n " ).join (signatures);
299+ message += str (" \n " ).join (signatures ());
291300
292301#if BOOST_PYTHON_DEBUG_ERROR_MESSAGES
293302 std::printf (" \n --------\n %s\n --------\n " , extract<const char *>(message)());
@@ -391,6 +400,12 @@ namespace
391400
392401void function::add_to_namespace (
393402 object const & name_space, char const * name_, object const & attribute)
403+ {
404+ add_to_namespace (name_space, name_, attribute, 0 );
405+ }
406+
407+ void function::add_to_namespace (
408+ object const & name_space, char const * name_, object const & attribute, char const * doc)
394409{
395410 str const name (name_);
396411 PyObject* const ns = name_space.ptr ();
@@ -463,16 +478,11 @@ void function::add_to_namespace(
463478 PyErr_Clear ();
464479 if (PyObject_SetAttr (ns, name.ptr (), attribute.ptr ()) < 0 )
465480 throw_error_already_set ();
466- }
467481
468- void function::add_to_namespace (
469- object const & name_space, char const * name_, object const & attribute, char const * doc)
470- {
471- add_to_namespace (name_space, name_, attribute);
482+ object mutable_attribute (attribute);
472483 if (doc != 0 )
473484 {
474485 // Accumulate documentation
475- object mutable_attribute (attribute);
476486
477487 if (
478488 PyObject_HasAttrString (mutable_attribute.ptr (), " __doc__" )
@@ -481,21 +491,35 @@ void function::add_to_namespace(
481491 mutable_attribute.attr (" __doc__" ) += " \n\n " ;
482492 mutable_attribute.attr (" __doc__" ) += doc;
483493 }
484- else
494+ else {
485495 mutable_attribute.attr (" __doc__" ) = doc;
496+ }
497+ }
498+
499+ {
500+ if ( PyObject_HasAttrString (mutable_attribute.ptr (), " __doc__" )
501+ && mutable_attribute.attr (" __doc__" )) {
502+ mutable_attribute.attr (" __doc__" ) += " \n " ;
503+ }
504+ else {
505+ mutable_attribute.attr (" __doc__" ) = " " ;
506+ }
507+ function* f = downcast<function>(attribute.ptr ());
508+ mutable_attribute.attr (" __doc__" ) += str (" \n " ).join (make_tuple (
509+ " C++ signature:" , f->signature (true )));
486510 }
487511}
488512
489513BOOST_PYTHON_DECL void add_to_namespace (
490514 object const & name_space, char const * name, object const & attribute)
491515{
492- function::add_to_namespace (name_space, name, attribute);
516+ function::add_to_namespace (name_space, name, attribute, 0 );
493517}
494518
495519BOOST_PYTHON_DECL void add_to_namespace (
496520 object const & name_space, char const * name, object const & attribute, char const * doc)
497521{
498- function::add_to_namespace (name_space, name, attribute, doc);
522+ function::add_to_namespace (name_space, name, attribute, doc);
499523}
500524
501525
0 commit comments