diff --git a/include/boost/python/converter/as_to_python_function.hpp b/include/boost/python/converter/as_to_python_function.hpp index b343b4db..19a3efaa 100644 --- a/include/boost/python/converter/as_to_python_function.hpp +++ b/include/boost/python/converter/as_to_python_function.hpp @@ -39,6 +39,9 @@ struct as_to_python_function // but c'est la vie. return ToPython::convert(*const_cast(static_cast(x))); } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const * get_pytype() { return ToPython::get_pytype(); } +#endif }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/builtin_converters.hpp b/include/boost/python/converter/builtin_converters.hpp index dddb154c..df32ad21 100644 --- a/include/boost/python/converter/builtin_converters.hpp +++ b/include/boost/python/converter/builtin_converters.hpp @@ -47,7 +47,7 @@ namespace detail } // Use expr to create the PyObject corresponding to x -# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr) \ +# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr, pytype)\ template <> struct to_python_value \ : detail::builtin_to_python \ { \ @@ -55,6 +55,10 @@ namespace detail { \ return (expr); \ } \ + inline PyTypeObject const* get_pytype() const \ + { \ + return (pytype); \ + } \ }; \ template <> struct to_python_value \ : detail::builtin_to_python \ @@ -63,6 +67,10 @@ namespace detail { \ return (expr); \ } \ + inline PyTypeObject const* get_pytype() const \ + { \ + return (pytype); \ + } \ }; # define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \ @@ -77,25 +85,25 @@ namespace detail } // Specialize argument and return value converters for T using expr -# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \ - BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr) \ +# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr, pytype) \ + BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr, pytype) \ BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr) // Specialize converters for signed and unsigned T to Python Int # define BOOST_PYTHON_TO_INT(T) \ - BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x)) \ + BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x), &PyInt_Type) \ BOOST_PYTHON_TO_PYTHON_BY_VALUE( \ unsigned T \ , static_cast(x) > static_cast( \ (std::numeric_limits::max)()) \ ? ::PyLong_FromUnsignedLong(x) \ - : ::PyInt_FromLong(x)) + : ::PyInt_FromLong(x), &PyInt_Type) // Bool is not signed. #if PY_VERSION_HEX >= 0x02030000 -BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyBool_FromLong(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyBool_FromLong(x), &PyBool_Type) #else -BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x), &PyInt_Type) #endif // note: handles signed char and unsigned char, but not char (see below) @@ -108,25 +116,25 @@ BOOST_PYTHON_TO_INT(long) // using Python's macro instead of Boost's - we don't seem to get the // config right all the time. # ifdef HAVE_LONG_LONG -BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x)) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x), &PyInt_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyInt_Type) # endif # undef BOOST_TO_PYTHON_INT -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast(x.size()))) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyString_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyString_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast(x.size())), &PyString_Type) #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast(x.size()))) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast(x.size())), &PyString_Type) # endif -BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x)) -BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x)) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag())) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag())) -BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag())) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x), &PyFloat_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x), &PyFloat_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x), &PyFloat_Type) +BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x), 0) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type) +BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type) # undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE # undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE diff --git a/include/boost/python/converter/pyobject_traits.hpp b/include/boost/python/converter/pyobject_traits.hpp index ce7d3fb4..03ef4460 100644 --- a/include/boost/python/converter/pyobject_traits.hpp +++ b/include/boost/python/converter/pyobject_traits.hpp @@ -18,6 +18,9 @@ struct pyobject_traits // All objects are convertible to PyObject static bool check(PyObject*) { return true; } static PyObject* checked_downcast(PyObject* x) { return x; } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const* get_pytype() { return 0; } +#endif }; // diff --git a/include/boost/python/converter/pyobject_type.hpp b/include/boost/python/converter/pyobject_type.hpp index a02974cd..526f9f9d 100644 --- a/include/boost/python/converter/pyobject_type.hpp +++ b/include/boost/python/converter/pyobject_type.hpp @@ -14,7 +14,7 @@ BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*); // Used as a base class for specializations which need to provide // Python type checking capability. template -struct pyobject_type +struct pyobject_type { static bool check(PyObject* x) { @@ -27,6 +27,9 @@ struct pyobject_type (checked_downcast_impl)(x, pytype) ); } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const* get_pytype() { return pytype; } +#endif }; }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/pytype_function.hpp b/include/boost/python/converter/pytype_function.hpp new file mode 100755 index 00000000..95d0f66d --- /dev/null +++ b/include/boost/python/converter/pytype_function.hpp @@ -0,0 +1,132 @@ +// Copyright David Abrahams 2002, 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) +#ifndef WRAP_PYTYPE_NM20070606_HPP +# define WRAP_PYTYPE_NM20070606_HPP + +# include +# include +# include + + +namespace boost { namespace python { + +namespace converter +{ +template +struct wrap_pytype +{ + static PyTypeObject const* get_pytype() + { + return python_type; + } +}; + +typedef PyTypeObject const* (*pytype_function)(); + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + + + +namespace detail +{ +struct unwind_type_id_helper{ + typedef python::type_info result_type; + template + static result_type execute(U* ){ + return python::type_id(); + } +}; + +template +inline python::type_info unwind_type_id_(boost::type* = 0, mpl::false_ * =0) +{ + return boost::python::detail::unwind_type (); +} + +inline python::type_info unwind_type_id_(boost::type* = 0, mpl::true_* =0) +{ + return type_id(); +} + +template +inline python::type_info unwind_type_id(boost::type* p= 0) +{ + return unwind_type_id_(p, (mpl::bool_::value >*)0 ); +} +} + + +template +struct expected_pytype_for_arg +{ + static PyTypeObject const *get_pytype() + { + const converter::registration *r=converter::registry::query( + detail::unwind_type_id_((boost::type*)0, (mpl::bool_::value >*)0 ) + ); + return r ? r->expected_from_python_type(): 0; + } +}; + + +template +struct registered_pytype +{ + static PyTypeObject const *get_pytype() + { + const converter::registration *r=converter::registry::query( + detail::unwind_type_id_((boost::type*) 0, (mpl::bool_::value >*)0 ) + ); + return r ? r->m_class_object: 0; + } +}; + + +template +struct registered_pytype_direct +{ + static PyTypeObject const* get_pytype() + { + return registered::converters.m_class_object; + } +}; + +template +struct expected_from_python_type : expected_pytype_for_arg{}; + +template +struct expected_from_python_type_direct +{ + static PyTypeObject const* get_pytype() + { + return registered::converters.expected_from_python_type(); + } +}; + +template +struct to_python_target_type +{ + static PyTypeObject const *get_pytype() + { + const converter::registration *r=converter::registry::query( + detail::unwind_type_id_((boost::type*)0, (mpl::bool_::value >*)0 ) + ); + return r ? r->to_python_target_type(): 0; + } +}; + +template +struct to_python_target_type_direct +{ + static PyTypeObject const *get_pytype() + { + return registered::converters.to_python_target_type(); + } +}; +#endif + +}}} // namespace boost::python + +#endif // WRAP_PYTYPE_NM20070606_HPP diff --git a/include/boost/python/converter/registrations.hpp b/include/boost/python/converter/registrations.hpp index d71401de..7ef74e8f 100644 --- a/include/boost/python/converter/registrations.hpp +++ b/include/boost/python/converter/registrations.hpp @@ -27,6 +27,7 @@ struct rvalue_from_python_chain { convertible_function convertible; constructor_function construct; + PyTypeObject const* (*expected_pytype)(); rvalue_from_python_chain* next; }; @@ -34,6 +35,7 @@ struct BOOST_PYTHON_DECL registration { public: // member functions explicit registration(type_info target, bool is_shared_ptr = false); + ~registration(); // Convert the appropriately-typed data to Python PyObject* to_python(void const volatile*) const; @@ -42,6 +44,11 @@ struct BOOST_PYTHON_DECL registration // exception if no class has been registered. PyTypeObject* get_class_object() const; + // Return common denominator of the python class objects, + // convertable to target. Inspects the m_class_object and the value_chains. + PyTypeObject const* expected_from_python_type() const; + PyTypeObject const* to_python_target_type() const; + public: // data members. So sue me. const python::type_info target_type; @@ -56,6 +63,8 @@ struct BOOST_PYTHON_DECL registration // The unique to_python converter for the associated C++ type. to_python_function_t m_to_python; + PyTypeObject const* (*m_to_python_target_type)(); + // True iff this type is a shared_ptr. Needed for special rvalue // from_python handling. @@ -76,6 +85,7 @@ inline registration::registration(type_info target_type, bool is_shared_ptr) , rvalue_chain(0) , m_class_object(0) , m_to_python(0) + , m_to_python_target_type(0) , is_shared_ptr(is_shared_ptr) {} diff --git a/include/boost/python/converter/registry.hpp b/include/boost/python/converter/registry.hpp index 5492edf7..e037bbcc 100644 --- a/include/boost/python/converter/registry.hpp +++ b/include/boost/python/converter/registry.hpp @@ -27,16 +27,17 @@ namespace registry // Return a pointer to the corresponding registration, if one exists BOOST_PYTHON_DECL registration const* query(type_info); - BOOST_PYTHON_DECL void insert(to_python_function_t, type_info); + BOOST_PYTHON_DECL void insert(to_python_function_t, type_info, PyTypeObject const* (*to_python_target_type)() = 0); // Insert an lvalue from_python converter - BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info); + BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info, PyTypeObject const* (*expected_pytype)() = 0); // Insert an rvalue from_python converter BOOST_PYTHON_DECL void insert( convertible_function , constructor_function , type_info + , PyTypeObject const* (*expected_pytype)() = 0 ); // Insert an rvalue from_python converter at the tail of the @@ -45,6 +46,7 @@ namespace registry convertible_function , constructor_function , type_info + , PyTypeObject const* (*expected_pytype)() = 0 ); } diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index 577fb447..6b49c469 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -10,6 +10,9 @@ # include # include # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif # include namespace boost { namespace python { namespace converter { @@ -19,7 +22,11 @@ struct shared_ptr_from_python { shared_ptr_from_python() { - converter::registry::insert(&convertible, &construct, type_id >()); + converter::registry::insert(&convertible, &construct, type_id >() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &converter::expected_from_python_type_direct::get_pytype +#endif + ); } private: diff --git a/include/boost/python/default_call_policies.hpp b/include/boost/python/default_call_policies.hpp index 800cce79..3d32d2eb 100644 --- a/include/boost/python/default_call_policies.hpp +++ b/include/boost/python/default_call_policies.hpp @@ -13,6 +13,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -49,6 +50,12 @@ struct default_call_policies typedef default_result_converter result_converter; typedef PyObject* argument_package; + + template + struct extract_return_type : mpl::front + { + }; + }; struct default_result_converter diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index 1054b6e2..e479bf42 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -11,12 +11,15 @@ # include # include +# include + # include # include # include # include # include +# include # include # include @@ -89,6 +92,27 @@ inline ResultConverter create_result_converter( { return ResultConverter(); } + +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +template +struct converter_target_type +{ + static PyTypeObject const *get_pytype() + { + return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype(); + } +}; + +template < > +struct converter_target_type +{ + static PyTypeObject const *get_pytype() + { + return 0; + } +}; +#endif + template struct caller_arity; @@ -203,11 +227,26 @@ struct caller_arity static unsigned min_arity() { return N; } - static signature_element const* signature() + static py_func_sig_info signature() { - return detail::signature::elements(); + const signature_element * sig = detail::signature::elements(); +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + + typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type::type rtype; + typedef typename select_result_converter::type result_converter; + + static const signature_element ret = { + (boost::is_void::value ? "void" : type_id().name()) + , &detail::converter_target_type::get_pytype + , boost::detail::indirect_traits::is_reference_to_non_const::value + }; + py_func_sig_info res = {sig, &ret }; +#else + py_func_sig_info res = {sig, sig }; +#endif + + return res; } - private: compressed_pair m_data; }; diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index cfd762b9..acafc037 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -134,4 +134,8 @@ #include #endif // auto-linking disabled +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +#define BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // enables smooth transition +#endif + #endif // CONFIG_DWA052200_H_ diff --git a/include/boost/python/detail/def_helper.hpp b/include/boost/python/detail/def_helper.hpp index 33abf19d..e68ca0cd 100644 --- a/include/boost/python/detail/def_helper.hpp +++ b/include/boost/python/detail/def_helper.hpp @@ -155,7 +155,7 @@ namespace detail , T3 const& , T4 const& , default_call_policies - , keywords<0> + , detail::keywords<0> , char const* , void(not_specified::*)() // A function pointer type which is never an // appropriate default implementation diff --git a/include/boost/python/detail/defaults_def.hpp b/include/boost/python/detail/defaults_def.hpp index 9ce98a62..68799f83 100644 --- a/include/boost/python/detail/defaults_def.hpp +++ b/include/boost/python/detail/defaults_def.hpp @@ -168,7 +168,7 @@ namespace detail char const* doc) { // define the NTH stub function of stubs - define_stub_function::define(name, stubs, kw, policies, name_space, 0); + define_stub_function::define(name, stubs, kw, policies, name_space, doc); if (kw.second > kw.first) --kw.second; diff --git a/include/boost/python/detail/defaults_gen.hpp b/include/boost/python/detail/defaults_gen.hpp index 45274957..0b3e0e26 100644 --- a/include/boost/python/detail/defaults_gen.hpp +++ b/include/boost/python/detail/defaults_gen.hpp @@ -248,7 +248,7 @@ namespace detail BOOST_PYTHON_GEN_MEM_FUNCTION( \ fname, void_return_type, n_args, n_dflts, ;) \ \ - BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ + BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \ }; # else // !defined(BOOST_NO_VOID_RETURNS) @@ -273,7 +273,7 @@ namespace detail fname, non_void_return_type, n_args, n_dflts, return) \ \ typedef non_void_return_type void_return_type; \ - BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \ + BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \ }; # endif // !defined(BOOST_NO_VOID_RETURNS) diff --git a/include/boost/python/detail/make_keyword_range_fn.hpp b/include/boost/python/detail/make_keyword_range_fn.hpp index bc959997..634bbb99 100644 --- a/include/boost/python/detail/make_keyword_range_fn.hpp +++ b/include/boost/python/detail/make_keyword_range_fn.hpp @@ -57,6 +57,9 @@ object make_keyword_range_constructor( , Holder* = 0 , ArgList* = 0, Arity* = 0) { +#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE) + python_class::register_(); +#endif return detail::make_keyword_range_function( objects::make_holder ::template apply::execute diff --git a/include/boost/python/detail/operator_id.hpp b/include/boost/python/detail/operator_id.hpp index f2cd404e..4a2785ed 100755 --- a/include/boost/python/detail/operator_id.hpp +++ b/include/boost/python/detail/operator_id.hpp @@ -47,7 +47,8 @@ enum operator_id op_ixor, op_ior, op_complex, - op_nonzero + op_nonzero, + op_repr }; }}} // namespace boost::python::detail diff --git a/include/boost/python/detail/python_type.hpp b/include/boost/python/detail/python_type.hpp new file mode 100755 index 00000000..f7630c17 --- /dev/null +++ b/include/boost/python/detail/python_type.hpp @@ -0,0 +1,37 @@ +// 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) +#ifndef BOOST_PYTHON_OBJECT_PYTHON_TYPE_H +#define BOOST_PYTHON_OBJECT_PYTHON_TYPE_H + +#include + +namespace boost {namespace python {namespace detail{ + + +template struct python_class : PyObject +{ + typedef python_class this_type; + + typedef T type; + + static void *converter (PyObject *p){ + return p; + } + + static void register_() + { + static bool first_time = true; + + if ( !first_time ) return; + + first_time = false; + converter::registry::insert(&converter, boost::python::type_id(), &converter::registered_pytype_direct::get_pytype); + } +}; + + +}}} //namespace boost :: python :: detail + +#endif //BOOST_PYTHON_OBJECT_PYTHON_TYPE_H diff --git a/include/boost/python/detail/signature.hpp b/include/boost/python/detail/signature.hpp index 26e986cc..11268b92 100644 --- a/include/boost/python/detail/signature.hpp +++ b/include/boost/python/detail/signature.hpp @@ -12,6 +12,7 @@ # include # include +# include # include # include @@ -24,9 +25,16 @@ namespace boost { namespace python { namespace detail { struct signature_element { char const* basename; + converter::pytype_function pytype_f; bool lvalue; }; +struct py_func_sig_info +{ + signature_element const *signature; + signature_element const *ret; +}; + template struct signature_arity; # define BOOST_PP_ITERATION_PARAMS_1 \ @@ -68,15 +76,25 @@ struct signature_arity { static signature_element const result[N+2] = { +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES # define BOOST_PP_LOCAL_MACRO(i) \ - { \ - type_id::type>().name() \ - , indirect_traits::is_reference_to_non_const::type>::value \ - }, + { \ + type_id::type>().name() \ + , &converter::expected_pytype_for_arg::type>::get_pytype \ + , indirect_traits::is_reference_to_non_const::type>::value \ + }, +#else +# define BOOST_PP_LOCAL_MACRO(i) \ + { \ + type_id::type>().name() \ + , 0 \ + , indirect_traits::is_reference_to_non_const::type>::value \ + }, +#endif # define BOOST_PP_LOCAL_LIMITS (0, N) # include BOOST_PP_LOCAL_ITERATE() - {0,0} + {0,0,0} }; return result; } diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp new file mode 100755 index 00000000..3c6f8ca2 --- /dev/null +++ b/include/boost/python/detail/unwind_type.hpp @@ -0,0 +1,170 @@ +// Copyright David Abrahams 2002. +// 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) +#ifndef UNWIND_TYPE_DWA200222_HPP +# define UNWIND_TYPE_DWA200222_HPP + +# include +# include +# include + +namespace boost { namespace python { namespace detail { + +#ifndef _MSC_VER //if forward declared, msvc6.5 does not recognize them as inline +// forward declaration, required (at least) by Tru64 cxx V6.5-042 +template +inline typename Generator::result_type +unwind_type(U const& p, Generator* = 0); + +// forward declaration, required (at least) by Tru64 cxx V6.5-042 +template +inline typename Generator::result_type +unwind_type(boost::type*p = 0, Generator* = 0); +#endif + +template +inline typename Generator::result_type +unwind_type_cv(U* p, cv_unqualified, Generator* = 0) +{ + return Generator::execute(p); +} + +template +inline typename Generator::result_type +unwind_type_cv(U const* p, const_, Generator* = 0) +{ + return unwind_type(const_cast(p), (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_type_cv(U volatile* p, volatile_, Generator* = 0) +{ + return unwind_type(const_cast(p), (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0) +{ + return unwind_type(const_cast(p), (Generator*)0); +} + +template +inline typename Generator::result_type +unwind_ptr_type(U* p, Generator* = 0) +{ + typedef typename cv_category::type tag; + return unwind_type_cv(p, tag()); +} + +template +struct unwind_helper +{ + template + static typename Generator::result_type + execute(U p, Generator* = 0) + { + return unwind_ptr_type(p, (Generator*)0); + } +}; + +template <> +struct unwind_helper +{ + template + static typename Generator::result_type + execute(U& p, Generator* = 0) + { + return unwind_ptr_type(&p, (Generator*)0); + } +}; + +template +inline typename Generator::result_type +#ifndef _MSC_VER +unwind_type(U const& p, Generator*) +#else +unwind_type(U const& p, Generator* = 0) +#endif +{ + return unwind_helper::value>::execute(p, (Generator*)0); +} + +enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 }; +template struct unwind_helper2; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U*(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U&(*)(), Generator* = 0) + { + return unwind_ptr_type((U*)0, (Generator*)0); + } +}; + +template <> +struct unwind_helper2 +{ + template + static typename Generator::result_type + execute(U&(*)(), Generator* = 0) + { + return unwind_ptr_type(U(0), (Generator*)0); + } +}; + +// Call this one with both template parameters explicitly specified +// and no function arguments: +// +// return unwind_type(); +// +// Doesn't work if T is an array type; we could handle that case, but +// why bother? +template +inline typename Generator::result_type +#ifndef _MSC_VER +unwind_type(boost::type*p, Generator*) +#else +unwind_type(boost::type*p =0, Generator* =0) +#endif +{ + BOOST_STATIC_CONSTANT(int, indirection + = (boost::is_pointer::value ? pointer_ : 0) + + (indirect_traits::is_reference_to_pointer::value + ? reference_to_pointer_ + : boost::is_reference::value + ? reference_ + : 0)); + + return unwind_helper2::execute((U(*)())0,(Generator*)0); +} + +}}} // namespace boost::python::detail + +#endif // UNWIND_TYPE_DWA200222_HPP diff --git a/include/boost/python/docstring_options.hpp b/include/boost/python/docstring_options.hpp index 507a4c5d..1914bd51 100755 --- a/include/boost/python/docstring_options.hpp +++ b/include/boost/python/docstring_options.hpp @@ -17,23 +17,38 @@ class BOOST_PYTHON_DECL docstring_options : boost::noncopyable docstring_options(bool show_all=true) { previous_show_user_defined_ = show_user_defined_; - previous_show_signatures_ = show_signatures_; + previous_show_py_signatures_ = show_py_signatures_; + previous_show_cpp_signatures_ = show_cpp_signatures_; show_user_defined_ = show_all; - show_signatures_ = show_all; + show_cpp_signatures_ = show_all; + show_py_signatures_ = show_all; } docstring_options(bool show_user_defined, bool show_signatures) { previous_show_user_defined_ = show_user_defined_; - previous_show_signatures_ = show_signatures_; + previous_show_cpp_signatures_ = show_cpp_signatures_; + previous_show_py_signatures_ = show_py_signatures_; show_user_defined_ = show_user_defined; - show_signatures_ = show_signatures; + show_cpp_signatures_ = show_signatures; + show_py_signatures_ = show_signatures; + } + + docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures) + { + previous_show_user_defined_ = show_user_defined_; + previous_show_cpp_signatures_ = show_cpp_signatures_; + previous_show_py_signatures_ = show_py_signatures_; + show_user_defined_ = show_user_defined; + show_cpp_signatures_ = show_cpp_signatures; + show_py_signatures_ = show_py_signatures; } ~docstring_options() { show_user_defined_ = previous_show_user_defined_; - show_signatures_ = previous_show_signatures_; + show_cpp_signatures_ = previous_show_cpp_signatures_; + show_py_signatures_ = previous_show_py_signatures_; } void @@ -43,32 +58,68 @@ class BOOST_PYTHON_DECL docstring_options : boost::noncopyable enable_user_defined() { show_user_defined_ = true; } void - disable_signatures() { show_signatures_ = false; } + disable_py_signatures() + { + show_py_signatures_ = false; + } void - enable_signatures() { show_signatures_ = true; } + enable_py_signatures() + { + show_py_signatures_ = true; + } + + void + disable_cpp_signatures() + { + show_cpp_signatures_ = false; + } + + void + enable_cpp_signatures() + { + show_cpp_signatures_ = true; + } + + void + disable_signatures() + { + show_cpp_signatures_ = false; + show_py_signatures_ = false; + } + + void + enable_signatures() + { + show_cpp_signatures_ = true; + show_py_signatures_ = true; + } void disable_all() { show_user_defined_ = false; - show_signatures_ = false; + show_cpp_signatures_ = false; + show_py_signatures_ = false; } void enable_all() { show_user_defined_ = true; - show_signatures_ = true; + show_cpp_signatures_ = true; + show_py_signatures_ = true; } friend struct objects::function; private: static volatile bool show_user_defined_; - static volatile bool show_signatures_; + static volatile bool show_cpp_signatures_; + static volatile bool show_py_signatures_; bool previous_show_user_defined_; - bool previous_show_signatures_; + bool previous_show_cpp_signatures_; + bool previous_show_py_signatures_; }; }} // namespace boost::python diff --git a/include/boost/python/enum.hpp b/include/boost/python/enum.hpp index 24b616a4..57684530 100644 --- a/include/boost/python/enum.hpp +++ b/include/boost/python/enum.hpp @@ -19,7 +19,7 @@ struct enum_ : public objects::enum_base typedef objects::enum_base base; // Declare a new enumeration type in the current scope() - enum_(char const* name); + enum_(char const* name, char const* doc = 0); // Add a new enumeration value with the given name and value. inline enum_& value(char const* name, T); @@ -34,13 +34,15 @@ struct enum_ : public objects::enum_base }; template -inline enum_::enum_(char const* name) +inline enum_::enum_(char const* name, char const* doc ) : base( name , &enum_::to_python , &enum_::convertible_from_python , &enum_::construct - , type_id()) + , type_id() + , doc + ) { } diff --git a/include/boost/python/implicit.hpp b/include/boost/python/implicit.hpp index 14a69700..4d01b2fb 100644 --- a/include/boost/python/implicit.hpp +++ b/include/boost/python/implicit.hpp @@ -9,6 +9,9 @@ # include # include # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif # include namespace boost { namespace python { @@ -21,7 +24,11 @@ void implicitly_convertible(boost::type* = 0, boost::type* = 0) converter::registry::push_back( &functions::convertible , &functions::construct - , type_id()); + , type_id() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &converter::expected_from_python_type_direct::get_pytype +#endif + ); } }} // namespace boost::python diff --git a/include/boost/python/init.hpp b/include/boost/python/init.hpp index a07359e6..6598fd35 100644 --- a/include/boost/python/init.hpp +++ b/include/boost/python/init.hpp @@ -245,7 +245,7 @@ class init : public init_base > : base(doc_, kw.range()) { typedef typename detail::error::more_keywords_than_init_arguments< - N, n_arguments::value + N, n_arguments::value + 1 >::too_many_keywords assertion; } @@ -254,7 +254,7 @@ class init : public init_base > : base(doc_, kw.range()) { typedef typename detail::error::more_keywords_than_init_arguments< - N, n_arguments::value + N, n_arguments::value + 1 >::too_many_keywords assertion; } @@ -363,7 +363,7 @@ namespace detail , char const* doc , detail::keyword_range keywords) { - detail::def_init_aux(cl, args, NArgs(), policies, 0, keywords); + detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords); if (keywords.second > keywords.first) --keywords.second; diff --git a/include/boost/python/lvalue_from_pytype.hpp b/include/boost/python/lvalue_from_pytype.hpp index 51660050..019d4ae5 100755 --- a/include/boost/python/lvalue_from_pytype.hpp +++ b/include/boost/python/lvalue_from_pytype.hpp @@ -6,6 +6,9 @@ # define LVALUE_FROM_PYTYPE_DWA2002130_HPP # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif # include # include @@ -81,12 +84,17 @@ struct extract_identity // Extractor's static execute function from Python objects whose type // object is python_type. template -struct lvalue_from_pytype +struct lvalue_from_pytype { lvalue_from_pytype() { - converter::registry::insert( - &extract, detail::extractor_type_id(&Extractor::execute)); + converter::registry::insert + ( &extract + , detail::extractor_type_id(&Extractor::execute) +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &get_pytype +#endif + ); } private: static void* extract(PyObject* op) @@ -98,6 +106,9 @@ struct lvalue_from_pytype : 0 ; } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const*get_pytype() { return python_type; } +#endif }; }} // namespace boost::python diff --git a/include/boost/python/make_constructor.hpp b/include/boost/python/make_constructor.hpp index 598bf4f6..972de5fc 100755 --- a/include/boost/python/make_constructor.hpp +++ b/include/boost/python/make_constructor.hpp @@ -23,6 +23,7 @@ # include # include # include +# include namespace boost { namespace python { @@ -103,13 +104,23 @@ namespace detail // If the BasePolicy_ supplied a result converter it would be // ignored; issue an error if it's not the default. - BOOST_STATIC_ASSERT(( - is_same< +#if defined _MSC_VER && _MSC_VER < 1300 + typedef is_same< typename BasePolicy_::result_converter , default_result_converter - >::value - )); - + > same_result_converter; + //see above for explanation + BOOST_STATIC_ASSERT(same_result_converter::value) ; +#else + BOOST_MPL_ASSERT_MSG( + (is_same< + typename BasePolicy_::result_converter + , default_result_converter + >::value) + , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS + , (typename BasePolicy_::result_converter) + ); +#endif typedef constructor_result_converter result_converter; typedef offset_args > argument_package; }; diff --git a/include/boost/python/numeric.hpp b/include/boost/python/numeric.hpp index 66fde676..ab4db8c3 100644 --- a/include/boost/python/numeric.hpp +++ b/include/boost/python/numeric.hpp @@ -92,6 +92,7 @@ namespace aux { static bool check(PyObject* obj); static detail::new_non_null_reference adopt(PyObject* obj); + static PyTypeObject const* get_pytype() ; }; } // namespace aux diff --git a/include/boost/python/object/class_metadata.hpp b/include/boost/python/object/class_metadata.hpp index bf0e2748..05740b8e 100755 --- a/include/boost/python/object/class_metadata.hpp +++ b/include/boost/python/object/class_metadata.hpp @@ -238,6 +238,14 @@ struct class_metadata // inline static void maybe_register_pointer_to_python(void*,void*,void*) {} +#ifndef BOOST_PYTHON_NO_PY_SYGNATURES + inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*) + { + objects::copy_class_object(python::type_id(), python::type_id >()); + objects::copy_class_object(python::type_id(), python::type_id >()); + } +#endif + template inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*) { @@ -247,6 +255,10 @@ struct class_metadata , make_ptr_instance > >() ); +#ifndef BOOST_PYTHON_NO_PY_SYGNATURES + // explicit qualification of type_id makes msvc6 happy + objects::copy_class_object(python::type_id(), python::type_id()); +#endif } // // Support for registering to-python converters @@ -258,6 +270,10 @@ struct class_metadata inline static void maybe_register_class_to_python(T2*, mpl::false_) { python::detail::force_instantiate(class_cref_wrapper >()); +#ifndef BOOST_PYTHON_NO_PY_SYGNATURES + // explicit qualification of type_id makes msvc6 happy + objects::copy_class_object(python::type_id(), python::type_id()); +#endif } // diff --git a/include/boost/python/object/class_wrapper.hpp b/include/boost/python/object/class_wrapper.hpp index 5097ee5a..ffee7457 100644 --- a/include/boost/python/object/class_wrapper.hpp +++ b/include/boost/python/object/class_wrapper.hpp @@ -6,6 +6,9 @@ # define CLASS_WRAPPER_DWA20011221_HPP # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif # include namespace boost { namespace python { namespace objects { @@ -19,22 +22,28 @@ namespace boost { namespace python { namespace objects { template struct class_cref_wrapper - : to_python_converter > + : to_python_converter ,true> { static PyObject* convert(Src const& x) { return MakeInstance::execute(boost::ref(x)); } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype() { return converter::registered_pytype_direct::get_pytype(); } +#endif }; template struct class_value_wrapper - : to_python_converter > + : to_python_converter ,true> { static PyObject* convert(Src x) { return MakeInstance::execute(x); } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype() { return MakeInstance::get_pytype(); } +#endif }; }}} // namespace boost::python::objects diff --git a/include/boost/python/object/enum_base.hpp b/include/boost/python/object/enum_base.hpp index 7062ed90..be342742 100644 --- a/include/boost/python/object/enum_base.hpp +++ b/include/boost/python/object/enum_base.hpp @@ -21,7 +21,9 @@ struct BOOST_PYTHON_DECL enum_base : python::api::object , converter::to_python_function_t , converter::convertible_function , converter::constructor_function - , type_info); + , type_info + , const char *doc = 0 + ); void add_value(char const* name, long value); void export_values(); diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index 5ef0f827..e44ca5b2 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -14,6 +14,7 @@ namespace boost { namespace python { namespace objects { + struct BOOST_PYTHON_DECL function : PyObject { function( @@ -53,6 +54,7 @@ struct BOOST_PYTHON_DECL function : PyObject object m_doc; object m_arg_names; unsigned m_nkeyword_values; + friend class function_doc_signature_generator; }; // diff --git a/include/boost/python/object/function_doc_signature.hpp b/include/boost/python/object/function_doc_signature.hpp new file mode 100755 index 00000000..4f00cb38 --- /dev/null +++ b/include/boost/python/object/function_doc_signature.hpp @@ -0,0 +1,36 @@ +// 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) +#ifndef FUNCTION_SIGNATURE_20070531_HPP +# define FUNCTION_SIGNATURE_20070531_HPP + +#include +#include +#include +#include + +#include + + +#include + +namespace boost { namespace python { namespace objects { + +class function_doc_signature_generator{ + static const char * py_type_str(const python::detail::signature_element &s); + static bool arity_cmp( function const *f1, function const *f2 ); + static bool are_seq_overloads( function const *f1, function const *f2 , bool check_docs); + static std::vector flatten(function const *f); + static std::vector split_seq_overloads( const std::vector &funcs, bool split_on_doc_change); + static str raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); + static str parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types); + static str pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); + +public: + static list function_doc_signatures( function const * f); +}; + +}}}//end of namespace boost::python::objects + +#endif //FUNCTION_SIGNATURE_20070531_HPP diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 83c18582..9d5de98d 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -11,6 +11,10 @@ # include # include +# include +#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE) +# include +#endif # include # include @@ -74,7 +78,11 @@ struct make_holder # endif static void execute( - PyObject* p +#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE) + boost::python::detail::python_class *p +#else + PyObject *p +#endif BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a)) { typedef instance instance_t; diff --git a/include/boost/python/object/make_ptr_instance.hpp b/include/boost/python/object/make_ptr_instance.hpp index d045243b..9fdb23f6 100644 --- a/include/boost/python/object/make_ptr_instance.hpp +++ b/include/boost/python/object/make_ptr_instance.hpp @@ -29,7 +29,12 @@ struct make_ptr_instance { return get_class_object_impl(get_pointer(x)); } - +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static inline PyTypeObject const* get_pytype() + { + return converter::registered::converters.get_class_object(); + } +#endif private: template static inline PyTypeObject* get_class_object_impl(U const volatile* p) diff --git a/include/boost/python/object/py_function.hpp b/include/boost/python/object/py_function.hpp index b8ef5ab4..ba9aadf4 100644 --- a/include/boost/python/object/py_function.hpp +++ b/include/boost/python/object/py_function.hpp @@ -23,7 +23,7 @@ struct BOOST_PYTHON_DECL py_function_impl_base virtual PyObject* operator()(PyObject*, PyObject*) = 0; virtual unsigned min_arity() const = 0; virtual unsigned max_arity() const; - virtual python::detail::signature_element const* signature() const = 0; + virtual python::detail::py_func_sig_info signature() const = 0; }; template @@ -43,7 +43,7 @@ struct caller_py_function_impl : py_function_impl_base return m_caller.min_arity(); } - virtual python::detail::signature_element const* signature() const + virtual python::detail::py_func_sig_info signature() const { return m_caller.signature(); } @@ -69,9 +69,11 @@ struct signature_py_function_impl : py_function_impl_base return mpl::size::value - 1; } - virtual python::detail::signature_element const* signature() const + virtual python::detail::py_func_sig_info signature() const { - return python::detail::signature::elements(); + python::detail::signature_element const* sig = python::detail::signature::elements(); + python::detail::py_func_sig_info res = {sig, sig}; + return res; } private: @@ -102,9 +104,11 @@ struct full_py_function_impl : py_function_impl_base return m_max_arity; } - virtual python::detail::signature_element const* signature() const + virtual python::detail::py_func_sig_info signature() const { - return python::detail::signature::elements(); + python::detail::signature_element const* sig = python::detail::signature::elements(); + python::detail::py_func_sig_info res = {sig, sig}; + return res; } private: @@ -151,7 +155,12 @@ struct py_function python::detail::signature_element const* signature() const { - return m_impl->signature(); + return m_impl->signature().signature; + } + + python::detail::signature_element const& get_return_type() const + { + return *m_impl->signature().ret; } private: diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index 6aa5df21..ecd7257f 100755 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -470,6 +470,9 @@ namespace converter { return python::detail::new_non_null_reference(x); } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype() {return 0;} +#endif }; } diff --git a/include/boost/python/object_protocol.hpp b/include/boost/python/object_protocol.hpp index 2011b04a..e8d35866 100755 --- a/include/boost/python/object_protocol.hpp +++ b/include/boost/python/object_protocol.hpp @@ -12,46 +12,55 @@ namespace boost { namespace python { namespace api { +# if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) +// attempt to use SFINAE to prevent functions accepting T const& from +// coming up as ambiguous with the one taking a char const* when a +// string literal is passed +# define BOOST_PYTHON_NO_ARRAY_ARG(T) , T (*)() = 0 +# else +# define BOOST_PYTHON_NO_ARRAY_ARG(T) +# endif + template -object getattr(Target const& target, Key const& key) +object getattr(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) { return getattr(object(target), object(key)); } template -object getattr(Target const& target, Key const& key, Default const& default_) +object getattr(Target const& target, Key const& key, Default const& default_ BOOST_PYTHON_NO_ARRAY_ARG(key)) { return getattr(object(target), object(key), object(default_)); } template -void setattr(object const& target, Key const& key, Value const& value) +void setattr(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(key)) { setattr(target, object(key), object(value)); } template -void delattr(object const& target, Key const& key) +void delattr(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) { delattr(target, object(key)); } template -object getitem(Target const& target, Key const& key) +object getitem(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) { return getitem(object(target), object(key)); } template -void setitem(object const& target, Key const& key, Value const& value) +void setitem(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(key)) { setitem(target, object(key), object(value)); } template -void delitem(object const& target, Key const& key) +void delitem(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) { delitem(target, object(key)); } diff --git a/include/boost/python/opaque_pointer_converter.hpp b/include/boost/python/opaque_pointer_converter.hpp index 83c76433..745a5cd4 100644 --- a/include/boost/python/opaque_pointer_converter.hpp +++ b/include/boost/python/opaque_pointer_converter.hpp @@ -1,4 +1,4 @@ -// Copyright Gottfried Ganßauge 2003..2006 +// Copyright Gottfried Ganßauge 2003..2006. // 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) @@ -93,8 +93,13 @@ private: if ((existing == 0) || (existing->m_to_python == 0)) { +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + converter::registry::insert(&extract, type_id(), &get_pytype); + converter::registry::insert(&wrap, type_id(), &get_pytype); +#else converter::registry::insert(&extract, type_id()); converter::registry::insert(&wrap, type_id()); +#endif } } @@ -105,6 +110,9 @@ private: }; static PyTypeObject type_object; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + static PyTypeObject const *get_pytype(){return &type_object; } +#endif }; template diff --git a/include/boost/python/operators.hpp b/include/boost/python/operators.hpp index 41f24d28..e929779e 100644 --- a/include/boost/python/operators.hpp +++ b/include/boost/python/operators.hpp @@ -347,6 +347,7 @@ BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_) BOOST_PYTHON_UNARY_OPERATOR(float, double, float_) BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex, complex_) BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast, str) +BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast, repr) # undef BOOST_PYTHON_UNARY_OPERATOR }} // namespace boost::python @@ -358,6 +359,7 @@ using boost::python::self_ns::long_; using boost::python::self_ns::float_; using boost::python::self_ns::complex_; using boost::python::self_ns::str; +using boost::python::self_ns::repr; using boost::python::self_ns::pow; # endif diff --git a/include/boost/python/return_arg.hpp b/include/boost/python/return_arg.hpp index a6f651b6..c36f898d 100755 --- a/include/boost/python/return_arg.hpp +++ b/include/boost/python/return_arg.hpp @@ -8,10 +8,15 @@ # include # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif + # include # include # include +# include # include # include @@ -44,6 +49,9 @@ namespace detail { return none(); } +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + PyTypeObject const *get_pytype() const { return converter::expected_pytype_for_arg::get_pytype() ; } +#endif }; }; }; @@ -82,6 +90,12 @@ struct return_arg : Base Py_DECREF(result); return incref( detail::get(mpl::int_(),args) ); } + + template + struct extract_return_type : mpl::at_c + { + }; + }; template < diff --git a/include/boost/python/suite/indexing/indexing_suite.hpp b/include/boost/python/suite/indexing/indexing_suite.hpp index 0ebb755a..b636b211 100644 --- a/include/boost/python/suite/indexing/indexing_suite.hpp +++ b/include/boost/python/suite/indexing/indexing_suite.hpp @@ -17,73 +17,73 @@ # include namespace boost { namespace python { - + // indexing_suite class. This class is the facade class for // the management of C++ containers intended to be integrated // to Python. The objective is make a C++ container look and // feel and behave exactly as we'd expect a Python container. // By default indexed elements are returned by proxy. This can be // disabled by supplying *true* in the NoProxy template parameter. - // + // // Derived classes provide the hooks needed by the indexing_suite // to do its job: // - // static data_type& + // static data_type& // get_item(Container& container, index_type i); // - // static object + // static object // get_slice(Container& container, index_type from, index_type to); // - // static void + // static void // set_item(Container& container, index_type i, data_type const& v); // - // static void + // static void // set_slice( - // Container& container, index_type from, + // Container& container, index_type from, // index_type to, data_type const& v // ); // // template - // static void - // set_slice(Container& container, index_type from, + // static void + // set_slice(Container& container, index_type from, // index_type to, Iter first, Iter last // ); // - // static void + // static void // delete_item(Container& container, index_type i); - // - // static void + // + // static void // delete_slice(Container& container, index_type from, index_type to); - // + // // static size_t // size(Container& container); // // template // static bool // contains(Container& container, T const& val); - // + // // static index_type // convert_index(Container& container, PyObject* i); - // + // // static index_type - // adjust_index(index_type current, index_type from, + // adjust_index(index_type current, index_type from, // index_type to, size_type len // ); // - // Most of these policies are self explanatory. convert_index and - // adjust_index, however, deserves some explanation. + // Most of these policies are self explanatory. convert_index and + // adjust_index, however, deserves some explanation. // - // convert_index converts an Python index into a C++ index that the - // container can handle. For instance, negative indexes in Python, by - // convention, indexes from the right (e.g. C[-1] indexes the rightmost - // element in C). convert_index should handle the necessary conversion + // convert_index converts an Python index into a C++ index that the + // container can handle. For instance, negative indexes in Python, by + // convention, indexes from the right (e.g. C[-1] indexes the rightmost + // element in C). convert_index should handle the necessary conversion // for the C++ container (e.g. convert -1 to C.size()-1). convert_index // should also be able to convert the type of the index (A dynamic Python // type) to the actual type that the C++ container expects. // // When a container expands or contracts, held indexes to its elements // must be adjusted to follow the movement of data. For instance, if - // we erase 3 elements, starting from index 0 from a 5 element vector, + // we erase 3 elements, starting from index 0 from a 5 element vector, // what used to be at index 4 will now be at index 1: // // [a][b][c][d][e] ---> [d][e] @@ -104,7 +104,7 @@ namespace boost { namespace python { , class Index = typename Container::size_type , class Key = typename Container::value_type > - class indexing_suite + class indexing_suite : public def_visitor< indexing_suite< Container @@ -117,7 +117,7 @@ namespace boost { namespace python { > > { private: - + typedef mpl::or_< mpl::bool_ , mpl::not_ > @@ -127,10 +127,10 @@ namespace boost { namespace python { , is_same > , is_same > >::type> no_proxy; - + typedef detail::container_element container_element_t; - + #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) struct return_policy : return_internal_reference<> {}; #else @@ -142,7 +142,7 @@ namespace boost { namespace python { , iterator , iterator >::type def_iterator; - + typedef typename mpl::if_< no_proxy , detail::no_proxy_helper< @@ -172,15 +172,15 @@ namespace boost { namespace python { , Data , Index> >::type slice_handler; - + public: - + template void visit(Class& cl) const { // Hook into the class_ generic visitation .def function proxy_handler::register_container_element(); - + cl .def("__len__", base_size) .def("__setitem__", &base_set_item) @@ -189,12 +189,12 @@ namespace boost { namespace python { .def("__contains__", &base_contains) .def("__iter__", def_iterator()) ; - + DerivedPolicies::extension_def(cl); - } - + } + template - static void + static void extension_def(Class& cl) { // default. @@ -202,24 +202,24 @@ namespace boost { namespace python { } private: - + static object base_get_item(back_reference container, PyObject* i) - { + { if (PySlice_Check(i)) return slice_handler::base_get_slice( - container.get(), reinterpret_cast(i)); - + container.get(), static_cast(static_cast(i))); + return proxy_handler::base_get_item_(container, i); } - - static void + + static void base_set_item(Container& container, PyObject* i, PyObject* v) { if (PySlice_Check(i)) { - slice_handler::base_set_slice(container, - reinterpret_cast(i), v); + slice_handler::base_set_slice(container, + static_cast(static_cast(i)), v); } else { @@ -228,7 +228,7 @@ namespace boost { namespace python { if (elem.check()) { DerivedPolicies:: - set_item(container, + set_item(container, DerivedPolicies:: convert_index(container, i), elem()); } @@ -239,7 +239,7 @@ namespace boost { namespace python { if (elem.check()) { DerivedPolicies:: - set_item(container, + set_item(container, DerivedPolicies:: convert_index(container, i), elem()); } @@ -252,20 +252,20 @@ namespace boost { namespace python { } } - static void + static void base_delete_item(Container& container, PyObject* i) { if (PySlice_Check(i)) { slice_handler::base_delete_slice( - container, reinterpret_cast(i)); + container, static_cast(static_cast(i))); return; } - + Index index = DerivedPolicies::convert_index(container, i); proxy_handler::base_erase_index(container, index, mpl::bool_()); DerivedPolicies::delete_item(container, index); - } + } static size_t base_size(Container& container) @@ -290,10 +290,10 @@ namespace boost { namespace python { return DerivedPolicies::contains(container, x()); else return false; - } + } } }; - -}} // namespace boost::python + +}} // namespace boost::python #endif // INDEXING_SUITE_JDG20036_HPP diff --git a/include/boost/python/to_python_converter.hpp b/include/boost/python/to_python_converter.hpp index b7dd3c3d..378d159e 100644 --- a/include/boost/python/to_python_converter.hpp +++ b/include/boost/python/to_python_converter.hpp @@ -9,13 +9,67 @@ # include # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif # include namespace boost { namespace python { -template -struct to_python_converter +#if 0 //get_pytype member detection +namespace detail { + typedef char yes_type; + typedef struct {char a[2]; } no_type; + template struct test_get_pytype1 { }; + template struct test_get_pytype2 { }; + + template yes_type tester(test_get_pytype1<&T::get_pytype>*); + + template yes_type tester(test_get_pytype2<&T::get_pytype>*); + + template no_type tester(...); + + template + struct test_get_pytype_base + { + BOOST_STATIC_CONSTANT(bool, value= (sizeof(detail::tester(0)) == sizeof(yes_type))); + }; + + template + struct test_get_pytype : boost::mpl::bool_::value> + { + }; + +} +#endif + +template < class T, class Conversion, bool has_get_pytype=false > +struct to_python_converter +{ +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +#if 0 //defined _MSC_VER && _MSC_VER >=1310 + //probably other compilers could come here as well + typedef typename detail::test_get_pytype HasGetPytype; +#else + typedef boost::mpl::bool_ HasGetPytype; +#endif + + static PyTypeObject const* get_pytype_1(boost::mpl::true_ *) + { + return Conversion::get_pytype(); + } + + static PyTypeObject const* get_pytype_1(boost::mpl::false_ *) + { + return 0; + } + static PyTypeObject const* get_pytype_impl() + { + return get_pytype_1((HasGetPytype*)0); + } +#endif + to_python_converter(); }; @@ -23,18 +77,23 @@ struct to_python_converter // implementation // -template -to_python_converter::to_python_converter() +template +to_python_converter::to_python_converter() { typedef converter::as_to_python_function< T, Conversion > normalized; - + converter::registry::insert( &normalized::convert - , type_id()); + , type_id() +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + , &get_pytype_impl +#endif + ); } }} // namespace boost::python #endif // TO_PYTHON_CONVERTER_DWA200221_HPP + diff --git a/include/boost/python/to_python_indirect.hpp b/include/boost/python/to_python_indirect.hpp index a39b723d..23ad0263 100644 --- a/include/boost/python/to_python_indirect.hpp +++ b/include/boost/python/to_python_indirect.hpp @@ -12,6 +12,10 @@ # include +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES +# include +#endif + # include # include @@ -36,7 +40,13 @@ struct to_python_indirect { return this->execute(const_cast(ref), is_pointer()); } - +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + inline PyTypeObject const* + get_pytype()const + { + return converter::registered_pytype::get_pytype(); + } +#endif private: template inline PyObject* execute(U* ptr, mpl::true_) const diff --git a/include/boost/python/to_python_value.hpp b/include/boost/python/to_python_value.hpp index 7c350bb4..c40299ba 100644 --- a/include/boost/python/to_python_value.hpp +++ b/include/boost/python/to_python_value.hpp @@ -9,12 +9,12 @@ # include # include +# include # include # include # include # include -# include # include # include @@ -24,17 +24,57 @@ # include # include +# include namespace boost { namespace python { namespace detail { +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + +template +struct object_manager_get_pytype +{ + template + static PyTypeObject const* get( U& (*p)() =0) + { + return converter::object_manager_traits::get_pytype(); + } +}; + +template <> +struct object_manager_get_pytype +{ + template + static PyTypeObject const* get( U const& (*p)() =0) + { + return converter::object_manager_traits::get_pytype(); + } +}; + +#endif + template struct object_manager_to_python_value { typedef typename value_arg::type argument_type; PyObject* operator()(argument_type) const; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + typedef boost::mpl::bool_::value> is_t_handle; + typedef boost::detail::indirect_traits::is_reference_to_const is_t_const; + PyTypeObject const* get_pytype() const { + return get_pytype_aux((is_t_handle*)0); + } + + inline static PyTypeObject const* get_pytype_aux(mpl::true_*) {return converter::object_manager_traits::get_pytype();} + + inline static PyTypeObject const* get_pytype_aux(mpl::false_* ) + { + return object_manager_get_pytype::get((T(*)())0); + } + +#endif // This information helps make_getter() decide whether to try to // return an internal reference or not. I don't like it much, @@ -49,6 +89,9 @@ namespace detail typedef typename value_arg::type argument_type; PyObject* operator()(argument_type) const; +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + PyTypeObject const* get_pytype() const {return converter::registered::converters.to_python_target_type();} +#endif // This information helps make_getter() decide whether to try to // return an internal reference or not. I don't like it much, @@ -62,11 +105,20 @@ namespace detail typedef typename value_arg::type argument_type; PyObject* operator()(argument_type) const; - +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + PyTypeObject const* get_pytype() const {return get_pytype((boost::type*)0);} +#endif // This information helps make_getter() decide whether to try to // return an internal reference or not. I don't like it much, // but it will have to serve for now. BOOST_STATIC_CONSTANT(bool, uses_registry = false); + private: +#ifndef BOOST_PYTHON_NO_PY_SIGNATURES + template + PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} + template + PyTypeObject const* get_pytype(boost::type &> *) const {return converter::registered::converters.to_python_target_type();} +#endif }; }