]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/python/src/object/function_doc_signature.cpp
1 // Copyright Nikolay Mladenov 2007.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 // boost::python::make_tuple below are for gcc 4.4 -std=c++0x compatibility
7 // (Intel C++ 10 and 11 with -std=c++0x don't need the full qualification).
9 #include <boost/python/converter/registrations.hpp>
10 #include <boost/python/object/function_doc_signature.hpp>
11 #include <boost/python/errors.hpp>
12 #include <boost/python/str.hpp>
13 #include <boost/python/args.hpp>
14 #include <boost/python/tuple.hpp>
16 #include <boost/python/detail/signature.hpp>
20 namespace boost
{ namespace python
{ namespace objects
{
22 bool function_doc_signature_generator::arity_cmp( function
const *f1
, function
const *f2
)
24 return f1
->m_fn
.max_arity() < f2
->m_fn
.max_arity();
27 bool function_doc_signature_generator::are_seq_overloads( function
const *f1
, function
const *f2
, bool check_docs
)
29 py_function
const & impl1
= f1
->m_fn
;
30 py_function
const & impl2
= f2
->m_fn
;
32 //the number of parameters differs by 1
33 if (impl2
.max_arity()-impl1
.max_arity() != 1)
36 // if check docs then f1 shold not have docstring or have the same docstring as f2
37 if (check_docs
&& f2
->doc() != f1
->doc() && f1
->doc())
40 python::detail::signature_element
const* s1
= impl1
.signature();
41 python::detail::signature_element
const* s2
= impl2
.signature();
43 unsigned size
= impl1
.max_arity()+1;
45 for (unsigned i
= 0; i
!= size
; ++i
)
47 //check if the argument types are the same
48 if (s1
[i
].basename
!= s2
[i
].basename
)
54 //check if the argument default values are the same
55 bool f1_has_names
= bool(f1
->m_arg_names
);
56 bool f2_has_names
= bool(f2
->m_arg_names
);
57 if ( (f1_has_names
&& f2_has_names
&& f2
->m_arg_names
[i
-1]!=f1
->m_arg_names
[i
-1])
58 || (f1_has_names
&& !f2_has_names
)
59 || (!f1_has_names
&& f2_has_names
&& f2
->m_arg_names
[i
-1]!=python::object())
66 std::vector
<function
const*> function_doc_signature_generator::flatten(function
const *f
)
68 object name
= f
->name();
70 std::vector
<function
const*> res
;
74 //this if takes out the not_implemented_function
75 if (f
->name() == name
)
78 f
=f
->m_overloads
.get();
81 //std::sort(res.begin(),res.end(), &arity_cmp);
85 std::vector
<function
const*> function_doc_signature_generator::split_seq_overloads( const std::vector
<function
const *> &funcs
, bool split_on_doc_change
)
87 std::vector
<function
const*> res
;
89 std::vector
<function
const*>::const_iterator fi
= funcs
.begin();
91 function
const * last
= *fi
;
93 while (++fi
!= funcs
.end()){
95 //check if fi starts a new chain of overloads
96 if (!are_seq_overloads( last
, *fi
, split_on_doc_change
))
108 str
function_doc_signature_generator::raw_function_pretty_signature(function
const *f
, size_t n_overloads
, bool cpp_types
)
112 res
= str("%s %s(%s)" % make_tuple( res
, f
->m_name
, str("tuple args, dict kwds")) );
117 const char * function_doc_signature_generator::py_type_str(const python::detail::signature_element
&s
)
119 if (s
.basename
==std::string("void")){
120 static const char * none
= "None";
124 PyTypeObject
const * py_type
= s
.pytype_f
?s
.pytype_f():0;
126 return py_type
->tp_name
;
128 static const char * object
= "object";
133 str
function_doc_signature_generator::parameter_string(py_function
const &f
, size_t n
, object arg_names
, bool cpp_types
)
137 python::detail::signature_element
const * s
= f
.signature();
141 s
= &f
.get_return_type();
142 if (s
[n
].basename
== 0)
147 param
= str(s
[n
].basename
);
150 param
+= " {lvalue}";
155 if (n
) //we are processing an argument and trying to come up with a name for it
158 if ( arg_names
&& (kv
= arg_names
[n
-1]) )
159 param
= str( " (%s)%s" % make_tuple(py_type_str(s
[n
]),kv
[0]) );
161 param
= str(" (%s)%s%d" % make_tuple(py_type_str(s
[n
]),"arg", n
) );
163 else //we are processing the return type
164 param
= py_type_str(f
.get_return_type());
167 //an argument - check for default value and append it
170 object
kv(arg_names
[n
-1]);
171 if (kv
&& len(kv
) == 2)
173 param
= str("%s=%r" % make_tuple(param
, kv
[1]));
179 str
function_doc_signature_generator::pretty_signature(function
const *f
, size_t n_overloads
, bool cpp_types
)
182 const& impl
= f
->m_fn
;
186 unsigned arity
= impl
.max_arity();
188 if(arity
== unsigned(-1))// is this the proper raw function test?
190 return raw_function_pretty_signature(f
,n_overloads
,cpp_types
);
195 size_t n_extra_default_args
=0;
197 for (unsigned n
= 0; n
<= arity
; ++n
)
201 formal_params
.append(
202 parameter_string(impl
, n
, f
->m_arg_names
, cpp_types
)
205 // find all the arguments with default values preceeding the arity-n_overloads
206 if (n
&& f
->m_arg_names
)
208 object
kv(f
->m_arg_names
[n
-1]);
210 if (kv
&& len(kv
) == 2)
212 //default argument preceeding the arity-n_overloads
213 if( n
<= arity
-n_overloads
)
214 ++n_extra_default_args
;
217 //argument without default, preceeding the arity-n_overloads
218 if( n
<= arity
-n_overloads
)
219 n_extra_default_args
= 0;
223 n_overloads
+=n_extra_default_args
;
225 if (!arity
&& cpp_types
)
226 formal_params
.append("void");
228 str
ret_type (formal_params
.pop(0));
233 % boost::python::make_tuple
// workaround, see top
236 , str(",").join(formal_params
.slice(0,arity
-n_overloads
))
237 , n_overloads
? (n_overloads
!=arity
?str(" [,"):str("[ ")) : str()
238 , str(" [,").join(formal_params
.slice(arity
-n_overloads
,arity
))
239 , std::string(n_overloads
,']')
244 % boost::python::make_tuple
// workaround, see top
246 , str(",").join(formal_params
.slice(0,arity
-n_overloads
))
247 , n_overloads
? (n_overloads
!=arity
?str(" [,"):str("[ ")) : str()
248 , str(" [,").join(formal_params
.slice(arity
-n_overloads
,arity
))
249 , std::string(n_overloads
,']')
256 % boost::python::make_tuple
// workaround, see top
257 ( cpp_types
?ret_type
:str("")
259 , str(",").join(formal_params
.slice(0,arity
-n_overloads
))
260 , n_overloads
? (n_overloads
!=arity
?str(" [,"):str("[ ")) : str()
261 , str(" [,").join(formal_params
.slice(arity
-n_overloads
,arity
))
262 , std::string(n_overloads
,']')
263 , cpp_types
?str(""):ret_type
269 char py_signature_tag
[] = "PY signature :";
270 char cpp_signature_tag
[] = "C++ signature :";
273 list
function_doc_signature_generator::function_doc_signatures( function
const * f
)
276 std::vector
<function
const*> funcs
= flatten( f
);
277 std::vector
<function
const*> split_funcs
= split_seq_overloads( funcs
, true);
278 std::vector
<function
const*>::const_iterator sfi
=split_funcs
.begin(), fi
;
279 size_t n_overloads
=0;
280 for (fi
=funcs
.begin(); fi
!=funcs
.end(); ++fi
)
285 str func_doc
= str((*fi
)->doc());
287 int doc_len
= len(func_doc
);
289 bool show_py_signature
= doc_len
>= int(sizeof(detail::py_signature_tag
)/sizeof(char)-1)
290 && str(detail::py_signature_tag
) == func_doc
.slice(0, int(sizeof(detail::py_signature_tag
)/sizeof(char))-1);
291 if(show_py_signature
)
293 func_doc
= str(func_doc
.slice(int(sizeof(detail::py_signature_tag
)/sizeof(char))-1, _
));
294 doc_len
= len(func_doc
);
297 bool show_cpp_signature
= doc_len
>= int(sizeof(detail::cpp_signature_tag
)/sizeof(char)-1)
298 && str(detail::cpp_signature_tag
) == func_doc
.slice( 1-int(sizeof(detail::cpp_signature_tag
)/sizeof(char)), _
);
300 if(show_cpp_signature
)
302 func_doc
= str(func_doc
.slice(_
, 1-int(sizeof(detail::cpp_signature_tag
)/sizeof(char))));
303 doc_len
= len(func_doc
);
309 if(show_py_signature
)
311 str sig
= pretty_signature(*fi
, n_overloads
,false);
313 if(doc_len
|| show_cpp_signature
)res
+=" :";
319 if(show_py_signature
)
321 res
+= pad
.join(func_doc
.split("\n"));
324 if( show_cpp_signature
)
328 res
+=detail::cpp_signature_tag
+pad
+" "+pretty_signature(*fi
, n_overloads
,true);
331 signatures
.append(res
);