2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 05:22:45 +00:00

Compare commits

..

7 Commits

Author SHA1 Message Date
Daniel James
f1ed00e3a5 Use root links in quickbook.
[SVN r45364]
2008-05-14 20:38:29 +00:00
Daniel James
0c5577c99a Update 'more' links.
[SVN r44996]
2008-05-01 21:34:42 +00:00
Daniel James
21d11150fd Work around a quickbook bug which is affecting the python docs. Refs #1864.
[SVN r44590]
2008-04-19 15:38:29 +00:00
Daniel James
502fe1fdb2 Fix some links in the python docs. Refs #1684.
[SVN r44589]
2008-04-19 15:37:39 +00:00
Daniel James
5d3b58f6f7 Create a branch for documentation work.
[SVN r44584]
2008-04-19 14:48:18 +00:00
Joel de Guzman
b316819925 Andreas indexing suite patch
[SVN r44450]
2008-04-16 03:07:11 +00:00
Joel de Guzman
52245de2e5 Andreas patch
[SVN r44449]
2008-04-16 03:07:06 +00:00
31 changed files with 268 additions and 991 deletions

View File

@@ -1,64 +0,0 @@
if (PYTHON_LIBRARIES)
include_directories(${PYTHON_INCLUDE_PATH})
# Determine extra libraries we need to link against to build Python
# extension modules.
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "dl")
if(CMAKE_COMPILER_IS_GNUCXX)
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
endif(CMAKE_COMPILER_IS_GNUCXX)
elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSD")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread")
elseif(CMAKE_SYSTEM_NAME STREQUAL "DragonFly")
# DragonFly is a variant of FreeBSD
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread")
elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread" "dl")
if(CMAKE_COMPILER_IS_GNUCXX)
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
endif(CMAKE_COMPILER_IS_GNUCXX)
elseif(CMAKE_SYSTEM_NAME STREQUAL "QNX")
# No options necessary for QNX
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
# No options necessary for Mac OS X
elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "rt")
elseif(UNIX)
# Assume -pthread and -ldl on all other variants
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "pthread" "dl")
if(CMAKE_COMPILER_IS_GNUCXX)
set(PYTHON_LIBRARIES ${PYTHON_LIBRARIES} "util")
endif(CMAKE_COMPILER_IS_GNUCXX)
endif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
# Macro for building Boost.Python extension modules
macro(boost_python_extension MODULE_NAME)
parse_arguments(BPL_EXT
""
""
${ARGN})
# Create the library target itself
add_library(${MODULE_NAME} MODULE ${BPL_EXT_DEFAULT_ARGS} )
# Miscellaneous target properties
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
# Link against Boost.Python library
target_link_libraries(${MODULE_NAME} boost_python-shared)
# Link against Python libraries
target_link_libraries(${MODULE_NAME} ${PYTHON_LIBRARIES})
endmacro(boost_python_extension)
boost_library_project(
Python
SRCDIRS src
TESTDIRS test
HEADERS python.hpp python
MODULARIZED
DESCRIPTION "A framework for interfacing Python and C++. It allows you to quickly and seamlessly expose C++ classes functions and objects to Python, and vice-versa, using no special tools -- just your C++ compiler."
AUTHORS "David Abrahams <dave -at- boostpro.com>"
)
endif (PYTHON_LIBRARIES)

View File

@@ -9,7 +9,7 @@
</head>
<body>
<div class="document" id="logo-boost-python-build-and-test-howto">
<h1 class="title"><a class="reference external" href="../index.html"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
<h1 class="title"><a class="reference external" href="../index.htm"><img alt="Boost C++ Libraries:" class="boost-logo" src="../../../boost.png" /></a> Boost.Python Build and Test HOWTO</h1>
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
@@ -158,8 +158,8 @@ all the parts of your Python installation. If it isn't, consider
<p>If you're still having trouble, Someone on one of the following
mailing lists may be able to help:</p>
<ul class="simple">
<li>The <a class="reference external" href="http://www.boost.org/more/mailing_lists.htm#jamboost">Boost.Build mailing list</a> for issues related to Boost.Build</li>
<li>The Python <a class="reference external" href="http://www.boost.org/more/mailing_lists.htm#cplussig">C++ Sig</a> for issues specifically related to Boost.Python</li>
<li>The <a class="reference external" href="http://www.boost.org/community/groups.html#jamboost">Boost.Build mailing list</a> for issues related to Boost.Build</li>
<li>The Python <a class="reference external" href="http://www.boost.org/community/groups.html#cplussig">C++ Sig</a> for issues specifically related to Boost.Python</li>
</ul>
</div>
<div class="section" id="in-case-everything-seemed-to-work">

View File

@@ -177,8 +177,8 @@ mailing lists may be able to help:
* The `Boost.Build mailing list`__ for issues related to Boost.Build
* The Python `C++ Sig`__ for issues specifically related to Boost.Python
__ http://www.boost.org/more/mailing_lists.htm#jamboost
__ http://www.boost.org/more/mailing_lists.htm#cplussig
__ http://www.boost.org/community/groups.html#jamboost
__ http://www.boost.org/community/groups.html#cplussig
In Case Everything Seemed to Work
---------------------------------

View File

@@ -375,27 +375,6 @@
application modules, including GUI and post-processing of results.</p>
</dd>
<dt><b><a href="http://polybori.sourceforge.net/">PolyBoRi</a></b></dt>
<dd>
<p><a href="mailto:brickenstein@mfo.de"
>Michael Brickenstein</a> writes:</p>
<blockquote>
<p>The core of PolyBoRi is a C++ library, which provides
high-level data types for Boolean polynomials and monomials,
exponent vectors, as well as for the underlying polynomial
rings and subsets of the powerset of the Boolean variables. As
a unique approach, binary decision diagrams are used as
internal storage type for polynomial structures. On top of
this C++-library we provide a Python interface. This allows
parsing of complex polynomial systems, as well as sophisticated
and extendable strategies for Gr&ouml;bner basis computation.
Boost.Python has helped us to create this interface in a
very clean way.</p>
</blockquote>
</dd>
<dt><b><a href="http://www.rationaldiscovery.com">Rational Discovery
LLC</a></b></dt>
@@ -456,11 +435,11 @@
</dl>
<hr>
<p>Revised
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
29 May, 2008</p>
15 July, 2003</p>
<p><i>&copy; Copyright <a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a> 2002-2008.</i></p>
Abrahams</a> 2002-2003.</i></p>
</body>
</html>

View File

@@ -47,7 +47,7 @@
&nbsp;</dt>
<dt><b><a href=
"http://www.boost.org/more/mailing_lists.htm#cplussig">The Python
"http://www.boost.org/community/groups.html#cplussig">The Python
C++-sig</a></b> mailing list is a forum for discussing Python/C++
interoperability, and Boost.Python in particular. Post your
Boost.Python questions here.<br>

View File

@@ -93,7 +93,7 @@ who had to use a different tool.
We will skip over the details. Our objective will be to simply create
the hello world module and run it in Python. For a complete reference to
building Boost.Python, check out: [@../../../building.html
building Boost.Python, check out: [@/libs/python/doc/building.html
building.html]. After this brief ['bjam] tutorial, we should have built
the DLLs and run a python program using the extension.
@@ -118,7 +118,7 @@ platforms. The complete list of Bjam executables can be found
[h2 Let's Jam!]
__jam__
[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot
[@/libs/python/example/tutorial/Jamroot Here] is our minimalist Jamroot
file. Simply copy the file and tweak [^use-project boost] to where your
boost root directory is and your OK.
@@ -186,10 +186,6 @@ And so on... Finally:
Or something similar. If all is well, you should now have built the DLLs and
run the Python program.
[note Starting from Boost 1.35, bjam erases the generated executables
(e.g. pyd file) after the test has concluded to conserve disk space.
To keep bjam from doing that, pass --preserve-test-targets to bjam.]
[:[*There you go... Have fun!]]
[endsect]
@@ -467,7 +463,7 @@ functions so that a Python override may be called:
};
Notice too that in addition to inheriting from `Base`, we also multiply-
inherited `wrapper<Base>` (See [@../../../v2/wrapper.html Wrapper]). The
inherited `wrapper<Base>` (See [@/libs/python/doc/v2/wrapper.html Wrapper]). The
`wrapper` template makes the job of wrapping classes that are meant to
overridden in Python, easier.
@@ -499,7 +495,7 @@ Methods correspond roughly to C++'s [*member functions]]
[section Virtual Functions with Default Implementations]
We've seen in the previous section how classes with pure virtual functions are
wrapped using Boost.Python's [@../../../v2/wrapper.html class wrapper]
wrapped using Boost.Python's [@/libs/python/doc/v2/wrapper.html class wrapper]
facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
mechanism is a bit different.
@@ -816,7 +812,7 @@ or more policies can be composed by chaining. Here's the general syntax:
policy3<args...> > >
Here is the list of predefined call policies. A complete reference detailing
these can be found [@../../../v2/reference.html#models_of_call_policies here].
these can be found [@/libs/python/doc/v2/reference.html#models_of_call_policies here].
* [*with_custodian_and_ward]: Ties lifetimes of the arguments
* [*with_custodian_and_ward_postcall]: Ties lifetimes of the arguments and results
@@ -974,7 +970,7 @@ fourth macro argument). The thin wrappers are all enclosed in a class named
.def("wack_em", &george::wack_em, george_overloads());
See the [@../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
See the [@/libs/python/doc/v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec overloads reference]
for details.
[h2 init and optional]
@@ -1271,7 +1267,7 @@ associated with the C++ type passed as its first parameter.
The scope is a class that has an associated global Python object which
controls the Python namespace in which new extension classes and wrapped
functions will be defined as attributes. Details can be found
[@../../../v2/scope.html here].]
[@/libs/python/doc/v2/scope.html here].]
You can access those values in Python as
@@ -1332,7 +1328,7 @@ in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
variants are called [^boost_python.lib] (for release builds) and
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
you probably haven't built Boost.Python yet. See
[@../../../building.html Building and Testing] on how to do this.
[@/libs/python/doc/building.html Building and Testing] on how to do this.
Python's library can be found in the [^/libs] subdirectory of
your Python directory. On Windows it is called pythonXY.lib where X.Y is
@@ -1390,8 +1386,8 @@ There is a difference however. While the reference-counting is fully
automatic in Python, the Python\/C API requires you to do it
[@http://www.python.org/doc/current/api/refcounts.html by hand]. This is
messy and especially hard to get right in the presence of C++ exceptions.
Fortunately Boost.Python provides the [@../../../v2/handle.html handle] and
[@../../../v2/object.html object] class templates to automate the process.
Fortunately Boost.Python provides the [@/libs/python/doc/v2/handle.html handle] and
[@/libs/python/doc/v2/object.html object] class templates to automate the process.
[h2 Running Python code]
@@ -1454,7 +1450,7 @@ which returns the result directly:
[h2 Exception handling]
If an exception occurs in the evaluation of the python expression,
[@../../../v2/errors.html#error_already_set-spec error_already_set] is thrown:
[@/libs/python/doc/v2/errors.html#error_already_set-spec error_already_set] is thrown:
try
{
@@ -1958,13 +1954,13 @@ This method is recommended too if you are developing the C++ library and
exporting it to Python at the same time: changes in a class will only demand
the compilation of a single cpp, instead of the entire wrapper code.
[note If you're exporting your classes with [@../../../../pyste/index.html Pyste],
[note If you're exporting your classes with [@/libs/python/doc/pyste/index.html Pyste],
take a look at the [^--multiple] option, that generates the wrappers in
various files as demonstrated here.]
[note This method is useful too if you are getting the error message
['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
a large source file, as explained in the [@../../../v2/faq.html#c1204 FAQ].]
a large source file, as explained in the [@/libs/python/doc/v2/faq.html#c1204 FAQ].]
[endsect]
[endsect] [/ General Techniques]

View File

@@ -137,7 +137,7 @@
<td valign="top"><code>P::extract_return_type</code></td>
<td>A model of <a href=
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a>.</td>
"../../../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>

View File

@@ -4,7 +4,7 @@
<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 - Dereferenceable Concept</title>
</head>
<body link="#0000ff" vlink="#800080">

View File

@@ -4,7 +4,7 @@
<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 - Extractor Concept</title>
</head>
<body link="#0000ff" vlink="#800080">

View File

@@ -4,7 +4,7 @@
<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 - Holder Concept</title>
</head>
<body link="#0000ff" vlink="#800080">

View File

@@ -74,32 +74,6 @@
</dl>
</dd>
<dt><a href="#const_objattribute_policies-spec">Class
<code>const_objattribute_policies</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#const_objattribute_policies-spec-synopsis">Class
<code>const_objattribute_policies</code> synopsis</a></dt>
<dt><a href="#const_objattribute_policies-spec-statics">Class
<code>const_objattribute_policies</code> static functions</a></dt>
</dl>
</dd>
<dt><a href="#objattribute_policies-spec">Class
<code>objattribute_policies</code></a></dt>
<dd>
<dl class="page-index">
<dt><a href="#objattribute_policies-spec-synopsis">Class
<code>objattribute_policies</code> synopsis</a></dt>
<dt><a href="#objattribute_policies-spec-statics">Class
<code>objattribute_policies</code> static functions</a></dt>
</dl>
</dd>
<dt><a href="#const_item_policies-spec">Class
<code>const_item_policies</code></a></dt>
@@ -354,102 +328,6 @@ static void del(object const&amp;target, char const* key);
<!-- end -->
<!-- begin -->
<h3><a name="const_objattribute_policies-spec"></a>Class
<code>const_objattribute_policies</code></h3>
<p>The policies which are used for proxies representing an attribute
access to a <code>const&nbsp;object</code> when the attribute name is
given as a <code>const&nbsp;object</code>.</p>
<h4><a name="const_objattribute_policies-spec-synopsis"></a>Class
<code>const_objattribute_policies</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace api
{
struct const_objattribute_policies
{
typedef object const& key_type;
static object get(object const&amp; target, object const& key);
};
}}}
</pre>
<h4><a name="const_objattribute_policies-spec-statics"></a>Class
<code>const_objattribute_policies</code> static functions</h4>
<pre>
static object get(object const&amp; target, object const& key);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>key</code> is an <code>object</code>
holding a string.</dt>
<dt><b>Effects:</b> accesses the attribute of <code>target</code> named
by <code>key</code>.</dt>
<dt><b>Returns:</b> An <code>object</code> managing the result of the
attribute access.</dt>
<dt><b>Throws:</b> <code><a href=
"errors.html#error_already_set-spec">error_already_set</a></code> if a
Python exception is raised.</dt>
</dl>
<h3><a name="objattribute_policies-spec"></a>Class
<code>objattribute_policies</code></h3>
<p>The policies which are used for proxies representing an attribute
access to a mutable <code>object</code> when the attribute name is
given as a <code>const&nbsp;object</code>.</p>
<h4><a name="objattribute_policies-spec-synopsis"></a>Class
<code>objattribute_policies</code> synopsis</h4>
<pre>
namespace boost { namespace python { namespace api
{
struct objattribute_policies : const_objattribute_policies
{
static object const&amp; set(object const&amp; target, object const& key, object const&amp; value);
static void del(object const&amp;target, object const& key);
};
}}}
</pre>
<h4><a name="objattribute_policies-spec-statics"></a>Class
<code>objattribute_policies</code> static functions</h4>
<pre>
static object const&amp; set(object const&amp; target, object const& key, object const&amp; value);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>key</code> is an <code>object</code>
holding a string.</dt>
<dt><b>Effects:</b> sets the attribute of <code>target</code> named by
<code>key</code> to <code>value</code>.</dt>
<dt><b>Throws:</b> <code><a href=
"errors.html#error_already_set-spec">error_already_set</a></code> if a
Python exception is raised.</dt>
</dl>
<pre>
static void del(object const&amp;target, object const& key);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>key</code> is an <code>object</code>
holding a string.</dt>
<dt><b>Effects:</b> deletes the attribute of <code>target</code> named
by <code>key</code>.</dt>
<dt><b>Throws:</b> <code><a href=
"errors.html#error_already_set-spec">error_already_set</a></code> if a
Python exception is raised.</dt>
</dl>
<!-- end -->
<!-- begin -->
<h3><a name="const_item_policies-spec"></a>Class
<code>const_item_policies</code></h3>
@@ -655,11 +533,6 @@ namespace boost { namespace python { namespace api
template &lt;class A0, class A1,...class An&gt;
object operator()(A0 const&amp;, A1 const&amp;,...An const&amp;) const;
detail::args_proxy operator* () const;
object operator()(detail::args_proxy const &amp;args) const;
object operator()(detail::args_proxy const &amp;args,
detail::kwds_proxy const &amp;kwds) const;
// truth value testing
//
typedef unspecified bool_type;
@@ -669,8 +542,6 @@ namespace boost { namespace python { namespace api
//
proxy&lt;const_object_attribute&gt; attr(char const*) const;
proxy&lt;object_attribute&gt; attr(char const*);
proxy&lt;const_object_objattribute&gt; attr(object const&) const;
proxy&lt;object_objattribute&gt; attr(object const&);
// item access
//
@@ -709,25 +580,6 @@ object operator()(A0 const&amp; a1, A1 const&amp; a2,...An const&amp; aN) const;
call&lt;object&gt;(object(*static_cast&lt;U*&gt;(this)).ptr(), a1,
a2,...aN)</dt>
</dl>
<pre>
object operator()(detail::args_proxy const &amp;args) const;
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
call object with arguments given by the tuple <varname>args</varname></dt>
</dl>
<pre>
object operator()(detail::args_proxy const &amp;args,
detail::kwds_proxy const &amp;kwds) const;
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b>
call object with arguments given by the tuple <varname>args</varname>, and named
arguments given by the dictionary <varname>kwds</varname></dt>
</dl>
<pre>
operator bool_type() const;
</pre>
@@ -756,21 +608,6 @@ proxy&lt;object_attribute&gt; attr(char const* name);
<code>name</code> as its key.</dt>
</dl>
<pre>
proxy&lt;const_object_objattribute&gt; attr(const object& name) const;
proxy&lt;object_objattribute&gt; attr(const object& name);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> name is a <code>object</code> holding a string.</dt>
<dt><b>Effects:</b> accesses the named attribute of
<code>*this</code>.</dt>
<dt><b>Returns:</b> a proxy object which binds
<code>object(*static_cast&lt;U*&gt;(this))</code> as its target, and
<code>name</code> as its key.</dt>
</dl>
<pre>
template &lt;class T&gt;
proxy&lt;const_object_item&gt; operator[](T const&amp; key) const;
template &lt;class T&gt;
@@ -1101,11 +938,11 @@ object sum_items(object seq)
</pre>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
27 May, 2008
13 January, 2006
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href=
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2008.</i></p>
"http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> 2006.</i></p>
</body>
</html>

View File

@@ -1,93 +1,112 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Boost.Python Pickle Support</title>
</head>
<title>Boost.Python Pickle Support</title>
<body>
<div>
<img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"center" width="277" height="86" />
<hr />
<div>
<h1>Boost.Python Pickle Support</h1>Pickle is a Python module for object
serialization, also known as persistence, marshalling, or flattening.
<img src="../../../../boost.png"
alt="boost.png (6897 bytes)"
align="center"
width="277" height="86">
<p>It is often necessary to save and restore the contents of an object to
a file. One approach to this problem is to write a pair of functions that
read and write data from a file in a special format. A powerful
alternative approach is to use Python's pickle module. Exploiting
Python's ability for introspection, the pickle module recursively
converts nearly arbitrary Python objects into a stream of bytes that can
be written to a file.</p>
<hr>
<h1>Boost.Python Pickle Support</h1>
<p>The Boost Python Library supports the pickle module through the
interface as described in detail in the <a href=
"http://www.python.org/doc/current/lib/module-pickle.html">Python Library
Reference for pickle.</a> This interface involves the special methods
<tt>__getinitargs__</tt>, <tt>__getstate__</tt> and <tt>__setstate__</tt>
as described in the following. Note that Boost.Python is also fully
compatible with Python's cPickle module.</p>
<hr />
Pickle is a Python module for object serialization, also known
as persistence, marshalling, or flattening.
<h2>The Boost.Python Pickle Interface</h2>At the user level, the
Boost.Python pickle interface involves three special methods:
<p>
It is often necessary to save and restore the contents of an object to
a file. One approach to this problem is to write a pair of functions
that read and write data from a file in a special format. A powerful
alternative approach is to use Python's pickle module. Exploiting
Python's ability for introspection, the pickle module recursively
converts nearly arbitrary Python objects into a stream of bytes that
can be written to a file.
<dl>
<dt><strong><tt>__getinitargs__</tt></strong></dt>
<p>
The Boost Python Library supports the pickle module
through the interface as described in detail in the
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
>Python Library Reference for pickle.</a> This interface
involves the special methods <tt>__getinitargs__</tt>,
<tt>__getstate__</tt> and <tt>__setstate__</tt> as described
in the following. Note that Boost.Python is also fully compatible
with Python's cPickle module.
<dd>
When an instance of a Boost.Python extension class is pickled, the
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
This method must return a Python tuple (it is most convenient to use
a boost::python::tuple). When the instance is restored by the
unpickler, the contents of this tuple are used as the arguments for
the class constructor.
<hr>
<h2>The Boost.Python Pickle Interface</h2>
<p>If <tt>__getinitargs__</tt> is not defined, <tt>pickle.load</tt>
will call the constructor (<tt>__init__</tt>) without arguments;
i.e., the object must be default-constructible.</p>
</dd>
At the user level, the Boost.Python pickle interface involves three special
methods:
<dt><strong><tt>__getstate__</tt></strong></dt>
<dl>
<dt>
<strong><tt>__getinitargs__</tt></strong>
<dd>
When an instance of a Boost.Python extension class is pickled, the
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
This method must return a Python tuple (it is most convenient to use
a boost::python::tuple). When the instance is restored by the
unpickler, the contents of this tuple are used as the arguments for
the class constructor.
<dd>When an instance of a Boost.Python extension class is pickled, the
pickler tests if the instance has a <tt>__getstate__</tt> method. This
method should return a Python object representing the state of the
instance.</dd>
<p>
If <tt>__getinitargs__</tt> is not defined, <tt>pickle.load</tt>
will call the constructor (<tt>__init__</tt>) without arguments;
i.e., the object must be default-constructible.
<dt><strong><tt>__setstate__</tt></strong></dt>
<p>
<dt>
<strong><tt>__getstate__</tt></strong>
<dd>When an instance of a Boost.Python extension class is restored by
the unpickler (<tt>pickle.load</tt>), it is first constructed using the
result of <tt>__getinitargs__</tt> as arguments (see above).
Subsequently the unpickler tests if the new instance has a
<tt>__setstate__</tt> method. If so, this method is called with the
result of <tt>__getstate__</tt> (a Python object) as the argument.</dd>
</dl>The three special methods described above may be <tt>.def()</tt>'ed
individually by the user. However, Boost.Python provides an easy to use
high-level interface via the
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
must be defined as pairs. Use of this interface is demonstrated by the
following examples.
<hr />
<dd>
When an instance of a Boost.Python extension class is pickled, the
pickler tests if the instance has a <tt>__getstate__</tt> method.
This method should return a Python object representing the state of
the instance.
<h2>Examples</h2>There are three files in <tt>boost/libs/python/test</tt>
that show how to provide pickle support.
<hr />
<p>
<dt>
<strong><tt>__setstate__</tt></strong>
<h3><a href="../../test/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>The C++
class in this example can be fully restored by passing the appropriate
argument to the constructor. Therefore it is sufficient to define the
pickle interface method <tt>__getinitargs__</tt>. This is done in the
following way:
<dd>
When an instance of a Boost.Python extension class is restored by the
unpickler (<tt>pickle.load</tt>), it is first constructed using the
result of <tt>__getinitargs__</tt> as arguments (see above). Subsequently
the unpickler tests if the new instance has a <tt>__setstate__</tt>
method. If so, this method is called with the result of
<tt>__getstate__</tt> (a Python object) as the argument.
<ul>
<li>1. Definition of the C++ pickle function:
<pre>
</dl>
The three special methods described above may be <tt>.def()</tt>'ed
individually by the user. However, Boost.Python provides an easy to use
high-level interface via the
<strong><tt>boost::python::pickle_suite</tt></strong> class that also
enforces consistency: <tt>__getstate__</tt> and <tt>__setstate__</tt>
must be defined as pairs. Use of this interface is demonstrated by the
following examples.
<hr>
<h2>Examples</h2>
There are three files in
<tt>boost/libs/python/test</tt> that show how to
provide pickle support.
<hr>
<h3><a href="../../test/pickle1.cpp"><tt>pickle1.cpp</tt></a></h3>
The C++ class in this example can be fully restored by passing the
appropriate argument to the constructor. Therefore it is sufficient
to define the pickle interface method <tt>__getinitargs__</tt>.
This is done in the following way:
<ul>
<li>1. Definition of the C++ pickle function:
<pre>
struct world_pickle_suite : boost::python::pickle_suite
{
static
@@ -98,28 +117,26 @@
}
};
</pre>
</li>
<li>2. Establishing the Python binding:
<pre>
<li>2. Establishing the Python binding:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ...
.def_pickle(world_pickle_suite())
// ...
</pre>
</li>
</ul>
<hr />
</ul>
<h3><a href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>The C++
class in this example contains member data that cannot be restored by any
of the constructors. Therefore it is necessary to provide the
<tt>__getstate__</tt>/<tt>__setstate__</tt> pair of pickle interface
methods:
<hr>
<h3><a href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a></h3>
<ul>
<li>1. Definition of the C++ pickle functions:
<pre>
The C++ class in this example contains member data that cannot be
restored by any of the constructors. Therefore it is necessary to
provide the <tt>__getstate__</tt>/<tt>__setstate__</tt> pair of
pickle interface methods:
<ul>
<li>1. Definition of the C++ pickle functions:
<pre>
struct world_pickle_suite : boost::python::pickle_suite
{
static
@@ -144,76 +161,92 @@
}
};
</pre>
</li>
<li>2. Establishing the Python bindings for the entire suite:
<pre>
<li>2. Establishing the Python bindings for the entire suite:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ...
.def_pickle(world_pickle_suite())
// ...
</pre>
</li>
</ul>
</ul>
<p>For simplicity, the <tt>__dict__</tt> is not included in the result of
<tt>__getstate__</tt>. This is not generally recommended, but a valid
approach if it is anticipated that the object's <tt>__dict__</tt> will
always be empty. Note that the safety guard described below will catch
the cases where this assumption is violated.</p>
<hr />
<p>
For simplicity, the <tt>__dict__</tt> is not included in the result
of <tt>__getstate__</tt>. This is not generally recommended, but a
valid approach if it is anticipated that the object's
<tt>__dict__</tt> will always be empty. Note that the safety guard
described below will catch the cases where this assumption is violated.
<h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>This
example is similar to <a href=
"../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the object's
<tt>__dict__</tt> is included in the result of <tt>__getstate__</tt>.
This requires a little more code but is unavoidable if the object's
<tt>__dict__</tt> is not always empty.
<hr />
<hr>
<h3><a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a></h3>
<h2>Pitfall and Safety Guard</h2>The pickle protocol described above has
an important pitfall that the end user of a Boost.Python extension module
might not be aware of:
This example is similar to <a
href="../../test/pickle2.cpp"><tt>pickle2.cpp</tt></a>. However, the
object's <tt>__dict__</tt> is included in the result of
<tt>__getstate__</tt>. This requires a little more code but is
unavoidable if the object's <tt>__dict__</tt> is not always empty.
<p><strong><tt>__getstate__</tt> is defined and the instance's
<tt>__dict__</tt> is not empty.</strong></p>
<hr>
<h2>Pitfall and Safety Guard</h2>
<p>The author of a Boost.Python extension class might provide a
<tt>__getstate__</tt> method without considering the possibilities
that:</p>
The pickle protocol described above has an important pitfall that the
end user of a Boost.Python extension module might not be aware of:
<p>
<strong>
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt>
is not empty.
</strong>
<p>
<ul>
<li>his class is used in Python as a base class. Most likely the
<tt>__dict__</tt> of instances of the derived class needs to be pickled
in order to restore the instances correctly.</li>
The author of a Boost.Python extension class might provide a
<tt>__getstate__</tt> method without considering the possibilities
that:
<li>the user adds items to the instance's <tt>__dict__</tt> directly.
Again, the <tt>__dict__</tt> of the instance then needs to be
pickled.</li>
</ul>
<p>
<ul>
<li>
his class is used in Python as a base class. Most likely the
<tt>__dict__</tt> of instances of the derived class needs to be
pickled in order to restore the instances correctly.
<p>To alert the user to this highly unobvious problem, a safety guard is
provided. If <tt>__getstate__</tt> is defined and the instance's
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has an
attribute <tt>__getstate_manages_dict__</tt>. An exception is raised if
this attribute is not defined:</p>
<pre>
<p>
<li>
the user adds items to the instance's <tt>__dict__</tt> directly.
Again, the <tt>__dict__</tt> of the instance then needs to be
pickled.
</ul>
<p>
To alert the user to this highly unobvious problem, a safety guard is
provided. If <tt>__getstate__</tt> is defined and the instance's
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has
an attribute <tt>__getstate_manages_dict__</tt>. An exception is
raised if this attribute is not defined:
<pre>
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
</pre>To resolve this problem, it should first be established that the <tt>
__getstate__</tt> and <tt>__setstate__</tt> methods manage the
instances's <tt>__dict__</tt> correctly. Note that this can be done
either at the C++ or the Python level. Finally, the safety guard should
intentionally be overridden. E.g. in C++ (from <a href=
"../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>):
<pre>
</pre>
To resolve this problem, it should first be established that the
<tt>__getstate__</tt> and <tt>__setstate__</tt> methods manage the
instances's <tt>__dict__</tt> correctly. Note that this can be done
either at the C++ or the Python level. Finally, the safety guard
should intentionally be overridden. E.g. in C++ (from
<a href="../../test/pickle3.cpp"><tt>pickle3.cpp</tt></a>):
<pre>
struct world_pickle_suite : boost::python::pickle_suite
{
// ...
static bool getstate_manages_dict() { return true; }
};
</pre>Alternatively in Python:
<pre>
</pre>
Alternatively in Python:
<pre>
import your_bpl_module
class your_class(your_bpl_module.your_class):
__getstate_manages_dict__ = 1
@@ -222,41 +255,54 @@
def __setstate__(self, state):
# your code here
</pre>
<hr />
<h2>Practical Advice</h2>
<hr>
<h2>Practical Advice</h2>
<ul>
<li>In Boost.Python extension modules with many extension classes,
providing complete pickle support for all classes would be a
significant overhead. In general complete pickle support should only be
implemented for extension classes that will eventually be pickled.</li>
<ul>
<li>
In Boost.Python extension modules with many extension classes,
providing complete pickle support for all classes would be a
significant overhead. In general complete pickle support should
only be implemented for extension classes that will eventually
be pickled.
<li>Avoid using <tt>__getstate__</tt> if the instance can also be
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
avoids the pitfall described above.</li>
<p>
<li>
Avoid using <tt>__getstate__</tt> if the instance can also be
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
avoids the pitfall described above.
<li>If <tt>__getstate__</tt> is required, include the instance's
<tt>__dict__</tt> in the Python object that is returned.</li>
</ul>
<hr />
<p>
<li>
If <tt>__getstate__</tt> is required, include the instance's
<tt>__dict__</tt> in the Python object that is returned.
<h2>Light-weight alternative: pickle support implemented in Python</h2>
</ul>
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>The
<tt>pickle4.cpp</tt> example demonstrates an alternative technique for
implementing pickle support. First we direct Boost.Python via the
<tt>class_::enable_pickling()</tt> member function to define only the
basic attributes required for pickling:
<pre>
<hr>
<h2>Light-weight alternative: pickle support implemented in Python</h2>
<h3><a href="../../test/pickle4.cpp"><tt>pickle4.cpp</tt></a></h3>
The <tt>pickle4.cpp</tt> example demonstrates an alternative technique
for implementing pickle support. First we direct Boost.Python via
the <tt>class_::enable_pickling()</tt> member function to define only
the basic attributes required for pickling:
<pre>
class_&lt;world&gt;("world", args&lt;const std::string&amp;&gt;())
// ...
.enable_pickling()
// ...
</pre>This enables the standard Python pickle interface as described in the
Python documentation. By "injecting" a <tt>__getinitargs__</tt> method into
the definition of the wrapped class we make all instances pickleable:
<pre>
</pre>
This enables the standard Python pickle interface as described
in the Python documentation. By &quot;injecting&quot; a
<tt>__getinitargs__</tt> method into the definition of the wrapped
class we make all instances pickleable:
<pre>
# import the wrapped world class
from pickle4_ext import world
@@ -266,15 +312,18 @@ the definition of the wrapped class we make all instances pickleable:
# now inject __getinitargs__ (Python is a dynamic language!)
world.__getinitargs__ = world_getinitargs
</pre>See also the <a href=
"../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python">
tutorial section</a> on injecting additional methods from Python.
<hr />
© Copyright Ralf W. Grosse-Kunstleve 2001-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)
</pre>
<p>Updated: Feb 2004.</p>
</div>
</body>
</html>
See also the
<a href="../tutorial/doc/html/python/techniques.html#python.extending_wrapped_objects_in_python"
>tutorial section</a> on injecting additional methods from Python.
<hr>
&copy; Copyright Ralf W. Grosse-Kunstleve 2001-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)
<p>
Updated: Feb 2004.
</div>

View File

@@ -38,10 +38,7 @@ namespace boost { namespace python {
# endif // CALL_DWA2002411_HPP
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call.hpp)
@@ -79,5 +76,4 @@ call(PyObject* callable
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -37,10 +37,7 @@ namespace boost { namespace python {
# endif // CALL_METHOD_DWA2002411_HPP
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
@@ -79,5 +76,4 @@ call_method(PyObject* self, char const* name
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif // BOOST_PP_IS_ITERATING

View File

@@ -86,10 +86,7 @@ result(X const&, short = 0) { return 0; }
# endif // RESULT_DWA2002521_HPP
/* --------------- function pointers --------------- */
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, result.hpp(function pointers))
@@ -131,5 +128,4 @@ boost::type<R>* result(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q, int = 0)
# undef N
# undef Q
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -37,10 +37,7 @@ T& (* target(R (T::*)) )() { return 0; }
# endif // TARGET_DWA2002521_HPP
/* --------------- function pointers --------------- */
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers))
@@ -82,5 +79,4 @@ T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )()
# undef N
# undef Q
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -47,10 +47,7 @@ template <int nargs> struct make_holder;
# endif // MAKE_HOLDER_DWA20011215_HPP
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, make_holder.hpp)
@@ -105,5 +102,4 @@ struct make_holder<N>
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -170,10 +170,7 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool
# endif // POINTER_HOLDER_DWA20011215_HPP
/* --------------- pointer_holder --------------- */
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, pointer_holder.hpp)
@@ -215,5 +212,4 @@ void* pointer_holder_back_reference<Pointer, Value>::holds(type_info dst_t, bool
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -117,10 +117,7 @@ void* value_holder_back_reference<Value,Held>::holds(
// --------------- value_holder ---------------
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
# line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder))
@@ -166,5 +163,4 @@ void* value_holder_back_reference<Value,Held>::holds(
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif

View File

@@ -17,7 +17,6 @@ struct const_attribute_policies
{
typedef char const* key_type;
static object get(object const& target, char const* key);
static object get(object const& target, object const& key);
};
struct attribute_policies : const_attribute_policies
@@ -26,18 +25,6 @@ struct attribute_policies : const_attribute_policies
static void del(object const&target, char const* key);
};
struct const_objattribute_policies
{
typedef object const key_type;
static object get(object const& target, object const& key);
};
struct objattribute_policies : const_objattribute_policies
{
static object const& set(object const& target, object const& key, object const& value);
static void del(object const&target, object const& key);
};
//
// implementation
//
@@ -55,30 +42,11 @@ inline const_object_attribute object_operators<U>::attr(char const* name) const
return const_object_attribute(x, name);
}
template <class U>
inline object_objattribute object_operators<U>::attr(object const& name)
{
object_cref2 x = *static_cast<U*>(this);
return object_objattribute(x, name);
}
template <class U>
inline const_object_objattribute object_operators<U>::attr(object const& name) const
{
object_cref2 x = *static_cast<U const*>(this);
return const_object_objattribute(x, name);
}
inline object const_attribute_policies::get(object const& target, char const* key)
{
return python::getattr(target, key);
}
inline object const_objattribute_policies::get(object const& target, object const& key)
{
return python::getattr(target, key);
}
inline object const& attribute_policies::set(
object const& target
, char const* key
@@ -88,15 +56,6 @@ inline object const& attribute_policies::set(
return value;
}
inline object const& objattribute_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setattr(target, key, value);
return value;
}
inline void attribute_policies::del(
object const& target
, char const* key)
@@ -104,13 +63,6 @@ inline void attribute_policies::del(
python::delattr(target, key);
}
inline void objattribute_policies::del(
object const& target
, object const& key)
{
python::delattr(target, key);
}
}}} // namespace boost::python::api
#endif // OBJECT_ATTRIBUTES_DWA2002615_HPP

View File

@@ -42,12 +42,6 @@
namespace boost { namespace python {
namespace detail
{
class kwds_proxy;
class args_proxy;
}
namespace converter
{
template <class T> struct arg_to_python;
@@ -65,8 +59,6 @@ namespace api
struct const_attribute_policies;
struct attribute_policies;
struct const_objattribute_policies;
struct objattribute_policies;
struct const_item_policies;
struct item_policies;
struct const_slice_policies;
@@ -75,8 +67,6 @@ namespace api
typedef proxy<const_attribute_policies> const_object_attribute;
typedef proxy<attribute_policies> object_attribute;
typedef proxy<const_objattribute_policies> const_object_objattribute;
typedef proxy<objattribute_policies> object_objattribute;
typedef proxy<const_item_policies> const_object_item;
typedef proxy<item_policies> object_item;
typedef proxy<const_slice_policies> const_object_slice;
@@ -108,11 +98,6 @@ namespace api
# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
# include BOOST_PP_ITERATE()
detail::args_proxy operator* () const;
object operator()(detail::args_proxy const &args) const;
object operator()(detail::args_proxy const &args,
detail::kwds_proxy const &kwds) const;
// truth value testing
//
@@ -123,8 +108,6 @@ namespace api
//
const_object_attribute attr(char const*) const;
object_attribute attr(char const*);
const_object_objattribute attr(object const&) const;
object_objattribute attr(object const&);
// item access
//
@@ -230,11 +213,11 @@ namespace api
inline object_base(object_base const&);
inline object_base(PyObject* ptr);
inline object_base& operator=(object_base const& rhs);
inline ~object_base();
object_base& operator=(object_base const& rhs);
~object_base();
// Underlying object access -- returns a borrowed reference
inline PyObject* ptr() const;
PyObject* ptr() const;
private:
PyObject* m_ptr;
@@ -404,7 +387,7 @@ namespace api
static PyObject*
get(T const& x, U)
{
return python::incref(get_managed_object(x, boost::python::tag));
return python::incref(get_managed_object(x, tag));
}
};
@@ -427,62 +410,6 @@ template <class T> struct extract;
// implementation
//
namespace detail
{
class call_proxy
{
public:
call_proxy(object target) : m_target(target) {}
operator object() const { return m_target;}
private:
object m_target;
};
class kwds_proxy : public call_proxy
{
public:
kwds_proxy(object o = object()) : call_proxy(o) {}
};
class args_proxy : public call_proxy
{
public:
args_proxy(object o) : call_proxy(o) {}
kwds_proxy operator* () const { return kwds_proxy(*this);}
};
}
template <typename U>
detail::args_proxy api::object_operators<U>::operator* () const
{
object_cref2 x = *static_cast<U const*>(this);
return boost::python::detail::args_proxy(x);
}
template <typename U>
object api::object_operators<U>::operator()(detail::args_proxy const &args) const
{
U const& self = *static_cast<U const*>(this);
PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
args.operator object().ptr(),
0);
return object(boost::python::detail::new_reference(result));
}
template <typename U>
object api::object_operators<U>::operator()(detail::args_proxy const &args,
detail::kwds_proxy const &kwds) const
{
U const& self = *static_cast<U const*>(this);
PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
args.operator object().ptr(),
kwds.operator object().ptr());
return object(boost::python::detail::new_reference(result));
}
inline object::object()
: object_base(python::incref(Py_None))
{}

View File

@@ -8,7 +8,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
// Based on boost/ref.hpp, thus:
// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 1999, 2000 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001 Peter Dimov
# if _MSC_VER+0 >= 1020

View File

@@ -113,10 +113,7 @@ struct most_derived
# endif // SIGNATURE_JDG20020813_HPP
// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
#elif BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)
# define N BOOST_PP_ITERATION()
@@ -179,5 +176,4 @@ get_signature(
# undef Q
# undef N
#endif // BOOST_PP_ITERATION_DEPTH()
#endif // !defined(BOOST_PP_IS_ITERATING)

View File

@@ -11,7 +11,6 @@
# include <boost/operators.hpp>
# include <typeinfo>
# include <cstring>
# include <ostream>
# include <boost/static_assert.hpp>
# include <boost/detail/workaround.hpp>
# include <boost/type_traits/same_traits.hpp>

View File

@@ -68,9 +68,8 @@ struct with_custodian_and_ward : BasePolicy_
bool result = BasePolicy_::precall(args_);
if (!result) {
if (!result)
Py_DECREF(life_support);
}
return result;
}

View File

@@ -1,3 +0,0 @@
boost_module(python DEPENDS graph numeric)
# numeric is there because of boost/cast.hpp from libs/python/src/errors.cpp:11

View File

@@ -1,64 +0,0 @@
if (PYTHON_DEBUG_LIBRARIES AND BUILD_BOOST_PYTHON)
# We have detected that there might be Python debug libraries
# available, but check for ourselves whether this is true by trying
# to compile/link a program against them.
set(CMAKE_REQUIRED_DEFINITIONS "-DBOOST_DEBUG_PYTHON -DPy_DEBUG")
get_directory_property(CMAKE_REQUIRED_INCLUDES INCLUDE_DIRECTORIES)
set(CMAKE_REQUIRED_LIBRARIES ${PYTHON_DEBUG_LIBRARIES})
set(CHECK_PYDEBUG_SOURCE
"#include <boost/python/object.hpp>")
check_cxx_source_compiles(
"#include <boost/python/object.hpp>
void check(PyObject *obj) { Py_INCREF(obj); } int main() { }"
PYDEBUG_CAN_BUILD)
# Setup an option to enable/disable building variants with Python
# debugging. If we were able to link against the debug libraries,
# default to ON; otherwise, default to OFF.
option(BUILD_PYTHON_DEBUG
"Build an additional Boost.Python library with Python debugging enabled"
${PYDEBUG_CAN_BUILD})
endif (PYTHON_DEBUG_LIBRARIES AND BUILD_BOOST_PYTHON)
# Always build the non-debug variants of the boost_python library
set(BUILD_PYTHON_NODEBUG ON)
boost_add_library(boost_python
numeric.cpp
list.cpp
long.cpp
dict.cpp
tuple.cpp
str.cpp
slice.cpp
converter/from_python.cpp
converter/registry.cpp
converter/type_id.cpp
object/enum.cpp
object/class.cpp
object/function.cpp
object/inheritance.cpp
object/life_support.cpp
object/pickle_support.cpp
errors.cpp
module.cpp
converter/builtin_converters.cpp
converter/arg_to_python_base.cpp
object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp
object_operators.cpp
wrapper.cpp
import.cpp
exec.cpp
object/function_doc_signature.cpp
STATIC_COMPILE_FLAGS "-DBOOST_PYTHON_SOURCE -DBOOST_PYTHON_STATIC_LIB"
SHARED_COMPILE_FLAGS "-DBOOST_PYTHON_SOURCE"
PYTHON_NODEBUG_LINK_LIBS "${PYTHON_LIBRARIES}"
# Support for Python debugging
EXTRA_VARIANTS PYTHON_NODEBUG:PYTHON_DEBUG
PYTHON_DEBUG_COMPILE_FLAGS "-DBOOST_DEBUG_PYTHON -DPy_DEBUG"
PYTHON_DEBUG_LINK_LIBS "${PYTHON_DEBUG_LIBRARIES}"
)

View File

@@ -1,194 +0,0 @@
macro(bpl_test TESTNAME)
parse_arguments(BPL_TEST
"ARGS"
""
${ARGN})
# Determine the Python and C++ source files for this test
if (BPL_TEST_DEFAULT_ARGS)
# First argument is the Python source we will run, the rest are
# either extra Python sources we're dependent on or C++ files from
# which we will build extension modules.
car(BPL_TEST_PYSOURCE ${BPL_TEST_DEFAULT_ARGS})
cdr(BPL_TEST_DEFAULT_ARGS ${BPL_TEST_DEFAULT_ARGS})
get_filename_component(BPL_TEST_PYBASE ${BPL_TEST_PYSOURCE} NAME_WE)
foreach(SRC ${BPL_TEST_DEFAULT_ARGS})
get_filename_component(BPL_SRC_EXT ${SRC} EXT)
if (BPL_SRC_EXT STREQUAL ".cpp")
# Build a Python extension module from this source file
get_filename_component(BPL_SRC_NAME ${SRC} NAME_WE)
if(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
boost_python_extension(${BPL_SRC_NAME}_ext ${SRC})
else(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
boost_python_extension(${BPL_SRC_NAME} ${SRC})
endif(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
endif (BPL_SRC_EXT STREQUAL ".cpp")
endforeach(SRC ${BPL_TEST_DEFAULT_ARGS})
else (BPL_TEST_DEFAULT_ARGS)
set(BPL_TEST_PYSOURCE "${TESTNAME}.py")
# Build a Python extension module from this source file
boost_python_extension(${TESTNAME}_ext "${TESTNAME}.cpp")
endif(BPL_TEST_DEFAULT_ARGS)
# We'll need the full patch to run the Python test
set(BPL_TEST_PYSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${BPL_TEST_PYSOURCE})
# Run the test itself
file(TO_NATIVE_PATH "${LIBRARY_OUTPUT_PATH}" PYTHONPATH)
if(WIN32 AND NOT UNIX)
string(REPLACE "\\" "\\\\" PYTHONPATH "${PYTHONPATH}")
endif(WIN32 AND NOT UNIX)
add_test("${PROJECT_NAME}::${TESTNAME}"
${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/pyrun.py"
"${PYTHONPATH}"
${BPL_TEST_PYSOURCE} ${BPL_TEST_ARGS})
endmacro(bpl_test)
macro(py_run TESTNAME)
boost_test_run(${TESTNAME}
${TESTNAME}.cpp
DEPENDS boost_python STATIC
LINK_LIBS ${PYTHON_LIBRARIES})
endmacro(py_run)
boost_test_run(exec
DEPENDS boost_python STATIC
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/exec.py"
LINK_LIBS ${PYTHON_LIBRARIES})
boost_test_run(exec-dynamic
exec.cpp
ARGS "${CMAKE_CURRENT_SOURCE_DIR}/exec.py"
DEPENDS boost_python SHARED
LINK_LIBS ${PYTHON_LIBRARIES})
bpl_test(crossmod_exception
crossmod_exception.py crossmod_exception_a.cpp crossmod_exception_b.cpp)
bpl_test(injected)
bpl_test(properties)
bpl_test(return_arg)
bpl_test(staticmethod)
bpl_test(shared_ptr)
bpl_test(andreas_beyer)
bpl_test(polymorphism)
bpl_test(polymorphism2)
bpl_test(wrapper_held_type)
bpl_test(polymorphism2_auto_ptr)
bpl_test(auto_ptr)
bpl_test(minimal)
bpl_test(args)
bpl_test(raw_ctor)
bpl_test(numpy numpy.py printer.py numeric_tests.py numarray_tests.py numpy.cpp)
bpl_test(enum)
bpl_test(exception_translator)
bpl_test(pearu1 test_cltree.py cltree.cpp)
bpl_test(try newtest.py m1.cpp m2.cpp)
bpl_test(const_argument)
bpl_test(keywords keywords_test.py keywords.cpp)
boost_python_extension(builtin_converters_ext test_builtin_converters.cpp)
bpl_test(builtin_converters test_builtin_converters.py builtin_converters_ext)
bpl_test(test_pointer_adoption)
bpl_test(operators)
bpl_test(callbacks)
bpl_test(defaults)
bpl_test(object)
bpl_test(list)
bpl_test(long)
bpl_test(dict)
bpl_test(tuple)
bpl_test(str)
bpl_test(slice)
bpl_test(virtual_functions)
bpl_test(back_reference)
bpl_test(implicit)
bpl_test(data_members)
bpl_test(ben_scott1)
bpl_test(bienstman1)
bpl_test(bienstman2)
bpl_test(bienstman3)
bpl_test(multi_arg_constructor)
# TODO: A bug in the Win32 intel compilers causes compilation of one
# of our tests to take forever when debug symbols are
# enabled. This rule turns them off when added to the requirements
# section
# <toolset>intel-win:<debug-symbols>off
bpl_test(iterator iterator.py iterator.cpp input_iterator.cpp)
bpl_test(stl_iterator stl_iterator.py stl_iterator.cpp)
bpl_test(extract)
bpl_test (crossmod_opaque
crossmod_opaque.py crossmod_opaque_a.cpp crossmod_opaque_b.cpp)
bpl_test(opaque)
bpl_test(voidptr)
bpl_test(pickle1)
bpl_test(pickle2)
bpl_test(pickle3)
bpl_test(pickle4)
bpl_test(nested)
bpl_test(docstring)
bpl_test(vector_indexing_suite)
bpl_test(pointer_vector)
# TODO: Turn off this test on HP CXX, as the test hangs when executing.
# Whenever the cause for the failure of the polymorphism test is found
# and fixed, this should be retested.
# <toolset>hp_cxx:<build>no
boost_python_extension(map_indexing_suite_ext
map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp)
bpl_test(map_indexing_suite
map_indexing_suite.py map_indexing_suite_ext)
# --- unit tests of library components ---
boost_test_compile(indirect_traits_test)
boost_test_run(destroy_test)
py_run(pointer_type_id_test)
py_run(bases)
boost_test_run(if_else)
py_run(pointee)
boost_test_run(result)
boost_test_compile(string_literal)
boost_test_compile(borrowed)
boost_test_compile(object_manager)
boost_test_compile(copy_ctor_mutates_rhs)
py_run(upcast)
boost_test_compile(select_holder)
boost_test_run(select_from_python_test
select_from_python_test.cpp ../src/converter/type_id.cpp
COMPILE_FLAGS "-DBOOST_PYTHON_STATIC_LIB"
LINK_LIBS ${PYTHON_LIBRARIES})
boost_test_compile(select_arg_to_python_test)
boost_test_compile_fail(raw_pyobject_fail1)
boost_test_compile_fail(raw_pyobject_fail2)
boost_test_compile_fail(as_to_python_function)
boost_test_compile_fail(object_fail1)

View File

@@ -13,7 +13,6 @@
# endif
# ifdef _MSC_VER
# include <eh.h> // for _set_se_translator()
# pragma warning(push)
# pragma warning(disable:4297)
# pragma warning(disable:4535)

View File

@@ -38,61 +38,26 @@ object obj_getattr(object x, char const* name)
return x.attr(name);
}
object obj_objgetattr(object x, object const& name)
{
return x.attr(name);
}
object obj_const_getattr(object const& x, char const* name)
{
return x.attr(name);
}
object obj_const_objgetattr(object const& x, object const& name)
{
return x.attr(name);
}
void obj_setattr(object x, char const* name, object value)
{
x.attr(name) = value;
}
void obj_objsetattr(object x, object const& name, object value)
{
x.attr(name) = value;
}
void obj_setattr42(object x, char const* name)
{
x.attr(name) = 42;
}
void obj_objsetattr42(object x, object const& name)
{
x.attr(name) = 42;
}
void obj_moveattr(object& x, char const* src, char const* dst)
{
x.attr(dst) = x.attr(src);
}
void obj_objmoveattr(object& x, object const& src, object const& dst)
{
x.attr(dst) = x.attr(src);
}
void obj_delattr(object x, char const* name)
{
x.attr(name).del();
}
void obj_objdelattr(object x, object const& name)
{
x.attr(name).del();
}
object obj_getitem(object x, object key)
{
return x[key];
@@ -143,21 +108,11 @@ bool test_attr(object y, char* name)
return y.attr(name);
}
bool test_objattr(object y, object& name)
{
return y.attr(name);
}
bool test_not_attr(object y, char* name)
{
return !y.attr(name);
}
bool test_not_objattr(object y, object& name)
{
return !y.attr(name);
}
bool test_item(object y, object key)
{
return y[key];
@@ -187,11 +142,6 @@ bool check_string_slice()
return s.slice(2,-1).slice(1,-1) == "lo, wor";
}
object test_call(object c, object args, object kwds)
{
return c(*args, **kwds);
}
bool check_binary_operators()
{
int y;
@@ -351,17 +301,11 @@ BOOST_PYTHON_MODULE(object_ext)
def("number", number);
def("obj_getattr", obj_getattr);
def("obj_objgetattr", obj_objgetattr);
def("obj_const_getattr", obj_const_getattr);
def("obj_const_objgetattr", obj_const_objgetattr);
def("obj_setattr", obj_setattr);
def("obj_objsetattr", obj_objsetattr);
def("obj_setattr42", obj_setattr42);
def("obj_objsetattr42", obj_objsetattr42);
def("obj_moveattr", obj_moveattr);
def("obj_objmoveattr", obj_objmoveattr);
def("obj_delattr", obj_delattr);
def("obj_objdelattr", obj_objdelattr);
def("obj_getitem", obj_getitem);
def("obj_getitem3", obj_getitem);
@@ -375,14 +319,11 @@ BOOST_PYTHON_MODULE(object_ext)
def("test_not", test_not);
def("test_attr", test_attr);
def("test_objattr", test_objattr);
def("test_not_attr", test_not_attr);
def("test_not_objattr", test_not_objattr);
def("test_item", test_item);
def("test_not_item", test_not_item);
def("test_call", test_call);
def("check_binary_operators", check_binary_operators);
def("check_inplace", check_inplace);
def("check_string_slice", check_string_slice);

View File

@@ -34,68 +34,29 @@
>>> try: obj_getattr(x, 'foo')
... except AttributeError: pass
... else: print 'expected an exception'
>>> try: obj_objgetattr(x, 'objfoo')
... except AttributeError: pass
... else: print 'expected an exception'
>>> obj_setattr(x, 'foo', 1)
>>> x.foo
1
>>> obj_objsetattr(x, 'objfoo', 1)
>>> try:obj_objsetattr(x, 1)
... except TypeError: pass
... else: print 'expected an exception'
>>> x.objfoo
1
>>> obj_getattr(x, 'foo')
1
>>> obj_objgetattr(x, 'objfoo')
1
>>> try:obj_objgetattr(x, 1)
... except TypeError: pass
... else: print 'expected an exception'
>>> obj_const_getattr(x, 'foo')
1
>>> obj_const_objgetattr(x, 'objfoo')
1
>>> obj_setattr42(x, 'foo')
>>> x.foo
42
>>> obj_objsetattr42(x, 'objfoo')
>>> x.objfoo
42
>>> obj_moveattr(x, 'foo', 'bar')
>>> x.bar
42
>>> obj_objmoveattr(x, 'objfoo', 'objbar')
>>> x.objbar
42
>>> test_attr(x, 'foo')
1
>>> test_objattr(x, 'objfoo')
1
>>> test_not_attr(x, 'foo')
0
>>> test_not_objattr(x, 'objfoo')
0
>>> x.foo = None
>>> test_attr(x, 'foo')
0
>>> x.objfoo = None
>>> test_objattr(x, 'objfoo')
0
>>> test_not_attr(x, 'foo')
1
>>> test_not_objattr(x, 'objfoo')
1
>>> obj_delattr(x, 'foo')
>>> obj_objdelattr(x, 'objfoo')
>>> try:obj_delattr(x, 'foo')
... except AttributeError: pass
... else: print 'expected an exception'
>>> try:obj_objdelattr(x, 'objfoo')
... except AttributeError: pass
... else: print 'expected an exception'
Items
@@ -134,12 +95,7 @@
Operators
>>> def print_args(*args, **kwds):
... print args, kwds
>>> test_call(print_args, (0, 1, 2, 3), {'a':'A'})
(0, 1, 2, 3) {'a': 'A'}
>>> assert check_binary_operators()
>>> class X: pass