From b13c902fb04eda0cba185924d2010b2d7a092509 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 19 Jul 2003 23:49:06 +0000 Subject: [PATCH] * added return_arg policy from Nikolay Mladenov * removed duplication from reference.html * improved automatic redirection messages [SVN r19226] --- doc/v2/index.html | 2 +- doc/v2/reference.html | 173 ++++++---------------- doc/v2/return_arg.html | 219 ++++++++++++++++++++++++++++ include/boost/python/return_arg.hpp | 100 +++++++++++++ index.html | 4 +- test/Jamfile | 1 + test/return_arg.cpp | 68 +++++++++ test/return_arg.py | 22 +++ 8 files changed, 454 insertions(+), 135 deletions(-) create mode 100755 doc/v2/return_arg.html create mode 100755 include/boost/python/return_arg.hpp create mode 100755 test/return_arg.cpp create mode 100644 test/return_arg.py diff --git a/doc/v2/index.html b/doc/v2/index.html index 6f5150fb..0d5ace16 100644 --- a/doc/v2/index.html +++ b/doc/v2/index.html @@ -10,7 +10,7 @@ - Automatic redirection failed, please go to ../index.html. diff --git a/doc/v2/reference.html b/doc/v2/reference.html index 50dfd1e8..413095e3 100644 --- a/doc/v2/reference.html +++ b/doc/v2/reference.html @@ -13,7 +13,7 @@ p.c3 {font-style: italic} h2.c2 {text-align: center} h1.c1 {text-align: center} - + @@ -570,6 +570,24 @@ +
return_arg.hpp
+ +
+
+
Classes
+ +
+
+
return_arg
+ +
return_self
+
+
+
+
+
return_internal_reference.hpp
@@ -750,16 +768,18 @@ -
return_opaque_pointer.hpp
+
return_opaque_pointer.hpp
-
Classes
+
Classes
-
- return_opaque_pointer
+
return_opaque_pointer
@@ -821,139 +841,28 @@
-
opaque_pointer_converter.hpp
+
opaque_pointer_converter.hpp
-
Classes
+
Classes
-
- opaque_pointer_converter
+
opaque_pointer_converter
+
Macros
-
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
-
-
-
-
- -
opaque_pointer_converter.hpp
- -
-
-
Classes
- -
-
-
- opaque_pointer_converter
-
-
-
Macros
- -
-
-
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
-
-
-
-
- -
opaque_pointer_converter.hpp
- -
-
-
Classes
- -
-
-
- opaque_pointer_converter
-
-
-
Macros
- -
-
-
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
-
-
-
-
- -
opaque_pointer_converter.hpp
- -
-
-
Classes
- -
-
-
- opaque_pointer_converter
-
-
-
Macros
- -
-
-
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
-
-
-
-
- -
opaque_pointer_converter.hpp
- -
-
-
Classes
- -
-
-
- opaque_pointer_converter
-
-
-
Macros
- -
-
-
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
-
-
-
-
- -
opaque_pointer_converter.hpp
- -
-
-
Classes
- -
-
-
- opaque_pointer_converter
-
-
-
Macros
- -
-
-
- BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
+
+ BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID
@@ -974,11 +883,13 @@
-
register_ptr_to_python.hpp
+
register_ptr_to_python.hpp
-
Functions
+
Functions
@@ -987,8 +898,7 @@
-
- +

Utility and Infrastructure

@@ -1100,8 +1010,7 @@

Revised - 7 March, 2003 - + 19 July, 2003

© Copyright + + + + + + + + Boost.Python - <boost/python/return_arg.hpp> + + + + + + + + + +
+

C++ Boost

+
+

Boost.Python

+ +

Header <boost/python/return_arg.hpp>

+
+


+ +

Contents

+ +
+
Introduction
+ +
Classes
+ +
+
+
Class Template + return_arg
+ +
+
+
Class Template + return_arg synopsis
+ +
Class + return_arg static functions
+
+
+ +
Class Template + return_self
+
+
+ +
Example
+
+
+ +

Introduction

+ return_arg and return_self instantiations are + models of CallPolicies which return the + specified argument parameter (usually *this) of a wrapped + (member) function. + +

Classes

+ +

Class template + return_arg

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ return_arg template parameters +
ParameterRequirementsDescriptionDefault
arg_posA positive compile-time constant of type + std::size_t.the position of the argument to be returned.1
BaseA model of CallPoliciesUsed for policy composition. Any result_converter it + supplies will be overridden by return_arg, but its + precall and postcall policies are composed + as described here CallPolicies.default_call_policies
+ +

Class template + return_arg synopsis

+
+namespace boost { namespace python
+{
+   template <size_t arg_pos=1, class Base = default_call_policies>
+   struct return_arg : Base
+   {
+      static PyObject* postcall(PyObject*, PyObject* result);
+      struct result_converter{ template <class T> struct apply; };
+   };
+}}
+
+ +

Class return_arg + static functions

+
+PyObject* postcall(PyObject* args, PyObject* result);
+
+ +
+
Requires: PyTuple_Check(args) + != 0 and PyTuple_Size(args) != 0
+ +
Returns: PyTuple_GetItem(args,arg_pos-1)
+
+ +

Class template + return_self

+ +

Class template return_self synopsis:

+
+namespace boost { namespace python
+{
+   template <class Base = default_call_policies>
+   struct return_self 
+     : return_arg<1,Base>
+   {};
+}}
+
+ +

Example

+ +

C++ module definition

+
+#include <boost/python/module.hpp>
+#include <boost/python/class.hpp>
+#include <boost/python/return_arg.hpp>
+
+struct Widget
+{
+   Widget() :sensitive_(true){}
+   bool get_sensitive() const { return sensitive_; }
+   void set_sensitive(bool s) { this->sensitive_ = s; }
+ private:
+   bool sensitive_;
+};
+
+struct Label : Widget
+{
+   Label() {}
+
+   std::string  get_label() const { return label_; }
+   void set_label(const std::string &l){ label_ = l; }
+
+ private:
+   std::string label_;
+};
+
+using namespace boost::python;
+BOOST_PYTHON_MODULE(return_self_ext)
+{
+   class_<widget>("Widget")
+      .def("sensitive", &Widget::get_sensitive)
+      .def("sensitive", &Widget::set_sensitive, return_self<>())
+      ;
+
+   class_<Label, bases<Widget> >("Label")
+      .def("label", &Label::get_label)
+      .def("label", &Label::set_label, return_self<>())
+      ;
+}
+
+
+
+ +

Python code

+
+>>> from return_self_ext import *
+>>> l1 = Label().label("foo").sensitive(false)
+>>> l2 = Label().sensitive(false).label("foo") 
+
+ +

Revised + + 19 July, 2003 +

+ +

© Copyright Dave Abrahams and Nikolay + Mladenov 2003. All Rights Reserved.

+ + + diff --git a/include/boost/python/return_arg.hpp b/include/boost/python/return_arg.hpp new file mode 100755 index 00000000..8c4dc189 --- /dev/null +++ b/include/boost/python/return_arg.hpp @@ -0,0 +1,100 @@ +// Copyright David Abrahams and Nikolay Mladenov 2003. Permission to +// copy, use, modify, sell and distribute this software is granted +// provided this copyright notice appears in all copies. This software +// is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. +#ifndef RETURN_ARG_DWA2003719_HPP +# define RETURN_ARG_DWA2003719_HPP +# include +# include +# include +# include +# include +# include +# include + +namespace boost { namespace python { + +namespace detail +{ + template + struct return_arg_pos_argument_must_be_positive +# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__) + {} +# endif + ; + + struct return_none + { + template struct apply + { + struct type + { + static bool convertible() + { + return true; + } + + PyObject *operator()( + typename add_reference< + typename add_const::type + >::type + ) const + { + return none(); + } + }; + }; + }; +} + +template < + std::size_t arg_pos=1 + , class Base = default_call_policies +> +struct return_arg : Base +{ + private: + BOOST_STATIC_CONSTANT(bool, legal = arg_pos > 0); + + public: + typedef typename mpl::if_c< + legal + , detail::return_none + , detail::return_arg_pos_argument_must_be_positive + // we could default to the base result_converter in case or + // arg_pos==0 since return arg 0 means return result, but I + // think it is better to issue an error instead, cause it can + // lead to confusions + >::type result_converter; + + static PyObject* postcall(PyObject *args, PyObject* result); +}; + +template < + class Base = default_call_policies + > +struct return_self + : return_arg<1,Base> +{}; + + +template +inline PyObject* +return_arg::postcall(PyObject *args, PyObject* result) +{ + // In case of arg_pos == 0 we could simply return Base::postcall, + // but this is redundant + BOOST_STATIC_ASSERT(arg_pos > 0); + + handle<> base_result(Base::postcall(args,result)); + + if(!base_result) + return 0; + + return incref(PyTuple_GetItem(args,arg_pos-1)); +} + +}} // namespace boost::python + +#endif // RETURN_ARG_DWA2003719_HPP diff --git a/index.html b/index.html index dff3b20f..40f1ae14 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ -Automatic redirection failed, please go to +Automatically loading index page... if nothing happens, please go to doc/index.html. - \ No newline at end of file + diff --git a/test/Jamfile b/test/Jamfile index 9af05ce2..1354dc09 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -66,6 +66,7 @@ run ../test/embedding.cpp ../build/boost_python <$(gcc-compilers)><*>$(CYGWIN_PYTHON_DLL_PATH) $(PYTHON_EMBEDDED_LIBRARY) ; +bpl-test return_arg ; bpl-test staticmethod ; bpl-test shared_ptr ; bpl-test polymorphism ; diff --git a/test/return_arg.cpp b/test/return_arg.cpp new file mode 100755 index 00000000..0412d511 --- /dev/null +++ b/test/return_arg.cpp @@ -0,0 +1,68 @@ +// Copyright David Abrahams and Nikolay Mladenov 2003. Permission to +// copy, use, modify, sell and distribute this software is granted +// provided this copyright notice appears in all copies. This software +// is provided "as is" without express or implied warranty, and with +// no claim as to its suitability for any purpose. + +#include +#include +#include +#include + +struct Widget +{ + Widget() + : sensitive_(true) + {} + + bool get_sensitive() const + { + return sensitive_; + } + + void set_sensitive(bool s) + { + this->sensitive_ = s; + } + + private: + bool sensitive_; +}; + +struct Label : Widget +{ + Label() {} + + std::string get_label() const + { + return label_; + } + + void set_label(const std::string &l) + { + label_ = l; + } + + private: + std::string label_; +}; + +void return_arg_f(boost::python::object) {} + +using namespace boost::python; +BOOST_PYTHON_MODULE(return_arg_ext) +{ + class_("Widget") + .def("sensitive", &Widget::get_sensitive) + .def("sensitive", &Widget::set_sensitive, return_self<>()) + ; + + class_ >("Label") + .def("label", &Label::get_label)//,return_arg<0>()) //error(s) + .def("label", &Label::set_label, return_self<>()) + ; + + def("return_arg", return_arg_f, return_arg<1>()); +} + +#include "module_tail.cpp" diff --git a/test/return_arg.py b/test/return_arg.py new file mode 100644 index 00000000..631521c0 --- /dev/null +++ b/test/return_arg.py @@ -0,0 +1,22 @@ +''' +>>> from return_arg_ext import * +>>> l1=Label() +>>> assert l1 is l1.label("bar") +>>> assert l1 is l1.label("bar").sensitive(0) +>>> assert l1.label("foo").sensitive(0) is l1.sensitive(1).label("bar") +>>> assert return_arg is return_arg(return_arg) + +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print "running..." + import sys + sys.exit(run()[0])