2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 16:32:16 +00:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Daniel James
6f77be9a3c Merge from trunk.
[SVN r40260]
2007-10-21 07:28:23 +00:00
Daniel James
daf6d97640 Merge with the offending files removed.
[SVN r39995]
2007-10-13 23:18:35 +00:00
Daniel James
8c70f0540a Merge from trunk.
[SVN r39287]
2007-09-14 22:24:22 +00:00
Daniel James
9630425051 Create a development branch for the hash library.
[SVN r38869]
2007-08-23 19:28:19 +00:00
84 changed files with 2621 additions and 361 deletions

View File

@@ -7,13 +7,14 @@ import modules ;
import python ;
if [ python.configured ] {
project boost/python
: source-location ../src
;
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
lib boost_python
: # sources
numeric.cpp
@@ -45,6 +46,7 @@ lib boost_python
wrapper.cpp
import.cpp
exec.cpp
object/function_doc_signature.cpp
: # requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE
@@ -61,7 +63,12 @@ lib boost_python
# python_for_extensions is a target defined by Boost.Build to
# provide the Python include paths, and on Windows, the Python
# import library, as usage requirements.
<library>/python//python_for_extensions
[ cond [ python.configured ] : <library>/python//python_for_extensions ]
# we prevent building when there is no python available
# as it's not possible anyway, and to cause dependents to
# fail to build
[ unless [ python.configured ] : <build>no ]
: # default build
<link>shared
@@ -69,9 +76,3 @@ lib boost_python
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<link>shared:<define>BOOST_PYTHON_DYNAMIC_LIB
;
}
else
{
ECHO "warning: Python location is not configured" ;
ECHO "warning: the Boost.Python library won't be built" ;
}

View File

@@ -32,7 +32,43 @@
<hr>
<dl class="page-index">
<dt>Current CVS</dt>
<dt>Current SVN</dt>
<dd>
<ul>
<li>Pythonic signatures are now automatically appended to the
docstrings.
<li>Use <a href="v2/docstring_options.html"
><code>docstring_options.hpp</code></a> header
control the content of docstrings.
<li>This new feature increases the size of the modules by about 14%.
If this is not acceptable it can be turned off by defining the macro
BOOST_PYTHON_NO_PY_SIGNATURES. Modules compiled with and without the macro
defined are compatible.
</li>
<li> If BOOST_PYTHON_NO_PY_SIGNATURES is undefined, this version defines the
macro BOOST_PYTHON_SUPPORTS_PY_SIGNATURES. This allows writing code that will compile
with older version of Boost.Python (see <a href="v2/pytype_function.html#examples">here</a>).
</li>
<li>By defining BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE, and at a cost
of another 14% size increase, proper pythonic type is generated for the "self"
parameter of the __init__ methods.
</li>
<li> To support this new feature changes were made to the
<a href="v2/to_python_converter.html"><code>to_python_converter.hpp</code></a>,
<a href="v2/default_call_policies.html"><code>default_call_policies</code></a>,
<a href="v2/ResultConverter.html"><code>ResultConverter</code></a>,
<a href="v2/CallPolicies.html"><code>CallPolicies</code></a> and some others.
Efforts were made not to have interface breaking changes.
</li>
</ul>
</dd>
<dt>12 May 2007 - 1.34.0 release</dt>
<dd>
<ul>

View File

@@ -8,7 +8,7 @@
<meta name="generator" content=
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href=../../../../boost.css>
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - CallPolicies Concept</title>
</head>
@@ -60,6 +60,7 @@
<li><code>postcall</code> - Python argument tuple and result management
after the wrapped object is invoked</li>
<li><code>extract_return_type</code> - metafunction for extracting the return type from a given signature type sequence</li>
</ol>
<h2><a name="composition"></a>CallPolicies Composition</h2>
@@ -132,7 +133,16 @@
reference count must be decremented; if another existing object is
returned, its reference count must be incremented.</td>
</tr>
</table>
<tr>
<td valign="top"><code>P::extract_return_type</code></td>
<td>A model of <a href=
"../../../doc/refmanual/metafunction.html">Metafunction</a>.</td>
<td>An MPL unary <a href=
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a> used extract the return type from a given signature. By default it is derived from mpl::front.</td>
</tr>
</table>
Models of CallPolicies are required to be <a href=
"../../../utility/CopyConstructible.html">CopyConstructible</a>.
<hr>

View File

@@ -1,10 +1,12 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Copyright David Abrahams 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) -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href=../../../../boost.css>
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
<title>Boost.Python - ResultConverter Concept</title>
</head>
<body link="#0000ff" vlink="#800080">
@@ -24,10 +26,12 @@
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
<dl class="page-index">
<dt><a href="#ResultConverter-concept">ResultConverter Concept</a></dt>
<dt><a href="#ResultConverterGenerator-concept">ResultConverterGenerator Concept</a></dt>
</dl>
<dd>
<dl class="page-index">
<dt><a href="#ResultConverter-concept">ResultConverter Concept</a></dt>
<dt><a href="#ResultConverterGenerator-concept">ResultConverterGenerator Concept</a></dt>
</dl>
</dd>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
@@ -79,6 +83,13 @@ denotes an object of type <code><b>R</b></code>.
href="http://www.python.org/doc/current/api/exceptionHandling.html#l2h-71">PyErr_Occurred</a>
should return non-zero.</td>
</tr>
<tr>
<td valign="top"><code>c.get_pytype()</code></td>
<td><code>PyTypeObject const*</code></td>
<td>A pointer to a Python Type object corresponding to result of the conversion,
or <code>0</code>. Used for documentation generation. If <code>0</code> is returned
the generated type in the documentation will be <b>object</b> .</td>
</tr>
</table>
<h3><a name="ResultConverterGenerator-concept"></a>ResultConverterGenerator Concept</h3>

View File

@@ -139,6 +139,41 @@
compares <code>typeid(T).name()</code> instead of using and comparing
the <code>std::type_info</code> objects directly.</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_NO_PY_SIGNATURES</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined for a module no pythonic signatures are generated
for the docstrings of the module functions, and no python type is associated with any
of the converters registered by the module. This also reduces the binary size of the
module by about 14% (gcc compiled).<br>
If defined for the boost_python runtime library, the default for the
<code>docstring_options.enable_py_signatures()</code> is set to <code>false</code>.
</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_SUPPORTS_PY_SIGNATURES</code></td>
<td valign="top" align="center"><i>defined if <code>BOOST_PYTHON_NO_PY_SIGNATURES</code> is undefined</i></td>
<td valign="top">This macro is defined to enable a smooth transition from older Boost.Python versions
which do not support pythonic signatures. For example usage see
<a href="pytype_function.html#examples">here</a>.
</td>
</tr>
<tr>
<td valign="top"><code>BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE</code></td>
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
<td valign="top">If defined the python type of <code>__init__</code> method "self" parameters
is properly generated, otherwise <code><b>object</b></code> is used. It is undefined
by default because it increases the binary size of the module by about 14% (gcc compiled).</td>
</tr>
</table>
<hr>

View File

@@ -82,6 +82,7 @@ namespace boost { namespace python
static PyObject* postcall(PyObject*, PyObject* result);
typedef <a href=
"#default_result_converter-spec">default_result_converter</a> result_converter;
template &lt;class Sig&gt; struct extract_return_type : mpl::front&lt;Sig&gt;{};
};
}}
</pre>
@@ -161,7 +162,7 @@ struct return_value_policy : Base
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
11 June, 2007
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->

View File

@@ -103,6 +103,8 @@ namespace boost { namespace python {
docstring_options(bool show_user_defined, bool show_signatures);
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
~docstring_options();
void
@@ -117,6 +119,18 @@ namespace boost { namespace python {
void
enable_signatures();
void
disable_py_signatures();
void
enable_py_signatures();
void
disable_cpp_signatures();
void
enable_cpp_signatures();
void
disable_all();
@@ -139,7 +153,7 @@ docstring_options(bool show_all=true);
object which controls the appearance of function and
member-function docstrings defined in the code that follows. If
<code>show_all</code> is <code>true</code>, both the
user-defined docstrings and the automatically generated C++
user-defined docstrings and the automatically generated Python and C++
signatures are shown. If <code>show_all</code> is
<code>false</code> the <code>__doc__</code> attributes are
<code>None</code>.</dt>
@@ -154,12 +168,29 @@ docstring_options(bool show_user_defined, bool show_signatures);
member-function docstrings defined in the code that follows.
Iff <code>show_user_defined</code> is <code>true</code>, the
user-defined docstrings are shown. Iff
<code>show_signatures</code> is <code>true</code>, C++
<code>show_signatures</code> is <code>true</code>, Python and C++
signatures are automatically added. If both
<code>show_user_defined</code> and <code>show_signatures</code>
are <code>false</code>, the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<pre>
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
object which controls the appearance of function and
member-function docstrings defined in the code that follows.
Iff <code>show_user_defined</code> is <code>true</code>, the
user-defined docstrings are shown. Iff
<code>show_py_signatures</code> is <code>true</code>, Python
signatures are automatically added. Iff
<code>show_cpp_signatures</code> is <code>true</code>, C++
signatures are automatically added. If all parameters are
<code>false</code>, the <code>__doc__</code> attributes are
<code>None</code>.</dt>
</dl>
<h4><a name="docstring_options-spec-dtors" id=
"docstring_options-spec-dtors"></a>Class
@@ -186,6 +217,10 @@ void disable_user_defined();
void enable_user_defined();
void disable_signatures();
void enable_signatures();
void disable_py_signatures();
void enable_py_signatures();
void disable_cpp_signatures();
void enable_cpp_signatures();
void disable_all();
void enable_all();
</pre>
@@ -196,7 +231,7 @@ void enable_all();
<code>*_user_defined()</code> and <code>*_signatures()</code>
member functions are provided for fine-grained control. The
<code>*_all()</code> member functions are convenient shortcuts
to manipulate both settings simultaneously.</dt>
to manipulate all settings simultaneously.</dt>
</dl>
<h2><a name="examples" id="examples"></a>Examples</h2>
@@ -219,7 +254,7 @@ BOOST_PYTHON_MODULE(demo)
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo.__doc__
foo doc
foo() -&gt; None : foo doc
C++ signature:
foo(void) -&gt; void
</pre>If compiled with
@@ -253,21 +288,33 @@ BOOST_PYTHON_MODULE(demo)
def("foo3", foo3, arg("f"), "foo3 doc");
doc_options.enable_user_defined();
def("foo4", foo4, arg("d"), "foo4 doc");
doc_options.enable_py_signatures();
def("foo5", foo4, arg("d"), "foo5 doc");
doc_options.disable_py_signatures();
doc_options.enable_cpp_signatures();
def("foo6", foo4, arg("d"), "foo6 doc");
}
</pre>Python code:
<pre>
&gt;&gt;&gt; import demo
&gt;&gt;&gt; print demo.foo1.__doc__
foo1 doc
foo1( (int)i) -&gt; int : foo1 doc
C++ signature:
foo1(int i) -&gt; int
&gt;&gt;&gt; print demo.foo2.__doc__
foo2( (int)l) -&gt; int :
C++ signature:
foo2(long l) -&gt; int
&gt;&gt;&gt; print demo.foo3.__doc__
None
&gt;&gt;&gt; print demo.foo4.__doc__
foo4 doc
&gt;&gt;&gt; print demo.foo5.__doc__
foo5( (float)d) -&gt; int : foo5 doc
&gt;&gt;&gt; print demo.foo6.__doc__
foo6 doc
C++ signature:
foo6(double d) -&gt; int
</pre>
<h4>Wrapping from multiple C++ scopes</h4>

View File

@@ -89,7 +89,7 @@ namespace boost { namespace python
template &lt;class T&gt;
class enum_ : public <a href="object.html#object-spec">object</a>
{
enum_(char const* name);
enum_(char const* name, char const* doc = 0);
enum_&lt;T&gt;&amp; value(char const* name, T);
enum_&lt;T&gt;&amp; export_values();
};
@@ -99,7 +99,7 @@ namespace boost { namespace python
<h4><a name="enum_-spec-ctors"></a>Class template <code>enum_</code>
constructors</h4>
<pre>
enum_(char const* name);
enum_(char const* name, char const* doc=0);
</pre>
<dl class="function-semantics">
@@ -131,7 +131,7 @@ inline enum_&lt;T&gt;&amp; value(char const* name, T x);
<dt><b>Effects:</b> adds an instance of the wrapped enumeration
type with value <code>x</code> to the type's dictionary as the
<code>name</code>d attribute</dt>.
<code>name</code>d attribute.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>
@@ -146,7 +146,7 @@ inline enum_&lt;T&gt;&amp; export_values();
<dt><b>Effects:</b> sets attributes in the current <a
href="scope.html#scope-spec"><code>scope</code></a> with the
same names and values as all enumeration values exposed so far
by calling <code>value()</code></dt>.
by calling <code>value()</code>.</dt>
<dt><b>Returns:</b> <code>*this</code></dt>

View File

@@ -0,0 +1,216 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- 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) -->
<html>
<head>
<meta http-equiv="Content-Type" content=
"text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/doobject/function_doc_signature.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%"
summary="header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width=
"277" alt="C++ Boost" src="../../../../boost.png" border=
"0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href=
"../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/object/function_doc_signature.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#function_doc_signature_generator-spec">Class
<code>function_doc_signature_generator</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#function_doc_signature_generator-spec-synopsis">Class
<code>function_doc_signature_generator</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction" id=
"introduction"></a>Introduction</h2>
<p>Boost.Python supports docstrings with automatic
appending of Pythonic and C++ signatures. This feature is implemented
by <code>class function_doc_signature_generator</code>
The class uses all of the overloads, supplied arg names and default values, as well as
the user-defined docstrings, to generate documentation for a given function.</p>
<h2><a name="classes" id="classes"></a>Classes</h2>
<h3><a name="function_doc_signature_generator-spec" id=
"function_doc_signature_generator-spec"></a>Class
<code>function_doc_signature_generator</code></h3>
<p>
The class has only one public function which returns a list of strings documenting the
overloads of a function.
</p>
<h4><a name="function_doc_signature_generator-spec-synopsis" id=
"function_doc_signature_generator-spec-synopsis"></a>Class
<code>function_doc_signature_generator</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace objects {
class function_doc_signature_generator
{
public:
static list function_doc_signatures(function const *f);
};
}}}
</pre>
<h2><a name="examples" id="examples"></a>Examples</h2>
<h4>Docstrings generated with <code>function_doc_signature_generator</code></h4>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/args.hpp&gt;
#include &lt;boost/python/tuple.hpp&gt;
#include &lt;boost/python/class.hpp&gt;
#include &lt;boost/python/overloads.hpp&gt;
#include &lt;boost/python/raw_function.hpp&gt;
using namespace boost::python;
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
{
return make_tuple(x, y, z);
}
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
struct X
{
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
{
return make_tuple(x, y, z);
}
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3)
tuple raw_func(tuple args, dict kw)
{
return make_tuple(args, kw);
}
BOOST_PYTHON_MODULE(args_ext)
{
def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
, "This is f's docstring"
);
def("raw", raw_function(raw_func));
def("f1", f, f_overloads("f1's docstring", args("x", "y", "z")));
class_&lt;X&gt;("X", "This is X's docstring", init&lt;&gt;(args("self")))
.def("f", &amp;X::f
, "This is X.f's docstring"
, args("self","x", "y", "z"))
;
}
</pre>
Python code:
<pre>
&gt;&gt;&gt; import args_ext
&gt;&gt;&gt; help(args_ext)
Help on module args_ext:
NAME
args_ext
FILE
args_ext.pyd
CLASSES
Boost.Python.instance(__builtin__.object)
X
class X(Boost.Python.instance)
| This is X's docstring
|
| Method resolution order:
| X
| Boost.Python.instance
| __builtin__.object
|
| Methods defined here:
|
| __init__(...)
| __init__( (object)self) -> None :
| C++ signature:
| void __init__(struct _object *)
|
| f(...)
| f( (X)self, (int)x, (float)y, (str)z) -> tuple : This is X.f's docstring
| C++ signature:
| class boost::python::tuple f(struct X {lvalue},int,double,char const *)
|
| .................
|
FUNCTIONS
f(...)
f([ (int)x=1 [, (float)y=4.25 [, (str)z='wow']]]) -> tuple : This is f's docstring
C++ signature:
class boost::python::tuple f([ int=1 [,double=4.25 [,char const *='wow']]])
f1(...)
f1([ (int)x [, (float)y [, (str)z]]]) -> tuple : f1's docstring
C++ signature:
class boost::python::tuple f1([ int [,double [,char const *]]])
raw(...)
object raw(tuple args, dict kwds) :
C++ signature:
object raw(tuple args, dict kwds)
</pre>
<p><i>&copy; Copyright <a href="mailto:nickm at sitius dot com">Nikolay Mladenov</a> 2007.</i></p>
</body>
</html>

370
doc/v2/pytype_function.html Normal file
View File

@@ -0,0 +1,370 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- 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) -->
<html>
<head>
<meta http-equiv="Content-Type" content=
"text/html; charset=us-ascii">
<link rel="stylesheet" type="text/css" href="../boost.css">
<title>Boost.Python -
&lt;boost/python/doobject/pytype_function.hpp&gt;</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%"
summary="header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../../index.htm"><img height="86" width=
"277" alt="C++ Boost" src="../../../../boost.png" border=
"0"></a></h3>
</td>
<td valign="top">
<h1 align="center"><a href=
"../index.html">Boost.Python</a></h1>
<h2 align="center">Header
&lt;boost/python/converter/pytype_function.hpp&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dd>
<dl class="page-index">
<dt><a href="#wrap_pytype-spec">Class
<code>wrap_pytype</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#wrap_pytype-spec-synopsis">Class
<code>wrap_pytype</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dd>
<dl class="page-index">
<dt><a href="#registered_pytype-spec">Class
<code>registered_pytype</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#registered_pytype-spec-synopsis">Class
<code>registered_pytype</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dd>
<dl class="page-index">
<dt><a href="#expected_from_python_type-spec">Class
<code>expected_from_python_type</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#expected_from_python_type-spec-synopsis">Class
<code>expected_from_python_type</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dd>
<dl class="page-index">
<dt><a href="#to_python_target_type-spec">Class
<code>to_python_target_type</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#to_python_target_type-spec-synopsis">Class
<code>to_python_target_type</code> synopsis</a></dt>
</dl>
</dd>
</dl>
</dd>
<dt><a href="#examples">Examples</a></dt>
</dl>
<hr>
<h2><a name="introduction" id=
"introduction"></a>Introduction</h2>
<p>To support Pythonic signatures the converters should supply a <code>get_pytype</code> function
returning a pointer to the associated <code>PyTypeObject</code>. See for example
<a href="ResultConverter.html#ResultConverter-concept">ResultConverter</a> or
<a href="to_python_converter.html#to_python_converter-spec">to_python_converter</a>.
The classes in this header file are meant to be used when implmenting <code>get_pytype</code>.
There are also <code>_direct</code> versions of the templates of <code>class T</code> which
should be used with undecorated type parameter, expected to be in the conversion registry when the module loads.
</p>
<h2><a name="classes" id="classes"></a>Classes</h2>
<h3><a name="wrap_pytype-spec" id=
"wrap_pytype-spec"></a>Class
<code>wrap_pytype</code></h3>
<p>
This template generates a static <code>get_pytype</code> member returning the template parameter.
</p>
<h4><a name="wrap_pytype-spec-synopsis" id=
"wrap_pytype-spec-synopsis"></a>Class
<code>wrap_pytype</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace converter{
template &lt; PyTypeObject const *pytype &gt;
class wrap_pytype
{
public:
static PyTypeObject const *get_pytype(){return pytype; }
};
}}}
</pre>
<h3><a name="registered_pytype-spec" id=
"registered_pytype-spec"></a>Class
<code>registered_pytype</code></h3>
<p>
This template should be used with template parameters which are (possibly decorated)
types exported to python using <a href="class.html"><code>class_</code></a>.
The generated a static <code>get_pytype</code> member
returns the corresponding python type.
</p>
<h4><a name="registered_pytype-spec-synopsis" id=
"registered_pytype-spec-synopsis"></a>Class
<code>registered_pytype</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace converter{
template &lt; class T &gt;
class registered_pytype
{
public:
static PyTypeObject const *get_pytype();
};
}}}
</pre>
<h3><a name="expected_from_python_type-spec" id=
"expected_from_python_type-spec"></a>Class
<code>expected_from_python_type</code></h3>
<p>
This template generates a static <code>get_pytype</code> member which inspects the registered
<code>from_python</code> converters for the type <code>T</code> and returns a matching python type.
</p>
<h4><a name="expected_from_python_type-spec-synopsis" id=
"expected_from_python_type-spec-synopsis"></a>Class
<code>expected_from_python_type</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace converter{
template &lt; class T &gt;
class expected_from_python_type
{
public:
static PyTypeObject const *get_pytype();
};
}}}
</pre>
<h3><a name="to_python_target_type-spec" id=
"to_python_target_type-spec"></a>Class
<code>to_python_target_type</code></h3>
<p>
This template generates a static <code>get_pytype</code> member returning the
python type to which T can be converted.
</p>
<h4><a name="to_python_target_type-spec-synopsis" id=
"to_python_target_type-spec-synopsis"></a>Class
<code>to_python_target_type</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace converter{
template &lt; class T &gt;
class to_python_target_type
{
public:
static PyTypeObject const *get_pytype();
};
}}}
</pre>
<h2><a name="examples" id="examples"></a>Examples</h2>
This example presumes that someone has implemented the standard <a href=
"http://www.python.org/doc/2.2/ext/dnt-basics.html">noddy example
module</a> from the Python documentation, and placed the corresponding
declarations in <code>"noddy.h"</code>. Because
<code>noddy_NoddyObject</code> is the ultimate trivial extension type,
the example is a bit contrived: it wraps a function for which all
information is contained in the <i>type</i> of its return value.
<h3>C++ module definition</h3>
<pre>
#include &lt;boost/python/reference.hpp&gt;
#include &lt;boost/python/module.hpp&gt;
#include "noddy.h"
struct tag {};
tag make_tag() { return tag(); }
using namespace boost::python;
struct tag_to_noddy
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
: wrap_pytype<&amp;noddy_NoddyType> //inherits get_pytype from wrap_pytype
#endif
{
static PyObject* convert(tag const&amp; x)
{
return PyObject_New(noddy_NoddyObject, &amp;noddy_NoddyType);
}
};
BOOST_PYTHON_MODULE(to_python_converter)
{
def("make_tag", make_tag);
to_python_converter&lt;tag, tag_to_noddy
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
, true
#endif
&gt;(); //"true" because tag_to_noddy has member get_pytype
}
</pre>
<p>The following example registers to and from python converters using the templates
<code>expected_from_python_type</code> and <code>to_pyhton_target_type</code>.
</p>
<pre>
#include &lt;boost/python/module.hpp&gt;
#include &lt;boost/python/def.hpp&gt;
#include &lt;boost/python/extract.hpp&gt;
#include &lt;boost/python/to_python_converter.hpp&gt;
#include &lt;boost/python/class.hpp&gt;
using namespace boost::python;
struct A
{
};
struct B
{
A a;
B(const A& a_):a(a_){}
};
// Converter from A to python int
struct BToPython
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
: converter::to_python_target_type&lt;A&gt; //inherits get_pytype
#endif
{
static PyObject* convert(const B& b)
{
return incref(object(b.a).ptr());
}
};
// Conversion from python int to A
struct BFromPython
{
BFromPython()
{
boost::python::converter::registry::push_back
( &amp;convertible
, &amp;construct
, type_id&lt; B &gt;()
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
, &amp;converter::expected_from_python_type&lt;A&gt;::get_pytype//convertible to A can be converted to B
#endif
);
}
static void* convertible(PyObject* obj_ptr)
{
extract&lt;const A&&gt; ex(obj_ptr);
if (!ex.check()) return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
converter::rvalue_from_python_stage1_data* data)
{
void* storage = (
(converter::rvalue_from_python_storage&lt; B &gt;*)data)-&gt; storage.bytes;
extract&lt;const A&&gt; ex(obj_ptr);
new (storage) B(ex());
data->convertible = storage;
}
};
B func(const B& b) { return b ; }
BOOST_PYTHON_MODULE(pytype_function_ext)
{
to_python_converter&lt; B , BToPython
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
,true
#endif
&gt;(); //has get_pytype
BFromPython();
class_&lt;A&gt;("A") ;
def("func", &amp;func);
}
&gt;&gt;&gt; from pytype_function_ext import *
&gt;&gt;&gt; print func.__doc__
func( (A)arg1) -> A :
C++ signature:
struct B func(struct B)
</pre>
<p><i>&copy; Copyright <a href="mailto:nickm at sitius dot com">Nikolay Mladenov</a> 2007.</i></p>
</body>
</html>

View File

@@ -609,6 +609,66 @@
</dl>
</dd>
<dd>
<a name="function_documentation"></a>
<h3>Function documentation</h3>
<dl class="index">
<dt><a href=
"function_doc_signature.html">function_doc_signature.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href=
"function_doc_signature.html#classes">Classes</a></dt>
<dd>
<dl class="index">
<dt><a href=
"function_doc_signature.html#function_doc_signature_generator-spec">function_doc_signature_generator</a></dt>
</dl>
</dd>
</dl>
</dd>
</dl>
<dl class="index">
<dt><a href=
"pytype_function.html">pytype_function.hpp</a></dt>
<dd>
<dl class="index">
<dt><a href=
"pytype_function.html#classes">Classes</a></dt>
<dd>
<dl class="index">
<dt><a href=
"pytype_function.html#wrap_pytype-spec">wrap_pytype</a></dt>
</dl>
<dl class="index">
<dt><a href=
"pytype_function.html#expected_from_python_type-spec">expected_from_python_type</a></dt>
</dl>
<dl class="index">
<dt><a href=
"pytype_function.html#to_python_target_type-spec">to_python_target_type</a></dt>
</dl>
<dl class="index">
<dt><a href=
"pytype_function.html#registered_pytype-spec">registered_pytype</a></dt>
</dl>
</dd>
</dl>
</dd>
</dl>
</dd>
<dd>
<a name="models_of_call_policies"></a>

View File

@@ -125,6 +125,8 @@ namespace boost { namespace python
{
static PyObject* postcall(PyObject*, PyObject* result);
struct result_converter{ template &lt;class T&gt; struct apply; };
template &lt;class Sig&gt; struct extract_return_type : mpl::at_c&lt;Sig, arg_pos&gt;{};
};
}}
</pre>

View File

@@ -108,6 +108,23 @@
<td>A class type whose static member function <code>convert</code>
does the real work of the conversion.</td>
</tr>
<tr>
<td><code>bool has_get_pytype = false</code></td>
<td>
<code>PyTypeObject const * p = Conversion::get_pytype() </code>.</td>
<td><b>Optional member</b> - if <code>Conversion</code> has <code>get_pytype</code> member supply
<code>true</code> for this parameters.
If present <code>get_pytype</code> is used to document the return type
of functions using this conversion. The <code>get_pytype</code> may be implemented
using the classes and functions
from <a href="pytype_function.html"><code>pytype_function.hpp</code></a>
<b>NOTE :</b> For backward compatibility this parameter may be passed after
checking if <code>BOOST_PYTHON_SUPPORTS_PY_SIGNATURES</code> is defined (see
<a href="pytype_function.html#examples">here</a>).
</td>
</tr>
</table>
<h4><a name="to_python_converter-spec-synopsis"></a>Class template
@@ -115,7 +132,7 @@
<pre>
namespace boost { namespace python
{
template &lt;class T, class Conversion&gt;
template &lt;class T, class Conversion, bool convertion_has_get_pytype_member=false&gt;
struct to_python_converter
{
to_python_converter();
@@ -160,12 +177,16 @@ struct tag_to_noddy
{
return PyObject_New(noddy_NoddyObject, &amp;noddy_NoddyType);
}
static PyTypeObject const* get_pytype()
{
return &amp;noddy_NoddyType;
}
};
BOOST_PYTHON_MODULE(to_python_converter)
{
def("make_tag", make_tag);
to_python_converter&lt;tag, tag_to_noddy&gt;();
to_python_converter&lt;tag, tag_to_noddy, true&gt;(); //"true" because tag_to_noddy has member get_pytype
}
</pre>
@@ -195,7 +216,7 @@ BOOST_PYTHON_MODULE(to_python_converter)
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
13 November, 2002
11 June, 2007
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>

View File

@@ -18,6 +18,7 @@ namespace { // Avoid cluttering the global namespace.
return boost::python::incref(
boost::python::make_tuple(p.first, p.second).ptr());
}
static PyTypeObject const *get_pytype () {return &PyTuple_Type; }
};
// Helper for convenience.
@@ -28,7 +29,9 @@ namespace { // Avoid cluttering the global namespace.
{
boost::python::to_python_converter<
std::pair<T1, T2>,
std_pair_to_tuple<T1, T2> >();
std_pair_to_tuple<T1, T2>,
true //std_pair_to_tuple has get_pytype
>();
}
};

View File

@@ -39,6 +39,9 @@ struct as_to_python_function
// but c'est la vie.
return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x)));
}
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
static PyTypeObject const * get_pytype() { return ToPython::get_pytype(); }
#endif
};
}}} // namespace boost::python::converter

View File

@@ -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<T&> \
: 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<T const&> \
: 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<unsigned long>(x) > static_cast<unsigned long>( \
(std::numeric_limits<long>::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<ssize_t>(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<ssize_t>(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<ssize_t>(x.size())))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(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<float>, ::PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::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<float>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type)
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type)
# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE
# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE

View File

@@ -18,6 +18,9 @@ struct pyobject_traits<PyObject>
// 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
};
//

View File

@@ -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 <class Object, PyTypeObject* pytype>
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

View File

@@ -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 <boost/python/detail/prefix.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/detail/unwind_type.hpp>
namespace boost { namespace python {
namespace converter
{
template <PyTypeObject const* python_type>
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 <class U>
static result_type execute(U* ){
return python::type_id<U>();
}
};
template <class T>
inline python::type_info unwind_type_id_(boost::type<T>* = 0, mpl::false_ * =0)
{
return boost::python::detail::unwind_type<unwind_type_id_helper, T> ();
}
inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0)
{
return type_id<void>();
}
template <class T>
inline python::type_info unwind_type_id(boost::type<T>* p= 0)
{
return unwind_type_id_(p, (mpl::bool_<boost::is_void<T>::value >*)0 );
}
}
template <class T>
struct expected_pytype_for_arg
{
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
);
return r ? r->expected_from_python_type(): 0;
}
};
template <class T>
struct registered_pytype
{
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::is_void<T>::value >*)0 )
);
return r ? r->m_class_object: 0;
}
};
template <class T>
struct registered_pytype_direct
{
static PyTypeObject const* get_pytype()
{
return registered<T>::converters.m_class_object;
}
};
template <class T>
struct expected_from_python_type : expected_pytype_for_arg<T>{};
template <class T>
struct expected_from_python_type_direct
{
static PyTypeObject const* get_pytype()
{
return registered<T>::converters.expected_from_python_type();
}
};
template <class T>
struct to_python_target_type
{
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
);
return r ? r->to_python_target_type(): 0;
}
};
template <class T>
struct to_python_target_type_direct
{
static PyTypeObject const *get_pytype()
{
return registered<T>::converters.to_python_target_type();
}
};
#endif
}}} // namespace boost::python
#endif // WRAP_PYTYPE_NM20070606_HPP

View File

@@ -27,6 +27,7 @@ struct rvalue_from_python_chain
{
convertible_function convertible;
constructor_function construct;
PyTypeObject const* (*expected_pytype)();
rvalue_from_python_chain* next;
};
@@ -43,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;
@@ -57,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.
@@ -77,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)
{}

View File

@@ -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
);
}

View File

@@ -10,6 +10,9 @@
# include <boost/python/converter/from_python.hpp>
# include <boost/python/converter/rvalue_from_python_data.hpp>
# include <boost/python/converter/registered.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/shared_ptr.hpp>
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<shared_ptr<T> >());
converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &converter::expected_from_python_type_direct<T>::get_pytype
#endif
);
}
private:

View File

@@ -13,6 +13,7 @@
# include <boost/type_traits/is_pointer.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/mpl/or.hpp>
# include <boost/mpl/front.hpp>
namespace boost { namespace python {
@@ -49,6 +50,12 @@ struct default_call_policies
typedef default_result_converter result_converter;
typedef PyObject* argument_package;
template <class Sig>
struct extract_return_type : mpl::front<Sig>
{
};
};
struct default_result_converter

View File

@@ -11,12 +11,15 @@
# include <boost/python/type_id.hpp>
# include <boost/python/handle.hpp>
# include <boost/detail/indirect_traits.hpp>
# include <boost/python/detail/invoke.hpp>
# include <boost/python/detail/signature.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/arg_from_python.hpp>
# include <boost/python/converter/context_result_converter.hpp>
# include <boost/python/converter/builtin_converters.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/cat.hpp>
@@ -89,6 +92,27 @@ inline ResultConverter create_result_converter(
{
return ResultConverter();
}
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
template <class ResultConverter>
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 <void_result_to_python >
{
static PyTypeObject const *get_pytype()
{
return 0;
}
};
#endif
template <unsigned> struct caller_arity;
@@ -203,11 +227,26 @@ struct caller_arity<N>
static unsigned min_arity() { return N; }
static signature_element const* signature()
static py_func_sig_info signature()
{
return detail::signature<Sig>::elements();
const signature_element * sig = detail::signature<Sig>::elements();
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype;
typedef typename select_result_converter<Policies, rtype>::type result_converter;
static const signature_element ret = {
(boost::is_void<rtype>::value ? "void" : type_id<rtype>().name())
, &detail::converter_target_type<result_converter>::get_pytype
, boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value
};
py_func_sig_info res = {sig, &ret };
#else
py_func_sig_info res = {sig, sig };
#endif
return res;
}
private:
compressed_pair<F,Policies> m_data;
};

View File

@@ -134,4 +134,8 @@
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
#define BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // enables smooth transition
#endif
#endif // CONFIG_DWA052200_H_

View File

@@ -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

View File

@@ -168,7 +168,7 @@ namespace detail
char const* doc)
{
// define the NTH stub function of stubs
define_stub_function<N>::define(name, stubs, kw, policies, name_space, 0);
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
if (kw.second > kw.first)
--kw.second;

View File

@@ -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)

View File

@@ -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<BOOST_DEDUCED_TYPENAME Holder::value_type>::register_();
#endif
return detail::make_keyword_range_function(
objects::make_holder<Arity::value>
::template apply<Holder,ArgList>::execute

View File

@@ -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 <boost/python/converter/registered.hpp>
namespace boost {namespace python {namespace detail{
template <class T> struct python_class : PyObject
{
typedef python_class<T> 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<this_type>(), &converter::registered_pytype_direct<T>::get_pytype);
}
};
}}} //namespace boost :: python :: detail
#endif //BOOST_PYTHON_OBJECT_PYTHON_TYPE_H

View File

@@ -12,6 +12,7 @@
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/python/converter/pytype_function.hpp>
# include <boost/preprocessor/iterate.hpp>
# include <boost/preprocessor/iteration/local.hpp>
@@ -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 <unsigned> struct signature_arity;
# define BOOST_PP_ITERATION_PARAMS_1 \
@@ -68,15 +76,25 @@ struct signature_arity<N>
{
static signature_element const result[N+2] = {
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# define BOOST_PP_LOCAL_MACRO(i) \
{ \
type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \
, indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \
},
{ \
type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \
, &converter::expected_pytype_for_arg<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::get_pytype \
, indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \
},
#else
# define BOOST_PP_LOCAL_MACRO(i) \
{ \
type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \
, 0 \
, indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \
},
#endif
# define BOOST_PP_LOCAL_LIMITS (0, N)
# include BOOST_PP_LOCAL_ITERATE()
{0,0}
{0,0,0}
};
return result;
}

View File

@@ -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 <boost/python/detail/cv_category.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/type_traits/object_traits.hpp>
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 <class Generator, class U>
inline typename Generator::result_type
unwind_type(U const& p, Generator* = 0);
// forward declaration, required (at least) by Tru64 cxx V6.5-042
template <class Generator, class U>
inline typename Generator::result_type
unwind_type(boost::type<U>*p = 0, Generator* = 0);
#endif
template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U* p, cv_unqualified, Generator* = 0)
{
return Generator::execute(p);
}
template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U const* p, const_, Generator* = 0)
{
return unwind_type(const_cast<U*>(p), (Generator*)0);
}
template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U volatile* p, volatile_, Generator* = 0)
{
return unwind_type(const_cast<U*>(p), (Generator*)0);
}
template <class Generator, class U>
inline typename Generator::result_type
unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0)
{
return unwind_type(const_cast<U*>(p), (Generator*)0);
}
template <class Generator, class U>
inline typename Generator::result_type
unwind_ptr_type(U* p, Generator* = 0)
{
typedef typename cv_category<U>::type tag;
return unwind_type_cv<Generator>(p, tag());
}
template <bool is_ptr>
struct unwind_helper
{
template <class Generator, class U>
static typename Generator::result_type
execute(U p, Generator* = 0)
{
return unwind_ptr_type(p, (Generator*)0);
}
};
template <>
struct unwind_helper<false>
{
template <class Generator, class U>
static typename Generator::result_type
execute(U& p, Generator* = 0)
{
return unwind_ptr_type(&p, (Generator*)0);
}
};
template <class Generator, class U>
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<is_pointer<U>::value>::execute(p, (Generator*)0);
}
enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 };
template <int indirection> struct unwind_helper2;
template <>
struct unwind_helper2<direct_>
{
template <class Generator, class U>
static typename Generator::result_type
execute(U(*)(), Generator* = 0)
{
return unwind_ptr_type((U*)0, (Generator*)0);
}
};
template <>
struct unwind_helper2<pointer_>
{
template <class Generator, class U>
static typename Generator::result_type
execute(U*(*)(), Generator* = 0)
{
return unwind_ptr_type((U*)0, (Generator*)0);
}
};
template <>
struct unwind_helper2<reference_>
{
template <class Generator, class U>
static typename Generator::result_type
execute(U&(*)(), Generator* = 0)
{
return unwind_ptr_type((U*)0, (Generator*)0);
}
};
template <>
struct unwind_helper2<reference_to_pointer_>
{
template <class Generator, class U>
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<my_generator,T>();
//
// Doesn't work if T is an array type; we could handle that case, but
// why bother?
template <class Generator, class U>
inline typename Generator::result_type
#ifndef _MSC_VER
unwind_type(boost::type<U>*p, Generator*)
#else
unwind_type(boost::type<U>*p =0, Generator* =0)
#endif
{
BOOST_STATIC_CONSTANT(int, indirection
= (boost::is_pointer<U>::value ? pointer_ : 0)
+ (indirect_traits::is_reference_to_pointer<U>::value
? reference_to_pointer_
: boost::is_reference<U>::value
? reference_
: 0));
return unwind_helper2<indirection>::execute((U(*)())0,(Generator*)0);
}
}}} // namespace boost::python::detail
#endif // UNWIND_TYPE_DWA200222_HPP

View File

@@ -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

View File

@@ -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_<T>& value(char const* name, T);
@@ -34,13 +34,15 @@ struct enum_ : public objects::enum_base
};
template <class T>
inline enum_<T>::enum_(char const* name)
inline enum_<T>::enum_(char const* name, char const* doc )
: base(
name
, &enum_<T>::to_python
, &enum_<T>::convertible_from_python
, &enum_<T>::construct
, type_id<T>())
, type_id<T>()
, doc
)
{
}

View File

@@ -9,6 +9,9 @@
# include <boost/type.hpp>
# include <boost/python/converter/implicit.hpp>
# include <boost/python/converter/registry.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/python/type_id.hpp>
namespace boost { namespace python {
@@ -21,7 +24,11 @@ void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0)
converter::registry::push_back(
&functions::convertible
, &functions::construct
, type_id<Target>());
, type_id<Target>()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &converter::expected_from_python_type_direct<Source>::get_pytype
#endif
);
}
}} // namespace boost::python

View File

@@ -245,7 +245,7 @@ class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
: 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<init<BOOST_PYTHON_OVERLOAD_ARGS> >
: 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;

View File

@@ -6,6 +6,9 @@
# define LVALUE_FROM_PYTYPE_DWA2002130_HPP
# include <boost/python/detail/prefix.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/python/type_id.hpp>
# include <boost/python/converter/registry.hpp>
@@ -81,12 +84,17 @@ struct extract_identity
// Extractor's static execute function from Python objects whose type
// object is python_type.
template <class Extractor, PyTypeObject const* python_type>
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

View File

@@ -104,6 +104,14 @@ namespace detail
// If the BasePolicy_ supplied a result converter it would be
// ignored; issue an error if it's not the default.
#if defined _MSC_VER && _MSC_VER < 1300
typedef is_same<
typename BasePolicy_::result_converter
, default_result_converter
> 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
@@ -112,7 +120,7 @@ namespace detail
, 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<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
};

View File

@@ -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<T>(), python::type_id<back_reference<T const &> >());
objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
}
#endif
template <class T2>
inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*)
{
@@ -247,6 +255,10 @@ struct class_metadata
, make_ptr_instance<T2, pointer_holder<held_type, T2> >
>()
);
#ifndef BOOST_PYTHON_NO_PY_SYGNATURES
// explicit qualification of type_id makes msvc6 happy
objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
#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<T2, make_instance<T2, holder> >());
#ifndef BOOST_PYTHON_NO_PY_SYGNATURES
// explicit qualification of type_id makes msvc6 happy
objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
#endif
}
//

View File

@@ -6,6 +6,9 @@
# define CLASS_WRAPPER_DWA20011221_HPP
# include <boost/python/to_python_converter.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/ref.hpp>
namespace boost { namespace python { namespace objects {
@@ -19,22 +22,28 @@ namespace boost { namespace python { namespace objects {
template <class Src, class MakeInstance>
struct class_cref_wrapper
: to_python_converter<Src,class_cref_wrapper<Src,MakeInstance> >
: to_python_converter<Src,class_cref_wrapper<Src,MakeInstance> ,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<Src>::get_pytype(); }
#endif
};
template <class Src, class MakeInstance>
struct class_value_wrapper
: to_python_converter<Src,class_value_wrapper<Src,MakeInstance> >
: to_python_converter<Src,class_value_wrapper<Src,MakeInstance> ,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

View File

@@ -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();

View File

@@ -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;
};
//

View File

@@ -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 <boost/python/object/function.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/str.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/detail/signature.hpp>
#include <vector>
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<function const*> flatten(function const *f);
static std::vector<function const*> split_seq_overloads( const std::vector<function const *> &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

View File

@@ -11,6 +11,10 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/object/instance.hpp>
# include <boost/python/converter/registry.hpp>
#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE)
# include <boost/python/detail/python_type.hpp>
#endif
# include <boost/python/object/forward.hpp>
# include <boost/python/detail/preprocessor.hpp>
@@ -74,7 +78,11 @@ struct make_holder<N>
# 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<BOOST_DEDUCED_TYPENAME Holder::value_type> *p
#else
PyObject *p
#endif
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a))
{
typedef instance<Holder> instance_t;

View File

@@ -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<T>::converters.get_class_object();
}
#endif
private:
template <class U>
static inline PyTypeObject* get_class_object_impl(U const volatile* p)

View File

@@ -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 <class Caller>
@@ -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<Sig>::value - 1;
}
virtual python::detail::signature_element const* signature() const
virtual python::detail::py_func_sig_info signature() const
{
return python::detail::signature<Sig>::elements();
python::detail::signature_element const* sig = python::detail::signature<Sig>::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<Sig>::elements();
python::detail::signature_element const* sig = python::detail::signature<Sig>::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:

View File

@@ -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
};
}

View File

@@ -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<Pointee>(), &get_pytype);
converter::registry::insert(&wrap, type_id<Pointee*>(), &get_pytype);
#else
converter::registry::insert(&extract, type_id<Pointee>());
converter::registry::insert(&wrap, type_id<Pointee*>());
#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 <class Pointee>

View File

@@ -8,10 +8,15 @@
# include <boost/python/detail/none.hpp>
# include <boost/python/detail/value_arg.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/type_traits/add_reference.hpp>
# include <boost/type_traits/add_const.hpp>
# include <boost/mpl/int.hpp>
# include <boost/mpl/at.hpp>
# include <boost/static_assert.hpp>
# include <boost/python/refcount.hpp>
@@ -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<T>::get_pytype() ; }
#endif
};
};
};
@@ -82,6 +90,12 @@ struct return_arg : Base
Py_DECREF(result);
return incref( detail::get(mpl::int_<arg_pos-1>(),args) );
}
template <class Sig>
struct extract_return_type : mpl::at_c<Sig, arg_pos>
{
};
};
template <

View File

@@ -9,13 +9,67 @@
# include <boost/python/converter/registry.hpp>
# include <boost/python/converter/as_to_python_function.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/python/type_id.hpp>
namespace boost { namespace python {
template <class T, class Conversion>
struct to_python_converter
#if 0 //get_pytype member detection
namespace detail
{
typedef char yes_type;
typedef struct {char a[2]; } no_type;
template<PyTypeObject const * (*f)()> struct test_get_pytype1 { };
template<PyTypeObject * (*f)()> struct test_get_pytype2 { };
template<class T> yes_type tester(test_get_pytype1<&T::get_pytype>*);
template<class T> yes_type tester(test_get_pytype2<&T::get_pytype>*);
template<class T> no_type tester(...);
template<class T>
struct test_get_pytype_base
{
BOOST_STATIC_CONSTANT(bool, value= (sizeof(detail::tester<T>(0)) == sizeof(yes_type)));
};
template<class T>
struct test_get_pytype : boost::mpl::bool_<test_get_pytype_base<T>::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<Conversion> HasGetPytype;
#else
typedef boost::mpl::bool_<has_get_pytype> 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 <class T, class Conversion>
to_python_converter<T,Conversion>::to_python_converter()
template <class T, class Conversion ,bool has_get_pytype>
to_python_converter<T,Conversion, has_get_pytype>::to_python_converter()
{
typedef converter::as_to_python_function<
T, Conversion
> normalized;
converter::registry::insert(
&normalized::convert
, type_id<T>());
, type_id<T>()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &get_pytype_impl
#endif
);
}
}} // namespace boost::python
#endif // TO_PYTHON_CONVERTER_DWA200221_HPP

View File

@@ -12,6 +12,10 @@
# include <boost/python/detail/none.hpp>
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
# include <boost/python/converter/pytype_function.hpp>
#endif
# include <boost/python/refcount.hpp>
# include <boost/type_traits/is_pointer.hpp>
@@ -36,7 +40,13 @@ struct to_python_indirect
{
return this->execute(const_cast<U&>(ref), is_pointer<U>());
}
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
inline PyTypeObject const*
get_pytype()const
{
return converter::registered_pytype<T>::get_pytype();
}
#endif
private:
template <class U>
inline PyObject* execute(U* ptr, mpl::true_) const

View File

@@ -9,12 +9,12 @@
# include <boost/python/refcount.hpp>
# include <boost/python/tag.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/converter/builtin_converters.hpp>
# include <boost/python/converter/object_manager.hpp>
# include <boost/python/converter/object_manager.hpp>
# include <boost/python/converter/shared_ptr_to_python.hpp>
# include <boost/python/detail/value_is_shared_ptr.hpp>
@@ -24,17 +24,57 @@
# include <boost/mpl/if.hpp>
# include <boost/mpl/or.hpp>
# include <boost/type_traits/is_const.hpp>
namespace boost { namespace python {
namespace detail
{
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
template <bool is_const_ref>
struct object_manager_get_pytype
{
template <class U>
static PyTypeObject const* get( U& (*p)() =0)
{
return converter::object_manager_traits<U>::get_pytype();
}
};
template <>
struct object_manager_get_pytype<true>
{
template <class U>
static PyTypeObject const* get( U const& (*p)() =0)
{
return converter::object_manager_traits<U>::get_pytype();
}
};
#endif
template <class T>
struct object_manager_to_python_value
{
typedef typename value_arg<T>::type argument_type;
PyObject* operator()(argument_type) const;
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
typedef boost::mpl::bool_<is_handle<T>::value> is_t_handle;
typedef boost::detail::indirect_traits::is_reference_to_const<T> 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<T>::get_pytype();}
inline static PyTypeObject const* get_pytype_aux(mpl::false_* )
{
return object_manager_get_pytype<is_t_const::value>::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<T>::type argument_type;
PyObject* operator()(argument_type) const;
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
PyTypeObject const* get_pytype() const {return converter::registered<T>::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<T>::type argument_type;
PyObject* operator()(argument_type) const;
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
PyTypeObject const* get_pytype() const {return get_pytype((boost::type<argument_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 <class U>
PyTypeObject const* get_pytype(boost::type<shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
template <class U>
PyTypeObject const* get_pytype(boost::type<const shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
#endif
};
}

View File

@@ -16,6 +16,7 @@
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/converter/shared_ptr_deleter.hpp>
#include <boost/python/converter/pytype_function.hpp>
#include <boost/cast.hpp>
#include <string>
@@ -56,6 +57,7 @@ namespace
&slot_rvalue_from_python<T,SlotPolicy>::convertible
, &slot_rvalue_from_python<T,SlotPolicy>::construct
, type_id<T>()
, &SlotPolicy::get_pytype
);
}
@@ -100,6 +102,7 @@ namespace
return (PyInt_Check(obj) || PyLong_Check(obj))
? &number_methods->nb_int : 0;
}
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
};
template <class T>
@@ -135,6 +138,7 @@ namespace
return (PyInt_Check(obj) || PyLong_Check(obj))
? &py_object_identity : 0;
}
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
};
template <class T>
@@ -173,6 +177,7 @@ namespace
else
return 0;
}
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
};
struct long_long_rvalue_from_python : long_long_rvalue_from_python_base
@@ -228,6 +233,15 @@ namespace
{
return PyObject_IsTrue(intermediate);
}
static PyTypeObject const* get_pytype()
{
#if PY_VERSION_HEX >= 0x02030000
return &PyBool_Type;
#else
return &PyInt_Type;
#endif
}
};
// A SlotPolicy for extracting floating types from Python objects.
@@ -259,6 +273,7 @@ namespace
return PyFloat_AS_DOUBLE(intermediate);
}
}
static PyTypeObject const* get_pytype() { return &PyFloat_Type;}
};
// A SlotPolicy for extracting C++ strings from Python objects.
@@ -276,6 +291,7 @@ namespace
{
return std::string(PyString_AsString(intermediate),PyString_Size(intermediate));
}
static PyTypeObject const* get_pytype() { return &PyString_Type;}
};
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
@@ -316,6 +332,7 @@ namespace
}
return result;
}
static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
};
#endif
@@ -346,6 +363,7 @@ namespace
return PyFloat_AS_DOUBLE(intermediate);
}
}
static PyTypeObject const* get_pytype() { return &PyComplex_Type;}
};
}
@@ -411,7 +429,7 @@ void initialize_builtin_converters()
slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>();
// Add an lvalue converter for char which gets us char const*
registry::insert(convert_to_cstring,type_id<char>());
registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
// Register by-value converters to std::string, std::wstring
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)

View File

@@ -20,6 +20,35 @@
#endif
namespace boost { namespace python { namespace converter {
BOOST_PYTHON_DECL PyTypeObject const* registration::expected_from_python_type() const
{
if (this->m_class_object != 0)
return this->m_class_object;
std::set<PyTypeObject const*> pool;
for(rvalue_from_python_chain* r = rvalue_chain; r ; r=r->next)
if(r->expected_pytype)
pool.insert(r->expected_pytype());
//for now I skip the search for common base
if (pool.size()==1)
return *pool.begin();
return 0;
}
BOOST_PYTHON_DECL PyTypeObject const* registration::to_python_target_type() const
{
if (this->m_class_object != 0)
return this->m_class_object;
if (this->m_to_python_target_type != 0)
return this->m_to_python_target_type();
return 0;
}
BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const
{
@@ -168,15 +197,15 @@ namespace // <unnamed>
namespace registry
{
void insert(to_python_function_t f, type_info source_t)
void insert(to_python_function_t f, type_info source_t, PyTypeObject const* (*to_python_target_type)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "inserting to_python " << source_t << "\n";
# endif
to_python_function_t& slot = get(source_t)->m_to_python;
entry* slot = get(source_t);
assert(slot == 0); // we have a problem otherwise
if (slot != 0)
assert(slot->m_to_python == 0); // we have a problem otherwise
if (slot->m_to_python != 0)
{
std::string msg = (
std::string("to-Python converter for ")
@@ -189,11 +218,12 @@ namespace registry
throw_error_already_set();
}
}
slot = f;
slot->m_to_python = f;
slot->m_to_python_target_type = to_python_target_type;
}
// Insert an lvalue from_python converter
void insert(convertible_function convert, type_info key)
void insert(convertible_function convert, type_info key, PyTypeObject const* (*exp_pytype)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "inserting lvalue from_python " << key << "\n";
@@ -204,13 +234,14 @@ namespace registry
registration->next = found->lvalue_chain;
found->lvalue_chain = registration;
insert(convert, 0, key);
insert(convert, 0, key,exp_pytype);
}
// Insert an rvalue from_python converter
void insert(void* (*convertible)(PyObject*)
, constructor_function construct
, type_info key)
, type_info key
, PyTypeObject const* (*exp_pytype)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "inserting rvalue from_python " << key << "\n";
@@ -219,6 +250,7 @@ namespace registry
rvalue_from_python_chain *registration = new rvalue_from_python_chain;
registration->convertible = convertible;
registration->construct = construct;
registration->expected_pytype = exp_pytype;
registration->next = found->rvalue_chain;
found->rvalue_chain = registration;
}
@@ -226,7 +258,8 @@ namespace registry
// Insert an rvalue from_python converter
void push_back(void* (*convertible)(PyObject*)
, constructor_function construct
, type_info key)
, type_info key
, PyTypeObject const* (*exp_pytype)())
{
# ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "push_back rvalue from_python " << key << "\n";
@@ -238,6 +271,7 @@ namespace registry
rvalue_from_python_chain *registration = new rvalue_from_python_chain;
registration->convertible = convertible;
registration->construct = construct;
registration->expected_pytype = exp_pytype;
registration->next = 0;
*found = registration;
}

View File

@@ -171,4 +171,14 @@ list dict_base::values() const
}
}
static struct register_dict_pytype_ptr
{
register_dict_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::dict>())
).m_class_object = &PyDict_Type;
}
}register_dict_pytype_ptr_;
}}} // namespace boost::python

View File

@@ -137,4 +137,14 @@ long list_base::count(object_cref value) const
return result;
}
static struct register_list_pytype_ptr
{
register_list_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::list>())
).m_class_object = &PyList_Type;
}
}register_list_pytype_ptr_;
}}} // namespace boost::python

View File

@@ -121,7 +121,7 @@ object module_prefix();
namespace
{
object new_enum_type(char const* name)
object new_enum_type(char const* name, char const *doc)
{
if (enum_type_object.tp_dict == 0)
{
@@ -143,6 +143,8 @@ namespace
object module_name = module_prefix();
if (module_name)
d["__module__"] = module_name;
if (doc)
d["__doc__"] = doc;
object result = (object(metatype))(name, make_tuple(base), d);
@@ -158,8 +160,9 @@ enum_base::enum_base(
, converter::convertible_function convertible
, converter::constructor_function construct
, type_info id
, char const *doc
)
: object(new_enum_type(name))
: object(new_enum_type(name, doc))
{
converter::registration& converters
= const_cast<converter::registration&>(

View File

@@ -6,6 +6,7 @@
#include <boost/python/docstring_options.hpp>
#include <boost/python/object/function_object.hpp>
#include <boost/python/object/function_handle.hpp>
#include <boost/python/object/function_doc_signature.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/str.hpp>
#include <boost/python/object_attributes.hpp>
@@ -17,6 +18,7 @@
#include <boost/python/ssize_t.hpp>
#include <boost/python/detail/signature.hpp>
#include <boost/python/detail/none.hpp>
#include <boost/mpl/vector/vector10.hpp>
#include <boost/bind.hpp>
@@ -30,7 +32,12 @@
namespace boost { namespace python {
volatile bool docstring_options::show_user_defined_ = true;
volatile bool docstring_options::show_signatures_ = true;
volatile bool docstring_options::show_cpp_signatures_ = true;
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
volatile bool docstring_options::show_py_signatures_ = true;
#else
volatile bool docstring_options::show_py_signatures_ = false;
#endif
}}
namespace boost { namespace python { namespace objects {
@@ -411,6 +418,12 @@ void function::add_to_namespace(
add_to_namespace(name_space, name_, attribute, 0);
}
namespace detail
{
extern char py_signature_tag[];
extern char cpp_signature_tag[];
}
void function::add_to_namespace(
object const& name_space, char const* name_, object const& attribute, char const* doc)
{
@@ -487,6 +500,7 @@ void function::add_to_namespace(
throw_error_already_set();
object mutable_attribute(attribute);
/*
if (doc != 0 && docstring_options::show_user_defined_)
{
// Accumulate documentation
@@ -517,6 +531,28 @@ void function::add_to_namespace(
mutable_attribute.attr("__doc__") += str("\n ").join(make_tuple(
"C++ signature:", f->signature(true)));
}
*/
str _doc;
if (docstring_options::show_py_signatures_)
{
_doc += str(reinterpret_cast<const char*>(detail::py_signature_tag));
}
if (doc != 0 && docstring_options::show_user_defined_)
_doc += doc;
if (docstring_options::show_cpp_signatures_)
{
// if(len(_doc))
// _doc += "\n"+str(reinterpret_cast<const char*>(detail::cpp_signature_tag));
// else
_doc += str(reinterpret_cast<const char*>(detail::cpp_signature_tag));
}
if(_doc)
{
object mutable_attribute(attribute);
mutable_attribute.attr("__doc__")= _doc;
}
}
BOOST_PYTHON_DECL void add_to_namespace(
@@ -591,7 +627,10 @@ extern "C"
static PyObject* function_get_doc(PyObject* op, void*)
{
function* f = downcast<function>(op);
return python::incref(f->doc().ptr());
list signatures = function_doc_signature_generator::function_doc_signatures(f);
if(!signatures) return python::detail::none();
signatures.reverse();
return python::incref( str("\n").join(signatures).ptr());
}
static int function_set_doc(PyObject* op, PyObject* doc, void*)

View File

@@ -0,0 +1,342 @@
// 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;
}
}}}

View File

@@ -349,5 +349,15 @@ BOOST_PYTHON_DEFINE_STR_METHOD(title, 0)
BOOST_PYTHON_DEFINE_STR_METHOD(translate, 1)
BOOST_PYTHON_DEFINE_STR_METHOD(translate, 2)
BOOST_PYTHON_DEFINE_STR_METHOD(upper, 0)
static struct register_str_pytype_ptr
{
register_str_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::str>())
).m_class_object = &PyString_Type;
}
}register_str_pytype_ptr_;
}}} // namespace boost::python

View File

@@ -21,4 +21,15 @@ tuple_base::tuple_base(object_cref sequence)
: object(call(sequence))
{}
static struct register_tuple_pytype_ptr
{
register_tuple_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::tuple>())
).m_class_object = &PyTuple_Type;
}
}register_tuple_pytype_ptr_;
}}} // namespace boost::python

View File

@@ -2,12 +2,20 @@
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
use-project /boost/python : ../build ;
project /boost/python/test ;
local PY = ;
if [ python.configured ]
{
PY = /python//python ;
}
rule py-run ( sources * : input-file ? )
{
return [ run $(sources) /boost/python//boost_python /python//python
return [ run $(sources) /boost/python//boost_python $(PY)
: # args
: $(input-file)
: #requirements
@@ -39,7 +47,7 @@ test-suite python
:
[
run exec.cpp ../build//boost_python/<link>static /python//python
run exec.cpp ../build//boost_python/<link>static $(PY)
: # program args
: exec.py
: # requirements
@@ -135,6 +143,7 @@ bpl-test crossmod_opaque
[ bpl-test nested ]
[ bpl-test docstring ]
[ bpl-test pytype_function ]
[ bpl-test vector_indexing_suite ]
@@ -147,7 +156,7 @@ bpl-test crossmod_opaque
<toolset>hp_cxx:<build>no ]
[ python-extension map_indexing_suite_ext
: map_indexing_suite.cpp int_map_indexing_suite.cpp
: map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp
/boost/python//boost_python ]
[ bpl-test
map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ]
@@ -182,7 +191,7 @@ bpl-test crossmod_opaque
:
:
: <define>BOOST_PYTHON_STATIC_LIB
<use>/python//python
<use>$(PY)
]

84
test/a_map_indexing_suite.cpp Executable file
View File

@@ -0,0 +1,84 @@
// Copyright Joel de Guzman 2004. 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/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/implicit.hpp>
using namespace boost::python;
struct A
{
int value;
A() : value(0){};
A(int v) : value(v) {};
};
bool operator==(const A& v1, const A& v2)
{
return (v1.value == v2.value);
}
struct B
{
A a;
};
// Converter from A to python int
struct AToPython
{
static PyObject* convert(const A& s)
{
return boost::python::incref(boost::python::object((int)s.value).ptr());
}
};
// Conversion from python int to A
struct AFromPython
{
AFromPython()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id< A >());
}
static void* convertible(PyObject* obj_ptr)
{
if (!PyInt_Check(obj_ptr)) return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
void* storage = (
(boost::python::converter::rvalue_from_python_storage< A >*)
data)-> storage.bytes;
new (storage) A((int)PyInt_AsLong(obj_ptr));
data->convertible = storage;
}
};
void a_map_indexing_suite()
{
to_python_converter< A , AToPython >();
AFromPython();
class_< std::map<int, A> >("AMap")
.def(map_indexing_suite<std::map<int, A>, true >())
;
class_< B >("B")
.add_property("a", make_getter(&B::a, return_value_policy<return_by_value>()),
make_setter(&B::a, return_value_policy<return_by_value>()))
;
}

View File

@@ -51,7 +51,7 @@ tuple raw_func(tuple args, dict kw)
BOOST_PYTHON_MODULE(args_ext)
{
def("f", f, args("x", "y", "z")
def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
, "This is f's docstring"
);
@@ -72,24 +72,24 @@ BOOST_PYTHON_MODULE(args_ext)
.def("raw", raw_function(raw_func))
;
class_<X>("X", "This is X's docstring")
.def(init<int, optional<int> >(args("a0", "a1")))
class_<X>("X", "This is X's docstring", init<>(args("self")))
.def(init<int, optional<int> >(args("self", "a0", "a1")))
.def("f", &X::f
, "This is X.f's docstring"
, args("x", "y", "z"))
, args("self","x", "y", "z"))
// Just to prove that all the different argument combinations work
.def("inner0", &X::inner, return_internal_reference<>(), args("n"), "docstring")
.def("inner1", &X::inner, return_internal_reference<>(), "docstring", args("n"))
.def("inner0", &X::inner, return_internal_reference<>(), args("self", "n"), "docstring")
.def("inner1", &X::inner, return_internal_reference<>(), "docstring", args("self", "n"))
.def("inner2", &X::inner, args("n"), return_internal_reference<>(), "docstring")
.def("inner3", &X::inner, "docstring", return_internal_reference<>(), args("n"))
.def("inner2", &X::inner, args("self", "n"), return_internal_reference<>(), "docstring")
.def("inner3", &X::inner, "docstring", return_internal_reference<>(), args("self", "n"))
.def("inner4", &X::inner, args("n"), "docstring", return_internal_reference<>())
.def("inner5", &X::inner, "docstring", args("n"), return_internal_reference<>())
.def("inner4", &X::inner, args("self", "n"), "docstring", return_internal_reference<>())
.def("inner5", &X::inner, "docstring", args("self", "n"), return_internal_reference<>())
.def("f1", &X::f, X_f_overloads(args("x", "y", "z")))
.def("f2", &X::f, X_f_overloads(args("x", "y", "z"), "f2's docstring"))
.def("f1", &X::f, X_f_overloads(args("self", "x", "y", "z")))
.def("f2", &X::f, X_f_overloads(args("self", "x", "y", "z"), "f2's docstring"))
;
def("inner", &X::inner, "docstring", args("self", "n"), return_internal_reference<>());

View File

@@ -84,24 +84,27 @@
(2, 4.25, 'wow')
>>> q.f1()
(1, 4.25, 'wow')
>>> q.f2.__doc__.splitlines()[-4]
"f2's docstring"
>>> q.f2.__doc__.splitlines()[1]
'f2( (X)self [, (int)x [, (float)y [, (str)z]]]) -> tuple :'
>>> X.f.__doc__.splitlines()[:3]
["This is X.f's docstring", '', 'C++ signature:']
>>> q.f2.__doc__.splitlines()[2]
" f2's docstring"
>>> X.f.__doc__.splitlines()[1:5]
['f( (X)self, (int)x, (float)y, (str)z) -> tuple :', " This is X.f's docstring", '', ' C++ signature :']
>>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5)
>>> for f in xfuncs:
... print f(q,1).value(),
... print f(q, n = 1).value(),
... print f(q, n = 0).value(),
... print f.__doc__.splitlines()[:3]
1 1 0 ['docstring', '', 'C++ signature:']
1 1 0 ['docstring', '', 'C++ signature:']
1 1 0 ['docstring', '', 'C++ signature:']
1 1 0 ['docstring', '', 'C++ signature:']
1 1 0 ['docstring', '', 'C++ signature:']
1 1 0 ['docstring', '', 'C++ signature:']
... print f.__doc__.splitlines()[1:5]
1 1 0 ['inner0( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
1 1 0 ['inner1( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
1 1 0 ['inner2( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
1 1 0 ['inner3( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
1 1 0 ['inner4( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
1 1 0 ['inner5( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
>>> x = X(a1 = 44, a0 = 22)
>>> x.inner0(0).value()
@@ -136,49 +139,9 @@ if __name__ == '__main__':
import sys
status = run()[0]
if (status == 0): print "Done."
import args_ext
help(args_ext)
sys.exit(status)

View File

@@ -64,6 +64,24 @@
... except TypeError: pass
... else: print 'expected a TypeError exception'
>>> print look.__doc__.splitlines()[1]
look( (X)arg1) -> int :
>>> print steal.__doc__.splitlines()[1]
steal( (X)arg1) -> int :
>>> print maybe_steal.__doc__.splitlines()[1]
maybe_steal( (X)arg1, (bool)arg2) -> int :
>>> print make.__doc__.splitlines()[1]
make() -> X :
>>> print callback.__doc__.splitlines()[1]
callback( (object)arg1) -> X :
>>> print extract.__doc__.splitlines()[1]
extract( (object)arg1) -> X :
'''
def run(args = None):

View File

@@ -16,6 +16,9 @@
>>> assert y_identity(y) is y
>>> y_equality(y, y)
1
>>> print y_identity.__doc__.splitlines()[1]
y_identity( (Y)arg1) -> object :
'''
def run(args = None):

View File

@@ -52,7 +52,7 @@ int Var::static1 = 0;
Y Var::static2(0);
// Compilability regression tests
namespace
namespace boost_python_test
{
struct trivial
{
@@ -86,6 +86,7 @@ namespace
BOOST_PYTHON_MODULE(data_members_ext)
{
using namespace boost_python_test;
class_<X>("X", init<int>())
.def("value", &X::value)
.def("set", &X::set)

View File

@@ -159,10 +159,10 @@ BOOST_PYTHON_MODULE(defaults_ext)
.def("get_state", &Y::get_state)
;
class_<X>("X")
class_<X>("X",no_init)
.def(init<int, optional<char, std::string, double> >("doc of init"))
.def(init<std::string, bool>()[default_call_policies()]) // what's a good policy here?
.def(init<optional<int, char, std::string, double> >("doc of init", args("self", "a", "b", "c", "d")))
.def(init<std::string, bool>(args("self", "s", "b"))[default_call_policies()]) // what's a good policy here?
.def("get_state", &X::get_state)
.def("bar", &X::bar, X_bar_stubs())
.def("bar2", &X::bar2, X_bar_stubs2("doc of X::bar2")[return_internal_reference<>()])

View File

@@ -113,28 +113,22 @@
... doc = obj.__doc__.splitlines()
... return "\\n".join(["|"+doc[i] for i in args])
>>> print selected_doc(X.__init__, 0, 3, 6, 9, 11, 12, 14, 17)
|C++ signature:
|C++ signature:
|C++ signature:
|C++ signature:
|
|doc of init
|C++ signature:
|C++ signature:
>>> print selected_doc(X.__init__, 1, 2, 4, 7, 9)
|__init__( (object)self [, (int)a [, (str)b [, (str)c [, (float)d]]]]) -> None :
| doc of init
| C++ signature :
|__init__( (object)self, (str)s, (bool)b) -> None :
| C++ signature :
>>> print selected_doc(Y.__init__, 0, 2)
|doc of Y init
|C++ signature:
>>> print selected_doc(Y.__init__, 1, 2, 4)
|__init__( (object)arg1) -> None :
| doc of Y init
| C++ signature :
>>> print selected_doc(X.bar2, 0, 3, 6, 9, 11, 12, 14)
|C++ signature:
|C++ signature:
|C++ signature:
|C++ signature:
|
|doc of X::bar2
|C++ signature:
>>> print selected_doc(X.bar2, 1, 2, 4)
|bar2( (X)arg1 [, (int)arg2 [, (str)arg3 [, (str)arg4 [, (float)arg5]]]]) -> Y :
| doc of X::bar2
| C++ signature :
"""
def run(args = None):

View File

@@ -43,55 +43,74 @@ BOOST_PYTHON_MODULE(docstring_ext)
, init<int>(
"this is the __init__ function\n"
"its documentation has two lines."
, args("self", "value")
)
)
.def("value", &X::value,
"gets the value of the object")
"gets the value of the object"
, args("self"))
.def( "value", &X::value,
"also gets the value of the object")
"also gets the value of the object"
, args("self"))
;
def("create", create, return_value_policy<manage_new_object>(),
"creates a new X object");
"creates a new X object", args("value"));
def("fact", fact, "compute the factorial");
def("fact", fact, "compute the factorial", args("n"));
{
docstring_options doc_options;
doc_options.disable_user_defined();
def("fact_usr_off_1", fact, "usr off 1");
def("fact_usr_off_1", fact, "usr off 1", args("n"));
doc_options.enable_user_defined();
def("fact_usr_on_1", fact, "usr on 1");
def("fact_usr_on_1", fact, "usr on 1", args("n"));
doc_options.disable_user_defined();
def("fact_usr_off_2", fact, "usr off 2");
def("fact_usr_off_2", fact, "usr off 2", args("n"));
}
def("fact_usr_on_2", fact, "usr on 2");
def("fact_usr_on_2", fact, "usr on 2", args("n"));
{
docstring_options doc_options(true, false);
def("fact_sig_off_1", fact, "sig off 1");
def("fact_sig_off_1", fact, "sig off 1", args("n"));
doc_options.enable_signatures();
def("fact_sig_on_1", fact, "sig on 1");
def("fact_sig_on_1", fact, "sig on 1", args("n"));
doc_options.disable_signatures();
def("fact_sig_off_2", fact, "sig off 2");
def("fact_sig_off_2", fact, "sig off 2", args("n"));
}
def("fact_sig_on_2", fact, "sig on 2");
def("fact_sig_on_2", fact, "sig on 2", args("n"));
{
docstring_options doc_options(false);
def("fact_usr_off_sig_off_1", fact, "usr off sig off 1");
def("fact_usr_off_sig_off_1", fact, "usr off sig off 1", args("n"));
{
docstring_options nested_doc_options;
def("fact_usr_on_sig_on_1", fact, "usr on sig on 1");
def("fact_usr_on_sig_on_1", fact, "usr on sig on 1", args("n"));
nested_doc_options.disable_all();
nested_doc_options.enable_user_defined();
def("fact_usr_on_sig_off_1", fact, "usr on sig off 1");
def("fact_usr_on_sig_off_1", fact, "usr on sig off 1", args("n"));
nested_doc_options.enable_all();
def("fact_usr_on_sig_on_2", fact, "usr on sig on 2");
def("fact_usr_on_sig_on_2", fact, "usr on sig on 2", args("n"));
}
def("fact_usr_off_sig_off_2", fact, "usr off sig off 2");
def("fact_usr_off_sig_off_2", fact, "usr off sig off 2", args("n"));
}
{
docstring_options doc_options(true);
doc_options.disable_cpp_signatures();
def("fact_usr_on_psig_on_csig_off_1", fact, "usr on psig on csig off 1", args("n"));
doc_options.enable_cpp_signatures();
doc_options.disable_py_signatures();
def("fact_usr_on_psig_off_csig_on_1", fact, "usr on psig off csig on 1", args("n"));
doc_options.enable_py_signatures();
doc_options.disable_user_defined();
doc_options.disable_cpp_signatures();
def("fact_usr_off_psig_on_csig_off_1", fact, "usr off psig on csig off 1", args("n"));
doc_options.enable_cpp_signatures();
doc_options.disable_py_signatures();
def("fact_usr_off_psig_off_csig_on_1", fact, "usr off psig off csig on 1", args("n"));
}
}
#include "module_tail.cpp"

View File

@@ -8,82 +8,114 @@
... doc = obj.__doc__.splitlines()
... return "\\n".join(["|"+doc[i] for i in args])
>>> print selected_doc(X.__init__, 0, 1, 3)
|this is the __init__ function
|its documentation has two lines.
|C++ signature:
>>> print selected_doc(X.value, 0, 2, 4, 5, 7)
|gets the value of the object
|C++ signature:
>>> print selected_doc(X.__init__, 1, 2, 3, 4, 5)
|__init__( (object)self, (int)value) -> None :
| this is the __init__ function
| its documentation has two lines.
|
|also gets the value of the object
|C++ signature:
| C++ signature :
>>> print selected_doc(create, 0, 2)
|creates a new X object
|C++ signature:
>>> print selected_doc(X.value, 1, 2, 4, 7, 8, 10)
|value( (X)self) -> int :
| gets the value of the object
| C++ signature :
|value( (X)self) -> int :
| also gets the value of the object
| C++ signature :
>>> print selected_doc(fact, 0, 2)
|compute the factorial
|C++ signature:
>>> print selected_doc(create, 1, 2, 3, 4)
|create( (int)value) -> X :
| creates a new X object
|
| C++ signature :
>>> print selected_doc(fact, 1, 2, 3, 4)
|fact( (int)n) -> int :
| compute the factorial
|
| C++ signature :
>>> len(fact_usr_off_1.__doc__.splitlines())
2
>>> print selected_doc(fact_usr_off_1, 0)
|C++ signature:
5
>>> print selected_doc(fact_usr_off_1, 1, 3)
|fact_usr_off_1( (int)n) -> int :
| C++ signature :
>>> len(fact_usr_on_1.__doc__.splitlines())
4
>>> print selected_doc(fact_usr_on_1, 0, 2)
|usr on 1
|C++ signature:
6
>>> print selected_doc(fact_usr_on_1, 1, 2, 4)
|fact_usr_on_1( (int)n) -> int :
| usr on 1
| C++ signature :
>>> len(fact_usr_off_2.__doc__.splitlines())
2
>>> print selected_doc(fact_usr_off_2, 0)
|C++ signature:
5
>>> print selected_doc(fact_usr_off_2, 1, 3)
|fact_usr_off_2( (int)n) -> int :
| C++ signature :
>>> len(fact_usr_on_2.__doc__.splitlines())
4
>>> print selected_doc(fact_usr_on_2, 0, 2)
|usr on 2
|C++ signature:
6
>>> print selected_doc(fact_usr_on_2, 1, 2, 4)
|fact_usr_on_2( (int)n) -> int :
| usr on 2
| C++ signature :
>>> len(fact_sig_off_1.__doc__.splitlines())
1
>>> print selected_doc(fact_sig_off_1, 0)
2
>>> print selected_doc(fact_sig_off_1, 1)
|sig off 1
>>> len(fact_sig_on_1.__doc__.splitlines())
4
>>> print selected_doc(fact_sig_on_1, 0, 2)
|sig on 1
|C++ signature:
6
>>> print selected_doc(fact_sig_on_1, 1, 2, 4)
|fact_sig_on_1( (int)n) -> int :
| sig on 1
| C++ signature :
>>> len(fact_sig_off_2.__doc__.splitlines())
1
>>> print selected_doc(fact_sig_off_2, 0)
2
>>> print selected_doc(fact_sig_off_2, 1)
|sig off 2
>>> len(fact_sig_on_2.__doc__.splitlines())
4
>>> print selected_doc(fact_sig_on_2, 0, 2)
|sig on 2
|C++ signature:
6
>>> print selected_doc(fact_sig_on_2, 1, 2, 4)
|fact_sig_on_2( (int)n) -> int :
| sig on 2
| C++ signature :
>>> print fact_usr_off_sig_off_1.__doc__
None
>>> len(fact_usr_on_sig_on_1.__doc__.splitlines())
4
>>> print selected_doc(fact_usr_on_sig_on_1, 0, 2)
|usr on sig on 1
|C++ signature:
6
>>> print selected_doc(fact_usr_on_sig_on_1, 1, 2, 4)
|fact_usr_on_sig_on_1( (int)n) -> int :
| usr on sig on 1
| C++ signature :
>>> len(fact_usr_on_sig_off_1.__doc__.splitlines())
1
>>> print selected_doc(fact_usr_on_sig_off_1, 0)
2
>>> print selected_doc(fact_usr_on_sig_off_1, 1)
|usr on sig off 1
>>> len(fact_usr_on_sig_on_2.__doc__.splitlines())
4
>>> print selected_doc(fact_usr_on_sig_on_2, 0, 2)
|usr on sig on 2
|C++ signature:
>>> print fact_usr_off_sig_off_2.__doc__
None
6
>>> print selected_doc(fact_usr_on_sig_on_2, 1, 2, 4)
|fact_usr_on_sig_on_2( (int)n) -> int :
| usr on sig on 2
| C++ signature :
>>> print selected_doc(fact_usr_on_psig_on_csig_off_1, 1, 2)
|fact_usr_on_psig_on_csig_off_1( (int)n) -> int :
| usr on psig on csig off 1
>>> print selected_doc(fact_usr_on_psig_off_csig_on_1, 1, 3)
|usr on psig off csig on 1
|C++ signature :
>>> print fact_usr_off_psig_on_csig_off_1.__doc__.splitlines()[1]
fact_usr_off_psig_on_csig_off_1( (int)n) -> int
>>> print selected_doc(fact_usr_off_psig_off_csig_on_1,1)
|C++ signature :
'''

View File

@@ -13,6 +13,19 @@
>>> try: make_x('fool')
... except TypeError: pass
... else: print 'no error'
>>> print x_value.__doc__.splitlines()[1]
x_value( (X)arg1) -> int :
>>> print make_x.__doc__.splitlines()[1]
make_x( (object)arg1) -> X :
>>> print X.value.__doc__.splitlines()[1]
value( (X)arg1) -> int :
>>> print X.set.__doc__.splitlines()[1]
set( (X)arg1, (object)arg2) -> None :
'''
def run(args = None):

View File

@@ -80,8 +80,10 @@
>>> f.set(1,1.0,"1")
>>> f.a(), f.b(), f.n()
(1, 1.0, '1')
>>> f.set2.__doc__.splitlines()[-4]
"set2's docstring"
>>> f.set2.__doc__.splitlines()[1]
'set2( (Bar)arg1 [, (int)arg2 [, (float)arg3 [, (str)arg4]]]) -> None :'
>>> f.set2.__doc__.splitlines()[2]
" set2's docstring"
'''

View File

@@ -13,6 +13,7 @@
#include <boost/python/to_python_converter.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/manage_new_object.hpp>
#include <boost/python/converter/pytype_function.hpp>
#include <string.h>
#include "simple_type.hpp"
#include "complicated.hpp"
@@ -170,7 +171,8 @@ using boost::python::to_python_converter;
// Wrap a simple by copying it into a Simple
struct simple_to_python
: to_python_converter<simple, simple_to_python>
: to_python_converter<simple, simple_to_python, true>
//, boost::python::converter::wrap_pytype<&SimpleType>
{
static PyObject* convert(simple const& x)
{
@@ -178,6 +180,7 @@ struct simple_to_python
p->x = x;
return (PyObject*)p;
}
static PyTypeObject const *get_pytype(){return &SimpleType; }
};
struct int_from_noddy

View File

@@ -26,61 +26,6 @@ std::string x_value(X const& x)
return "gotya " + x.s;
}
struct A
{
int value;
A() : value(0){};
A(int v) : value(v) {};
};
bool operator==(const A& v1, const A& v2)
{
return (v1.value == v2.value);
}
struct B
{
A a;
};
// Converter from A to python int
struct AToPython
{
static PyObject* convert(const A& s)
{
return boost::python::incref(boost::python::object((int)s.value).ptr());
}
};
// Conversion from python int to A
struct AFromPython
{
AFromPython()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id< A >());
}
static void* convertible(PyObject* obj_ptr)
{
if (!PyInt_Check(obj_ptr)) return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
void* storage = (
(boost::python::converter::rvalue_from_python_storage< A >*)
data)-> storage.bytes;
new (storage) A((int)PyInt_AsLong(obj_ptr));
data->convertible = storage;
}
};
BOOST_PYTHON_MODULE(map_indexing_suite_ext)
{
@@ -115,17 +60,9 @@ BOOST_PYTHON_MODULE(map_indexing_suite_ext)
.def(map_indexing_suite<std::map<std::string, boost::shared_ptr<X> >, true>())
;
to_python_converter< A , AToPython >();
AFromPython();
class_< std::map<int, A> >("AMap")
.def(map_indexing_suite<std::map<int, A>, true >())
;
class_< B >("B")
.add_property("a", make_getter(&B::a, return_value_policy<return_by_value>()),
make_setter(&B::a, return_value_policy<return_by_value>()))
;
void a_map_indexing_suite(); // moved to a_map_indexing_suite.cpp to
a_map_indexing_suite(); // avoid MSVC 6/7 internal structure overflow
}
#include "module_tail.cpp"

View File

@@ -183,6 +183,8 @@ are a complicated constructor and member function, respectively.
>>> dd = take_d(d_as_a)
>>> dd.name()
'D'
>>> print g.__doc__.splitlines()[1]
g( (Simple)arg1) -> Simple :
"""

View File

@@ -19,7 +19,7 @@
#include <string>
namespace {
namespace boost_python_test {
// A friendly class.
class world
@@ -52,6 +52,7 @@ namespace {
BOOST_PYTHON_MODULE(pickle1_ext)
{
using namespace boost::python;
using namespace boost_python_test;
class_<world>("world", init<const std::string&>())
.def("greet", &world::greet)
.def_pickle(world_pickle_suite())

View File

@@ -28,7 +28,7 @@
#include <boost/python/tuple.hpp>
#include <boost/python/extract.hpp>
namespace { // Avoid cluttering the global namespace.
namespace boost_python_test {
// A friendly class.
class world
@@ -88,6 +88,7 @@ namespace { // Avoid cluttering the global namespace.
BOOST_PYTHON_MODULE(pickle2_ext)
{
using namespace boost_python_test;
boost::python::class_<world>(
"world", boost::python::init<const std::string&>())
.def("greet", &world::greet)

View File

@@ -29,7 +29,7 @@
# define make_tuple boost::python::make_tuple
#endif
namespace { // Avoid cluttering the global namespace.
namespace boost_python_test {
// A friendly class.
class world
@@ -100,6 +100,7 @@ namespace { // Avoid cluttering the global namespace.
BOOST_PYTHON_MODULE(pickle3_ext)
{
using namespace boost_python_test;
boost::python::class_<world>(
"world", boost::python::init<const std::string&>())
.def("greet", &world::greet)

View File

@@ -15,7 +15,7 @@
#include <string>
namespace {
namespace boost_python_test {
// A friendly class.
class world
@@ -35,6 +35,7 @@ namespace {
BOOST_PYTHON_MODULE(pickle4_ext)
{
using namespace boost::python;
using namespace boost_python_test;
class_<world>("world", init<const std::string&>())
.enable_pickling()
.def("greet", &world::greet)

85
test/pytype_function.cpp Normal file
View File

@@ -0,0 +1,85 @@
// Copyright Joel de Guzman 2004. 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/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/python/class.hpp>
using namespace boost::python;
struct A
{
};
struct B
{
A a;
B(const A& a_):a(a_){}
};
// Converter from A to python int
struct BToPython
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
: converter::to_python_target_type<A> //inherits get_pytype
#endif
{
static PyObject* convert(const B& b)
{
return boost::python::incref(boost::python::object(b.a).ptr());
}
};
// Conversion from python int to A
struct BFromPython
{
BFromPython()
{
boost::python::converter::registry::push_back(
&convertible,
&construct,
boost::python::type_id< B >()
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
, &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
#endif
);
}
static void* convertible(PyObject* obj_ptr)
{
extract<const A&> ex(obj_ptr);
if (!ex.check()) return 0;
return obj_ptr;
}
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
void* storage = (
(boost::python::converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
extract<const A&> ex(obj_ptr);
new (storage) B(ex());
data->convertible = storage;
}
};
B func(const B& b) { return b ; }
BOOST_PYTHON_MODULE(pytype_function_ext)
{
to_python_converter< B , BToPython,true >(); //has get_pytype
BFromPython();
class_<A>("A") ;
def("func", &func);
}
#include "module_tail.cpp"

27
test/pytype_function.py Executable file
View File

@@ -0,0 +1,27 @@
# Copyright David Abrahams 2004. 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)
"""
>>> from pytype_function_ext import *
>>> print func.__doc__.splitlines()[1]
func( (A)arg1) -> A :
"""
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
status = run()[0]
if (status == 0): print "Done."
sys.exit(status)

View File

@@ -43,6 +43,7 @@ struct functions
}
static shared_ptr<T> get() { return storage; }
static shared_ptr<T> &get1() { return storage; }
static int look_store()
{
@@ -71,6 +72,8 @@ struct functions
.staticmethod("identity")
.def("null", &null)
.staticmethod("null")
.def("get1", &get1, return_internal_reference<>())
.staticmethod("get1")
.def("get", &get)
.staticmethod("get")
.def("count", &T::count)
@@ -154,6 +157,14 @@ shared_ptr<Y> factory(int n)
// ------
// from Neal Becker
struct Test {
boost::shared_ptr<X> x;
};
// ------
BOOST_PYTHON_MODULE(shared_ptr_ext)
{
class_<A, boost::shared_ptr<A_Wrapper>, boost::noncopyable>("A")
@@ -193,6 +204,12 @@ BOOST_PYTHON_MODULE(shared_ptr_ext)
.def("value", &Z::value)
.def("v", &Z::v, &ZWrap::default_v)
);
// from Neal Becker
class_<Test> ("Test")
.def_readonly ("x", &Test::x, "x")
;
// ------
}
#include "module_tail.cpp"