function_doc_signature.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 343 行

CPP
343
字号
// Copyright Nikolay Mladenov 2007.// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)#include <boost/python/converter/registrations.hpp>#include <boost/python/object/function_doc_signature.hpp>#include <boost/python/errors.hpp>#include <boost/python/str.hpp>#include <boost/python/args.hpp>#include <boost/python/tuple.hpp>#include <boost/python/detail/signature.hpp>#include <vector>namespace boost { namespace python { namespace objects {    bool function_doc_signature_generator::arity_cmp( function const *f1, function const *f2 )    {        return f1->m_fn.max_arity() < f2->m_fn.max_arity();    }    bool function_doc_signature_generator::are_seq_overloads( function const *f1, function const *f2 , bool check_docs)    {        py_function const & impl1 = f1->m_fn;        py_function const & impl2  = f2->m_fn;        //the number of parameters differs by 1        if (impl2.max_arity()-impl1.max_arity() != 1)            return false;        // if check docs then f1 shold not have docstring or have the same docstring as f2        if (check_docs && f2->doc() != f1->doc() && f1->doc())            return false;        python::detail::signature_element const* s1 = impl1.signature();        python::detail::signature_element const* s2 = impl2.signature();        unsigned size = impl1.max_arity()+1;        for (unsigned i = 0; i != size; ++i)        {            //check if the argument types are the same            if (s1[i].basename != s2[i].basename)                return false;            //return type            if (!i) continue;            //check if the argument default values are the same            bool f1_has_names = bool(f1->m_arg_names);            bool f2_has_names = bool(f2->m_arg_names);            if ( f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1]                || f1_has_names && !f2_has_names                || !f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object()                )                return false;        }        return true;    }    std::vector<function const*> function_doc_signature_generator::flatten(function const *f)    {        object name = f->name();        std::vector<function const*> res;        while (f) {            //this if takes out the not_implemented_function            if (f->name() == name)                res.push_back(f);            f=f->m_overloads.get();        }        //std::sort(res.begin(),res.end(), &arity_cmp);        return res;    }    std::vector<function const*> function_doc_signature_generator::split_seq_overloads( const std::vector<function const *> &funcs, bool split_on_doc_change)    {        std::vector<function const*> res;        std::vector<function const*>::const_iterator fi = funcs.begin();        function const * last = *fi;        while (++fi != funcs.end()){            //check if fi starts a new chain of overloads            if (!are_seq_overloads( last, *fi, split_on_doc_change ))                res.push_back(last);            last = *fi;        }        if (last)            res.push_back(last);        return res;    }    str function_doc_signature_generator::raw_function_pretty_signature(function const *f, size_t n_overloads,  bool cpp_types )    {        str res("object");        res = str("%s %s(%s)" % make_tuple( res, f->m_name, str("tuple args, dict kwds")) );        return res;    }    const  char * function_doc_signature_generator::py_type_str(const python::detail::signature_element &s)    {        if (s.basename==std::string("void")){            static const char * none = "None";            return none;        }        PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0;        if ( py_type )            return  py_type->tp_name;        else{            static const char * object = "object";            return object;        }    }    str function_doc_signature_generator::parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types)    {        str param;        python::detail::signature_element  const * s = f.signature();        if (cpp_types)        {            if(!n)                s = &f.get_return_type();            if (s[n].basename == 0)            {                return str("...");            }            param = str(s[n].basename);            if (s[n].lvalue)                 param += " {lvalue}";        }        else        {            if (n) //we are processing an argument and trying to come up with a name for it            {                object kv;                if ( arg_names && (kv = arg_names[n-1]) )                    param = str( " (%s)%s" % make_tuple(py_type_str(s[n]),kv[0]) );                else                    param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n]),"arg", n) );            }            else //we are processing the return type                param = py_type_str(f.get_return_type());        }        //an argument - check for default value and append it        if(n && arg_names)        {            object kv(arg_names[n-1]);            if (kv && len(kv) == 2)            {                param = str("%s=%r" % make_tuple(param, kv[1]));            }        }        return param;    }    str function_doc_signature_generator::pretty_signature(function const *f, size_t n_overloads,  bool cpp_types )    {        py_function            const& impl = f->m_fn;            ;        unsigned arity = impl.max_arity();        if(arity == unsigned(-1))// is this the proper raw function test?        {            return raw_function_pretty_signature(f,n_overloads,cpp_types);        }        list formal_params;        size_t n_extra_default_args=0;        for (unsigned n = 0; n <= arity; ++n)        {            str param;            formal_params.append(                parameter_string(impl, n, f->m_arg_names, cpp_types)                );            // find all the arguments with default values preceeding the arity-n_overloads            if (n && f->m_arg_names)            {                object kv(f->m_arg_names[n-1]);                if (kv && len(kv) == 2)                {                    //default argument preceeding the arity-n_overloads                    if( n <= arity-n_overloads)                        ++n_extra_default_args;                }                else                    //argument without default, preceeding the arity-n_overloads                    if( n <= arity-n_overloads)                        n_extra_default_args = 0;            }        }        n_overloads+=n_extra_default_args;        if (!arity && cpp_types)            formal_params.append("void");        str ret_type (formal_params.pop(0));        if (cpp_types )        {            return str(                "%s %s(%s%s%s%s)"                % make_tuple                ( ret_type                    , f->m_name                    , str(",").join(formal_params.slice(0,arity-n_overloads))                    , n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()                    , str(" [,").join(formal_params.slice(arity-n_overloads,arity))                    , std::string(n_overloads,']')                    ));        }else{            return str(                "%s(%s%s%s%s) -> %s"                % make_tuple                ( f->m_name                    , str(",").join(formal_params.slice(0,arity-n_overloads))                    , n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()                    , str(" [,").join(formal_params.slice(arity-n_overloads,arity))                    , std::string(n_overloads,']')                    , ret_type                    ));        }        return str(            "%s %s(%s%s%s%s) %s"            % make_tuple            ( cpp_types?ret_type:str("")                , f->m_name                , str(",").join(formal_params.slice(0,arity-n_overloads))                , n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()                , str(" [,").join(formal_params.slice(arity-n_overloads,arity))                , std::string(n_overloads,']')                , cpp_types?str(""):ret_type                ));    }    namespace detail {            char py_signature_tag[] = "PY signature :";        char cpp_signature_tag[] = "C++ signature :";    }    list function_doc_signature_generator::function_doc_signatures( function const * f)    {        list signatures;        std::vector<function const*> funcs = flatten( f);        std::vector<function const*> split_funcs = split_seq_overloads( funcs, true);        std::vector<function const*>::const_iterator sfi=split_funcs.begin(), fi;        size_t n_overloads=0;        for (fi=funcs.begin(); fi!=funcs.end(); ++fi)        {            if(*sfi == *fi){                if((*fi)->doc())                {                    str func_doc = str((*fi)->doc());                                        int doc_len = len(func_doc);                    bool show_py_signature = doc_len >= int(sizeof(detail::py_signature_tag)/sizeof(char)-1)                                            && str(detail::py_signature_tag) == func_doc.slice(0, int(sizeof(detail::py_signature_tag)/sizeof(char))-1);                    if(show_py_signature)                    {                        func_doc = str(func_doc.slice(int(sizeof(detail::py_signature_tag)/sizeof(char))-1, _));                        doc_len = len(func_doc);                    }                                        bool show_cpp_signature = doc_len >= int(sizeof(detail::cpp_signature_tag)/sizeof(char)-1)                                            && str(detail::cpp_signature_tag) == func_doc.slice( 1-int(sizeof(detail::cpp_signature_tag)/sizeof(char)), _);                                        if(show_cpp_signature)                    {                        func_doc = str(func_doc.slice(_, 1-int(sizeof(detail::cpp_signature_tag)/sizeof(char))));                        doc_len = len(func_doc);                    }                                        str res="\n";                    str pad = "\n";                    if(show_py_signature)                    {                         str sig = pretty_signature(*fi, n_overloads,false);                        res+=sig;                        if(doc_len || show_cpp_signature )res+=" :";                        pad+= str("    ");                    }                                        if(doc_len)                    {                        if(show_py_signature)                            res+=pad;                         res+= pad.join(func_doc.split("\n"));                    }                    if( show_cpp_signature)                    {                        if(len(res)>1)                            res+="\n"+pad;                        res+=detail::cpp_signature_tag+pad+"    "+pretty_signature(*fi, n_overloads,true);                    }                                        signatures.append(res);                }                ++sfi;                n_overloads = 0;            }else                ++n_overloads ;        }        return signatures;    }}}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?