From e80224b1adea5eb0d2c92f78cf51dd29e4100d1c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 17 Aug 2009 21:01:18 +0000 Subject: [PATCH] boost/python, libs/python: all changes from trunk merged into branches/release (without any manual modifications) Commands used: svn merge https://svn.boost.org/svn/boost/branches/release/boost/python https://svn.boost.org/svn/boost/trunk/boost/python /net/chevy/raid1/rwgk/boost_release/merge_attempt/boost/boost/python svn merge https://svn.boost.org/svn/boost/branches/release/libs/python https://svn.boost.org/svn/boost/trunk/libs/python /net/chevy/raid1/rwgk/boost_release/merge_attempt/boost/libs/python svn, version 1.6.4 (r38063) compiled Aug 17 2009, 13:31:03 [SVN r55629] --- doc/tutorial/doc/html/index.html | 21 ++-- doc/tutorial/doc/html/python/embedding.html | 51 ++++---- doc/tutorial/doc/html/python/exception.html | 12 +- doc/tutorial/doc/html/python/exposing.html | 115 ++++++------------ doc/tutorial/doc/html/python/functions.html | 112 ++++++----------- doc/tutorial/doc/html/python/hello.html | 15 ++- doc/tutorial/doc/html/python/iterators.html | 27 ++-- doc/tutorial/doc/html/python/object.html | 65 ++++------ doc/tutorial/doc/html/python/techniques.html | 66 ++++------ doc/tutorial/doc/tutorial.qbk | 12 +- doc/v2/object.html | 24 ++++ example/tutorial/Jamroot | 9 ++ include/boost/python/call.hpp | 6 +- include/boost/python/call_method.hpp | 6 +- .../converter/rvalue_from_python_data.hpp | 4 +- .../converter/shared_ptr_from_python.hpp | 10 +- include/boost/python/data_members.hpp | 6 +- .../boost/python/detail/decorated_type_id.hpp | 4 +- include/boost/python/detail/result.hpp | 6 +- include/boost/python/detail/target.hpp | 6 +- .../boost/python/object/class_metadata.hpp | 2 +- include/boost/python/object/make_holder.hpp | 6 +- .../boost/python/object/pointer_holder.hpp | 15 ++- include/boost/python/object/value_holder.hpp | 6 +- include/boost/python/object_core.hpp | 75 +++++++++++- include/boost/python/object_protocol.hpp | 18 +-- include/boost/python/object_slices.hpp | 22 ++-- include/boost/python/signature.hpp | 6 +- src/converter/builtin_converters.cpp | 44 +++++-- src/dict.cpp | 2 +- src/exec.cpp | 48 +++++++- src/list.cpp | 2 +- src/long.cpp | 6 +- src/object/class.cpp | 45 ++++--- src/object/enum.cpp | 34 +++--- src/object/function.cpp | 23 ++-- src/object/function_doc_signature.cpp | 6 +- src/object/inheritance.cpp | 2 +- src/object/life_support.cpp | 2 +- src/object/stl_iterator.cpp | 6 + src/str.cpp | 9 +- src/tuple.cpp | 2 +- test/CMakeLists.txt | 29 ++++- test/Jamfile.v2 | 6 +- test/andreas_beyer.cpp | 4 +- test/back_reference.cpp | 2 +- test/callbacks.cpp | 2 +- test/complicated.hpp | 6 +- test/enable_shared_from_this.cpp | 48 ++++++++ test/enable_shared_from_this.py | 26 ++++ test/enum.cpp | 3 +- test/enum.py | 20 ++- test/exec.cpp | 2 +- test/m1.cpp | 6 +- test/object.cpp | 6 + test/object.py | 7 +- test/pickle1.cpp | 4 +- test/pickle2.cpp | 4 +- test/pickle3.cpp | 4 +- test/pickle4.cpp | 4 +- test/slice.cpp | 6 +- test/staticmethod.cpp | 2 +- test/stl_iterator.py | 10 ++ test/test_builtin_converters.cpp | 16 ++- test/test_builtin_converters.py | 57 +++++++-- test/test_class.hpp | 2 +- test/test_overload_resolution.cpp | 53 ++++++++ test/test_pointer_adoption.cpp | 2 +- test/virtual_functions.cpp | 2 +- 69 files changed, 822 insertions(+), 469 deletions(-) mode change 100755 => 100644 example/tutorial/Jamroot mode change 100755 => 100644 include/boost/python/detail/decorated_type_id.hpp mode change 100755 => 100644 include/boost/python/detail/result.hpp mode change 100755 => 100644 include/boost/python/object/class_metadata.hpp mode change 100755 => 100644 include/boost/python/object_protocol.hpp mode change 100755 => 100644 src/object/function_doc_signature.cpp mode change 100755 => 100644 src/object/stl_iterator.cpp mode change 100755 => 100644 test/andreas_beyer.cpp create mode 100644 test/enable_shared_from_this.cpp create mode 100755 test/enable_shared_from_this.py create mode 100644 test/test_overload_resolution.cpp diff --git a/doc/tutorial/doc/html/index.html b/doc/tutorial/doc/html/index.html index 807dc2ce..e85d5d3a 100644 --- a/doc/tutorial/doc/html/index.html +++ b/doc/tutorial/doc/html/index.html @@ -10,10 +10,10 @@ - + - - + +
Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

@@ -31,7 +31,7 @@
-

+

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 ) @@ -94,15 +94,14 @@ (IDL).

- + Hello World

Following C/C++ tradition, let's start with the "hello, world". A C++ Function:

-
-char const* greet()
+
char const* greet()
 {
    return "hello, world";
 }
@@ -110,8 +109,7 @@
 

can be exposed to Python by writing a Boost.Python wrapper:

-
-#include <boost/python.hpp>
+
#include <boost/python.hpp>
 
 BOOST_PYTHON_MODULE(hello_ext)
 {
@@ -125,8 +123,7 @@
     

-
->>> import hello_ext
+
>>> import hello_ext
 >>> print hello.greet()
 hello, world
 
@@ -145,7 +142,7 @@
- +

Last revised: March 24, 2008 at 23:09:39 GMT

Last revised: November 22, 2008 at 03:24:11 GMT


diff --git a/doc/tutorial/doc/html/python/embedding.html b/doc/tutorial/doc/html/python/embedding.html index a402795f..a337e6c6 100644 --- a/doc/tutorial/doc/html/python/embedding.html +++ b/doc/tutorial/doc/html/python/embedding.html @@ -12,10 +12,10 @@ - + - - + +
Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

@@ -40,7 +40,7 @@ Python/C API at all. So stay tuned... smiley

- + Building embedded programs

@@ -82,7 +82,7 @@ exe embedded_program # name of the executable <find-library>$(PYTHON_EMBEDDED_LIBRARY) ;

- + Getting started

@@ -130,23 +130,22 @@ exe embedded_program # name of the executable Using the interpreter

As you probably already know, objects in Python are reference-counted. Naturally, - the PyObjects of the Python/C API are also reference-counted. + the PyObjects of the Python C API are also reference-counted. There is a difference however. While the reference-counting is fully automatic - in Python, the PythonC 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 + in Python, the Python C API requires you to do it by + hand. This is messy and especially hard to get right in the presence of C++ exceptions. Fortunately Boost.Python provides the handle and object class templates to automate the process.

- + Running Python code

Boost.python provides three related functions to run Python code from C++.

-
-object eval(str expression, object globals = object(), object locals = object())
+
object eval(str expression, object globals = object(), object locals = object())
 object exec(str code, object globals = object(), object locals = object())
 object exec_file(str filename, object globals = object(), object locals = object())
 
@@ -165,8 +164,7 @@ exe embedded_program # name of the executable

Boost.python provides a function to import a module:

-
-object import(str name)
+
object import(str name)
 

import imports a python module (potentially loading it into the running process @@ -176,8 +174,7 @@ exe embedded_program # name of the executable Let's import the _main_ module and run some Python code in its namespace:

-
-object main_module = import("__main__");
+
object main_module = import("__main__");
 object main_namespace = main_module.attr("__dict__");
 
 object ignored = exec("hello = file('hello.txt', 'w')\n"
@@ -190,7 +187,7 @@ exe embedded_program # name of the executable
         a phrase that is well-known in programming circles.
       

- + Manipulating Python objects

@@ -200,8 +197,7 @@ exe embedded_program # name of the executable derivatives. We've already seen that they can be constructed from a handle. The following examples should further illustrate this fact:

-
-object main_module = import("__main__");
+
object main_module = import("__main__");
 object main_namespace = main_module.attr("__dict__");
 object ignored = exec("result = 5 ** 2", main_namespace);
 int five_squared = extract<int>(main_namespace["result"]);
@@ -212,20 +208,18 @@ exe embedded_program # name of the executable
         this variable from the dictionary. Another way to achieve the same result
         is to use eval instead, which returns the result directly:
       

-
-object result = eval("5 ** 2");
+
object result = eval("5 ** 2");
 int five_squared = extract<int>(result);
 

- + Exception handling

If an exception occurs in the evaluation of the python expression, error_already_set is thrown:

-
-try
+
try
 {
     object result = eval("5/0");
     // execution will never get here:
@@ -240,14 +234,13 @@ exe embedded_program # name of the executable
         The error_already_set exception class doesn't carry any
         information in itself. To find out more about the Python exception that occurred,
         you need to use the exception
-        handling functions of the PythonC API in your catch-statement.
-        This can be as simple as calling [@http:/www.python.org/doc/api/exceptionHandling.html#l2h-70
-        PyErr_Print()] to print the exception's traceback to the console, or comparing
-        the type of the exception with those of the standard
+        handling functions of the Python C API in your catch-statement. This
+        can be as simple as calling PyErr_Print()
+        to print the exception's traceback to the console, or comparing the type
+        of the exception with those of the standard
         exceptions:
       

-
-catch(error_already_set const &)
+
catch(error_already_set const &)
 {
     if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
     {
diff --git a/doc/tutorial/doc/html/python/exception.html b/doc/tutorial/doc/html/python/exception.html
index 7a9b5c74..70b96739 100644
--- a/doc/tutorial/doc/html/python/exception.html
+++ b/doc/tutorial/doc/html/python/exception.html
@@ -12,10 +12,10 @@
 
 
-
+
-
-
+
+
Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

@@ -30,14 +30,12 @@ is the point where C++ meets Python. Boost.Python provides a default exception handler that translates selected standard exceptions, then gives up:

-
-raise RuntimeError, 'unidentifiable C++ Exception'
+
raise RuntimeError, 'unidentifiable C++ Exception'
 

Users may provide custom translation. Here's an example:

-
-struct PodBayDoorException;
+
struct PodBayDoorException;
 void translator(PodBayDoorException const& x) {
     PyErr_SetString(PyExc_UserWarning, "I'm sorry Dave...");
 }
diff --git a/doc/tutorial/doc/html/python/exposing.html b/doc/tutorial/doc/html/python/exposing.html
index e0f0266c..f2a2f1d2 100644
--- a/doc/tutorial/doc/html/python/exposing.html
+++ b/doc/tutorial/doc/html/python/exposing.html
@@ -12,10 +12,10 @@
 
 
-
+
-
-
+
+
Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

@@ -40,8 +40,7 @@

Consider a C++ class/struct that we want to expose to Python:

-
-struct World
+
struct World
 {
     void set(std::string msg) { this->msg = msg; }
     std::string greet() { return msg; }
@@ -51,8 +50,7 @@
 

We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:

-
-#include <boost/python.hpp>
+
#include <boost/python.hpp>
 using namespace boost::python;
 
 BOOST_PYTHON_MODULE(hello)
@@ -71,8 +69,7 @@
     

-
->>> import hello
+
>>> import hello
 >>> planet = hello.World()
 >>> planet.set('howdy')
 >>> planet.greet()
@@ -87,8 +84,7 @@
         exposes the default constructor by default, which is why we were able to
         write
       

-
->>> planet = hello.World()
+
>>> planet = hello.World()
 

We may wish to wrap a class with a non-default constructor. Let us build @@ -96,8 +92,7 @@

-
-struct World
+
struct World
 {
     World(std::string msg): msg(msg) {} // added constructor
     void set(std::string msg) { this->msg = msg; }
@@ -111,8 +106,7 @@
         We have to tell class_<World> about the constructor
         we want to expose instead.
       

-
-#include <boost/python.hpp>
+
#include <boost/python.hpp>
 using namespace boost::python;
 
 BOOST_PYTHON_MODULE(hello)
@@ -133,8 +127,7 @@
         to the def() member function. Say for example we have
         another World constructor taking in two doubles:
       

-
-class_<World>("World", init<std::string>())
+
class_<World>("World", init<std::string>())
     .def(init<double, double>())
     .def("greet", &World::greet)
     .def("set", &World::set)
@@ -144,8 +137,7 @@
         On the other hand, if we do not wish to expose any constructors at all, we
         may use no_init instead:
       

-
-class_<Abstract>("Abstract", no_init)
+
class_<Abstract>("Abstract", no_init)
 

This actually adds an _init_ @@ -161,8 +153,7 @@ to be exposed may be regarded as read-only or read-write. Consider this class Var:

-
-struct Var
+
struct Var
 {
     Var(std::string name) : name(name), value() {}
     std::string const name;
@@ -173,8 +164,7 @@
         Our C++ Var class and its data members can be exposed
         to Python:
       

-
-class_<Var>("Var", init<std::string>())
+
class_<Var>("Var", init<std::string>())
     .def_readonly("name", &Var::name)
     .def_readwrite("value", &Var::value);
 
@@ -184,8 +174,7 @@

-
->>> x = hello.Var('pi')
+
>>> x = hello.Var('pi')
 >>> x.value = 3.14
 >>> print x.name, 'is around', x.value
 pi is around 3.14
@@ -194,8 +183,7 @@
         Note that name is exposed as read-only
         while value is exposed as read-write.
       

-
->>> x.name = 'e' # can't change name
+
>>> x.name = 'e' # can't change name
 Traceback (most recent call last):
   File "<stdin>", line 1, in #
 AttributeError: can#t set attribute
@@ -212,8 +200,7 @@
       

-
-struct Num
+
struct Num
 {
     Num();
     float get() const;
@@ -227,8 +214,7 @@
         can just be a different syntax for a method call. Wrapping our Num
         class using Boost.Python:
       

-
-class_<Num>("Num")
+
class_<Num>("Num")
     .add_property("rovalue", &Num::get)
     .add_property("value", &Num::get, &Num::set);
 
@@ -237,8 +223,7 @@

-
->>> x = Num()
+
>>> x = Num()
 >>> x.value = 3.14
 >>> x.value, x.rovalue
 (3.14, 3.14)
@@ -251,8 +236,7 @@
       

-
-.add_property("rovalue", &Num::get)
+
.add_property("rovalue", &Num::get)
 
@@ -268,24 +252,21 @@

Consider this trivial inheritance structure:

-
-struct Base { virtual ~Base(); };
+
struct Base { virtual ~Base(); };
 struct Derived : Base {};
 

And a set of C++ functions operating on Base and Derived object instances:

-
-void b(Base*);
+
void b(Base*);
 void d(Derived*);
 Base* factory() { return new Derived; }
 

We've seen how we can wrap the base class Base:

-
-class_<Base>("Base")
+
class_<Base>("Base")
     /*...*/
     ;
 
@@ -293,8 +274,7 @@ Now we can inform Boost.Python of the inheritance relationship between Derived and its base class Base. Thus:

-
-class_<Derived, bases<Base> >("Derived")
+
class_<Derived, bases<Base> >("Derived")
     /*...*/
     ;
 
@@ -317,8 +297,7 @@ Now, we will expose the C++ free functions b and d and factory:

-
-def("b", b);
+
def("b", b);
 def("d", d);
 def("factory", factory);
 
@@ -331,8 +310,7 @@ is destroyed. We will see more of Boost.Python call policies later.

-
-// Tell Python to take ownership of factory's result
+
// Tell Python to take ownership of factory's result
 def("factory", factory,
     return_value_policy<manage_new_object>());
 
@@ -345,8 +323,7 @@ through virtual functions. Continuing our example, let us add a virtual function to our Base class:

-
-struct Base
+
struct Base
 {
     virtual ~Base() {}
     virtual int f() = 0;
@@ -364,8 +341,7 @@
         that will unintrusively hook into the virtual functions so that a Python
         override may be called:
       

-
-struct BaseWrap : Base, wrapper<Base>
+
struct BaseWrap : Base, wrapper<Base>
 {
     int f()
     {
@@ -397,8 +373,7 @@
 

Finally, exposing Base:

-
-class_<BaseWrap, boost::noncopyable>("Base")
+
class_<BaseWrap, boost::noncopyable>("Base")
     .def("f", pure_virtual(&Base::f))
     ;
 
@@ -437,8 +412,7 @@ section, we wrapped a class with a pure virtual function that we then implemented in C++, or Python classes derived from it. Our base class:

-
-struct Base
+
struct Base
 {
     virtual int f() = 0;
 };
@@ -447,8 +421,7 @@
         had a pure virtual function f. If, however, its member
         function f was not declared as pure virtual:
       

-
-struct Base
+
struct Base
 {
     virtual ~Base() {}
     virtual int f() { return 0; }
@@ -457,8 +430,7 @@
 

We wrap it this way:

-
-struct BaseWrap : Base, wrapper<Base>
+
struct BaseWrap : Base, wrapper<Base>
 {
     int f()
     {
@@ -490,8 +462,7 @@
 

Finally, exposing:

-
-class_<BaseWrap, boost::noncopyable>("Base")
+
class_<BaseWrap, boost::noncopyable>("Base")
     .def("f", &Base::f, &BaseWrap::default_f)
     ;
 
@@ -506,8 +477,7 @@

-
->>> base = Base()
+
>>> base = Base()
 >>> class Derived(Base):
 ...     def f(self):
 ...         return 42
@@ -517,15 +487,13 @@
 

Calling base.f():

-
->>> base.f()
+
>>> base.f()
 0
 

Calling derived.f():

-
->>> derived.f()
+
>>> derived.f()
 42
 
@@ -533,7 +501,7 @@

Class Operators/Special Functions

- + Python Operators

@@ -547,8 +515,7 @@

-
-class FilePos { /*...*/ };
+
class FilePos { /*...*/ };
 
 FilePos     operator+(FilePos, int);
 FilePos     operator+(int, FilePos);
@@ -562,8 +529,7 @@
         The class and the various operators can be mapped to Python rather easily
         and intuitively:
       

-
-class_<FilePos>("FilePos")
+
class_<FilePos>("FilePos")
     .def(self + int())          // __add__
     .def(int() + self)          // __radd__
     .def(self - self)           // __sub__
@@ -582,7 +548,7 @@
         expressions".
       

- + Special Methods

@@ -592,8 +558,7 @@ wrap C++ functions that correspond to these Python special functions. Example:

-
-class Rational
+
class Rational
 { public: operator double() const; };
 
 Rational pow(Rational, Rational);
diff --git a/doc/tutorial/doc/html/python/functions.html b/doc/tutorial/doc/html/python/functions.html
index b044c83e..e637e77d 100644
--- a/doc/tutorial/doc/html/python/functions.html
+++ b/doc/tutorial/doc/html/python/functions.html
@@ -12,10 +12,10 @@
 
 
-
+
-
-
+
+
Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

@@ -87,16 +87,14 @@ Namespaces are one honking great idea -- let's do more of those! so Boost.Python must deal with them. To do this, it may need your help. Consider the following C++ function:

-
-X& f(Y& y, Z* z);
+
X& f(Y& y, Z* z);
 

How should the library wrap this function? A naive approach builds a Python X object around result reference. This strategy might or might not work out. Here's an example where it didn't

-
->>> x = f(y, z) # x refers to some C++ X
+
>>> x = f(y, z) # x refers to some C++ X
 >>> del y
 >>> x.some_method() # CRASH!
 
@@ -106,8 +104,7 @@ Namespaces are one honking great idea -- let's do more of those!

Well, what if f() was implemented as shown below:

-
-X& f(Y& y, Z* z)
+
X& f(Y& y, Z* z)
 {
     y.z = z;
     return y.x;
@@ -145,8 +142,7 @@ Namespaces are one honking great idea -- let's do more of those!
       

-
->>> f(y, z).set(42) # Result disappears
+
>>> f(y, z).set(42) # Result disappears
 >>> y.x.get()       # No crash, but still bad
 3.14
 
@@ -160,8 +156,7 @@ Namespaces are one honking great idea -- let's do more of those!

-
-struct Y
+
struct Y
 {
     X x; Z* z;
     int z_value() { return z->value(); }
@@ -171,16 +166,14 @@ Namespaces are one honking great idea -- let's do more of those!
         Notice that the data member z is held by class Y using
         a raw pointer. Now we have a potential dangling pointer problem inside Y:
       

-
->>> x = f(y, z) # y refers to z
+
>>> x = f(y, z) # y refers to z
 >>> del z       # Kill the z object
 >>> y.z_value() # CRASH!
 

For reference, here's the implementation of f again:

-
-X& f(Y& y, Z* z)
+
X& f(Y& y, Z* z)
 {
     y.z = z;
     return y.x;
@@ -212,7 +205,7 @@ Namespaces are one honking great idea -- let's do more of those!
 
  • BOOM!
  • - + Call Policies

    @@ -220,8 +213,7 @@ Namespaces are one honking great idea -- let's do more of those! In our example, return_internal_reference and with_custodian_and_ward are our friends:

    -
    -def("f", f,
    +
    def("f", f,
         return_internal_reference<1,
             with_custodian_and_ward<1, 2> >());
     
    @@ -229,8 +221,7 @@ Namespaces are one honking great idea -- let's do more of those! What are the 1 and 2 parameters, you ask?

    -
    -return_internal_reference<1
    +
    return_internal_reference<1
     

    Informs Boost.Python that the first argument, in our case Y& @@ -239,8 +230,7 @@ Namespaces are one honking great idea -- let's do more of those! In short: "return an internal reference X& owned by the 1st argument Y& y".

    -
    -with_custodian_and_ward<1, 2>
    +
    with_custodian_and_ward<1, 2>
     

    Informs Boost.Python that the lifetime of the argument indicated by ward @@ -252,8 +242,7 @@ Namespaces are one honking great idea -- let's do more of those! It is also important to note that we have defined two policies above. Two or more policies can be composed by chaining. Here's the general syntax:

    -
    -policy1<args...,
    +
    policy1<args...,
         policy2<args...,
             policy3<args...> > >
     
    @@ -317,8 +306,7 @@ Namespaces are one honking great idea -- let's do more of those!

    We have here our C++ class:

    -
    -struct X
    +
    struct X
     {
         bool f(int a)
         {
    @@ -345,8 +333,7 @@ Namespaces are one honking great idea -- let's do more of those!
             Class X has 4 overloaded functions. We will start by introducing some member
             function pointer variables:
           

    -
    -bool    (X::*fx1)(int)              = &X::f;
    +
    bool    (X::*fx1)(int)              = &X::f;
     bool    (X::*fx2)(int, double)      = &X::f;
     bool    (X::*fx3)(int, double, char)= &X::f;
     int     (X::*fx4)(int, int, int)    = &X::f;
    @@ -354,8 +341,7 @@ Namespaces are one honking great idea -- let's do more of those!
     

    With these in hand, we can proceed to define and wrap this for Python:

    -
    -.def("f", fx1)
    +
    .def("f", fx1)
     .def("f", fx2)
     .def("f", fx3)
     .def("f", fx4)
    @@ -369,30 +355,26 @@ Namespaces are one honking great idea -- let's do more of those!
             pointers carry no default argument info. Take a function f
             with default arguments:
           

    -
    -int f(int, double = 3.14, char const* = "hello");
    +
    int f(int, double = 3.14, char const* = "hello");
     

    But the type of a pointer to the function f has no information about its default arguments:

    -
    -int(*g)(int,double,char const*) = f;    // defaults lost!
    +
    int(*g)(int,double,char const*) = f;    // defaults lost!
     

    When we pass this function pointer to the def function, there is no way to retrieve the default arguments:

    -
    -def("f", f);                            // defaults lost!
    +
    def("f", f);                            // defaults lost!
     

    Because of this, when wrapping C++ code, we had to resort to manual wrapping as outlined in the previous section, or writing thin wrappers:

    -
    -// write "thin wrappers"
    +
    // write "thin wrappers"
     int f1(int x) { f(x); }
     int f2(int x, double y) { f(x,y); }
     
    @@ -415,14 +397,13 @@ Namespaces are one honking great idea -- let's do more of those!
             
     
     

    - + BOOST_PYTHON_FUNCTION_OVERLOADS

    Boost.Python now has a way to make it easier. For instance, given a function:

    -
    -int foo(int a, char b = 1, unsigned c = 2, double d = 3)
    +
    int foo(int a, char b = 1, unsigned c = 2, double d = 3)
     {
         /*...*/
     }
    @@ -430,8 +411,7 @@ Namespaces are one honking great idea -- let's do more of those!
     

    The macro invocation:

    -
    -BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
    +
    BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
     

    will automatically create the thin wrappers for us. This macro will create @@ -441,11 +421,10 @@ Namespaces are one honking great idea -- let's do more of those! number of arguments is 1 and the maximum number of arguments is 4. The def(...) function will automatically add all the foo variants for us:

    -
    -def("foo", foo, foo_overloads());
    +
    def("foo", foo, foo_overloads());
     

    - + BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS

    @@ -460,8 +439,7 @@ Namespaces are one honking great idea -- let's do more of those! may be used to automatically create the thin wrappers for wrapping member functions. Let's have an example:

    -
    -struct george
    +
    struct george
     {
         void
         wack_em(int a, int b = 0, char c = 'x')
    @@ -473,8 +451,7 @@ Namespaces are one honking great idea -- let's do more of those!
     

    The macro invocation:

    -
    -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
    +
    BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
     

    will generate a set of thin wrappers for george's wack_em @@ -483,15 +460,14 @@ Namespaces are one honking great idea -- let's do more of those! in a class named george_overloads that can then be used as an argument to def(...):

    -
    -.def("wack_em", &george::wack_em, george_overloads());
    +
    .def("wack_em", &george::wack_em, george_overloads());
     

    See the overloads reference for details.

    - + init and optional

    @@ -499,8 +475,7 @@ Namespaces are one honking great idea -- let's do more of those! arguments or a sequence of overloads. Remember init<...>? For example, given a class X with a constructor:

    -
    -struct X
    +
    struct X
     {
         X(int a, char b = 'D', std::string c = "constructor", double d = 0.0);
         /*...*/
    @@ -509,8 +484,7 @@ Namespaces are one honking great idea -- let's do more of those!
     

    You can easily add this constructor to Boost.Python in one shot:

    -
    -.def(init<int, optional<char, std::string, double> >())
    +
    .def(init<int, optional<char, std::string, double> >())
     

    Notice the use of init<...> and optional<...> @@ -526,8 +500,7 @@ Namespaces are one honking great idea -- let's do more of those! used for overloaded functions and member functions with a common sequence of initial arguments. Here is an example:

    -
    -void foo()
    +
    void foo()
     {
        /*...*/
     }
    @@ -551,21 +524,19 @@ Namespaces are one honking great idea -- let's do more of those!
             Like in the previous section, we can generate thin wrappers for these overloaded
             functions in one-shot:
           

    -
    -BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
    +
    BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
     

    Then...

    -
    -.def("foo", (void(*)(bool, int, char))0, foo_overloads());
    +
    .def("foo", (void(*)(bool, int, char))0, foo_overloads());
     

    Notice though that we have a situation now where we have a minimum of zero (0) arguments and a maximum of 3 arguments.

    - + Manual Wrapping

    @@ -584,21 +555,18 @@ Namespaces are one honking great idea -- let's do more of those! to automatically wrap the first three of the defs and manually wrap just the last. Here's how we'll do this:

    -
    -BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
    +
    BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
     

    Create a member function pointers as above for both X::f overloads:

    -
    -bool    (X::*fx1)(int, double, char)    = &X::f;
    +
    bool    (X::*fx1)(int, double, char)    = &X::f;
     int     (X::*fx2)(int, int, int)        = &X::f;
     

    Then...

    -
    -.def("f", fx1, xf_overloads());
    +
    .def("f", fx1, xf_overloads());
     .def("f", fx2)
     
    diff --git a/doc/tutorial/doc/html/python/hello.html b/doc/tutorial/doc/html/python/hello.html index c6043c5e..5fcc66ec 100644 --- a/doc/tutorial/doc/html/python/hello.html +++ b/doc/tutorial/doc/html/python/hello.html @@ -12,10 +12,10 @@ - + - - + +
    Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

    @@ -26,7 +26,7 @@

    Building Hello World

    - + From Start To Finish

    @@ -92,7 +92,7 @@ platforms. The complete list of Bjam executables can be found here.

    - + Let's Jam!

    @@ -108,7 +108,7 @@ you going.

    - + Running bjam

    @@ -156,8 +156,7 @@ using python : 2.4 : C:/dev/toolsPython ;

    Finally:

    -
    -bjam
    +
    bjam
     

    It should be building now: diff --git a/doc/tutorial/doc/html/python/iterators.html b/doc/tutorial/doc/html/python/iterators.html index ad012f8f..9968cb73 100644 --- a/doc/tutorial/doc/html/python/iterators.html +++ b/doc/tutorial/doc/html/python/iterators.html @@ -12,10 +12,10 @@ - + - - + +
    Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More


    @@ -64,8 +64,7 @@

    -
    -iter = x.__iter__()         # get iterator
    +
    iter = x.__iter__()         # get iterator
     try:
         while 1:
         y = iter.next()         # get each item
    @@ -79,16 +78,14 @@
         

    -
    -object get_iterator = iterator<vector<int> >();
    +
    object get_iterator = iterator<vector<int> >();
     object iter = get_iterator(v);
     object first = iter.next();
     

    Or for use in class_<>:

    -
    -.def("__iter__", iterator<vector<int> >())
    +
    .def("__iter__", iterator<vector<int> >())
     

    range @@ -134,8 +131,7 @@

    -
    -f = Field()
    +
    f = Field()
     for x in f.pions:
         smash(x)
     for y in f.bogons:
    @@ -146,8 +142,7 @@
         

    -
    -class_<F>("Field")
    +
    class_<F>("Field")
         .property("pions", range(&F::p_begin, &F::p_end))
         .property("bogons", range(&F::b_begin, &F::b_end));
     
    @@ -163,8 +158,7 @@

    -
    -template<typename T>
    +
    template<typename T>
     void list_assign(std::list<T>& l, object o) {
         // Turn a Python sequence into an STL input range
         stl_input_iterator<T> begin(o), end;
    @@ -183,8 +177,7 @@
         

    -
    -x = list_int();
    +
    x = list_int();
     x.assign([1,2,3,4,5])
     
    diff --git a/doc/tutorial/doc/html/python/object.html b/doc/tutorial/doc/html/python/object.html index 4d28996b..533ab873 100644 --- a/doc/tutorial/doc/html/python/object.html +++ b/doc/tutorial/doc/html/python/object.html @@ -12,10 +12,10 @@ - + - - + +
    Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

    @@ -62,8 +62,7 @@

    -
    -def f(x, y):
    +
    def f(x, y):
          if (y == 'foo'):
              x[3:7] = 'bar'
          else:
    @@ -78,8 +77,7 @@
           

    -
    -object f(object x, object y) {
    +
    object f(object x, object y) {
          if (y == "foo")
              x.slice(3,7) = "bar";
          else
    @@ -126,23 +124,20 @@
             These derived object types act like real Python types.
             For instance:
           

    -
    -str(1) ==> "1"
    +
    str(1) ==> "1"
     

    Wherever appropriate, a particular derived object has corresponding Python type's methods. For instance, dict has a keys() method:

    -
    -d.keys()
    +
    d.keys()
     

    make_tuple is provided for declaring tuple literals. Example:

    -
    -make_tuple(123, 'D', "Hello, World", 0.0);
    +
    make_tuple(123, 'D', "Hello, World", 0.0);
     

    In C++, when Boost.Python objects are used as arguments @@ -150,8 +145,7 @@ f, as declared below, is wrapped, it will only accept instances of Python's str type and subtypes.

    -
    -void f(str name)
    +
    void f(str name)
     {
         object n2 = name.attr("upper")();   // NAME = name.upper()
         str NAME = name.upper();            // better
    @@ -161,15 +155,13 @@
     

    In finer detail:

    -
    -str NAME = name.upper();
    +
    str NAME = name.upper();
     

    Illustrates that we provide versions of the str type's methods as C++ member functions.

    -
    -object msg = "%s is bigger than %s" % make_tuple(NAME,name);
    +
    object msg = "%s is bigger than %s" % make_tuple(NAME,name);
     

    Demonstrates that you can write the C++ equivalent of "format" @@ -184,19 +176,17 @@

    Python:

    -
    ->>> d = dict(x.__dict__)     # copies x.__dict__
    +
    >>> d = dict(x.__dict__)     # copies x.__dict__
     >>> d['whatever'] = 3        # modifies the copy
     

    C++:

    -
    -dict d(x.attr("__dict__"));  // copies x.__dict__
    +
    dict d(x.attr("__dict__"));  // copies x.__dict__
     d['whatever'] = 3;           // modifies the copy
     

    - + class_<T> as objects

    @@ -207,8 +197,7 @@

    We can use this to create wrapped instances. Example:

    -
    -object vec345 = (
    +
    object vec345 = (
         class_<Vec2>("Vec2", init<double, double>())
             .def_readonly("length", &Point::length)
             .def_readonly("angle", &Point::angle)
    @@ -225,16 +214,14 @@
             can be achieved with the extract<T> function. Consider
             the following:
           

    -
    -double x = o.attr("length"); // compile error
    +
    double x = o.attr("length"); // compile error
     

    In the code above, we got a compiler error because Boost.Python object can't be implicitly converted to doubles. Instead, what we wanted to do above can be achieved by writing:

    -
    -double l = extract<double>(o.attr("length"));
    +
    double l = extract<double>(o.attr("length"));
     Vec2& v = extract<Vec2&>(o);
     assert(l == v.length());
     
    @@ -251,8 +238,7 @@ be extracted, an appropriate exception is thrown. To avoid an exception, we need to test for extractibility:

    -
    -extract<Vec2&> x(o);
    +
    extract<Vec2&> x(o);
     if (x.check()) {
         Vec2& v = x(); ...
     
    @@ -260,8 +246,7 @@ tip The astute reader might have noticed that the extract<T> facility in fact solves the mutable copying problem:

    -
    -dict d = extract<dict>(x.attr("__dict__"));
    +
    dict d = extract<dict>(x.attr("__dict__"));
     d["whatever"] = 3;          // modifies x.__dict__ !
     
    @@ -276,14 +261,12 @@ typing to C++'s strong static typing (in C++, ints cannot be implicitly converted to enums). To illustrate, given a C++ enum:

    -
    -enum choice { red, blue };
    +
    enum choice { red, blue };
     

    the construct:

    -
    -enum_<choice>("choice")
    +
    enum_<choice>("choice")
         .value("red", red)
         .value("blue", blue)
         ;
    @@ -315,8 +298,7 @@
           

    -
    ->>> my_module.choice.red
    +
    >>> my_module.choice.red
     my_module.choice.red
     

    @@ -325,8 +307,7 @@

    -
    -scope in_X = class_<X>("X")
    +
    scope in_X = class_<X>("X")
                     .def( ... )
                     .def( ... )
                 ;
    diff --git a/doc/tutorial/doc/html/python/techniques.html b/doc/tutorial/doc/html/python/techniques.html
    index 8598e927..1556e25b 100644
    --- a/doc/tutorial/doc/html/python/techniques.html
    +++ b/doc/tutorial/doc/html/python/techniques.html
    @@ -11,10 +11,10 @@
     
     
    -
    +
    -
    -
    +
    +
    Boost C++ LibrariesHomeHome LibrariesPeopleFAQPeopleFAQ More

    @@ -53,8 +53,7 @@ sounds. Our library already has a neat C++ namespace hierarchy, like so:

    -
    -sounds::core
    +
    sounds::core
     sounds::io
     sounds::filters
     
    @@ -62,16 +61,14 @@ We would like to present this same hierarchy to the Python user, allowing him to write code like this:

    -
    -import sounds.filters
    +
    import sounds.filters
     sounds.filters.echo(...) # echo is a C++ function
     

    The first step is to write the wrapping code. We have to export each module separately with Boost.Python, like this:

    -
    -/* file core.cpp */
    +
    /* file core.cpp */
     BOOST_PYTHON_MODULE(core)
     {
         /* export everything in the sounds::core namespace */
    @@ -129,8 +126,7 @@
           

    -
    ->>> import sounds.io
    +
    >>> import sounds.io
     >>> import sounds.filters
     >>> sound = sounds.io.open('file.mp3')
     >>> new_sound = sounds.filters.echo(sound, 1.0)
    @@ -152,8 +148,7 @@
           

    -
    -/* file core.cpp */
    +
    /* file core.cpp */
     BOOST_PYTHON_MODULE(_core)
     {
         ...
    @@ -185,8 +180,7 @@
           

    -
    ->>> import sounds.core._core
    +
    >>> import sounds.core._core
     >>> sounds.core._core.foo(...)
     

    @@ -196,15 +190,13 @@ entire namespace from _core.pyd to core/__init__.py. So add this line of code to soundscore__init__.py:

    -
    -from _core import *
    +
    from _core import *
     

    We do the same for the other packages. Now the user accesses the functions and classes in the extension modules like before:

    -
    ->>> import sounds.filters
    +
    >>> import sounds.filters
     >>> sounds.filters.echo(...)
     

    @@ -217,8 +209,7 @@ a file named sounds/filters/echo_noise.py and code our function:

    -
    -import _filters
    +
    import _filters
     def echo_noise(sound):
         s = _filters.echo(sound)
         s = _filters.noise(sound)
    @@ -227,15 +218,13 @@
     

    Next, we add this line to soundsfilters__init__.py:

    -
    -from echo_noise import echo_noise
    +
    from echo_noise import echo_noise
     

    And that's it. The user now accesses this function like any other function from the filters package:

    -
    ->>> import sounds.filters
    +
    >>> import sounds.filters
     >>> sounds.filters.echo_noise(...)
     
    @@ -246,8 +235,7 @@ Thanks to Python's flexibility, you can easily add new methods to a class, even after it was already created:

    -
    ->>> class C(object): pass
    +
    >>> class C(object): pass
     >>>
     >>> # a regular function
     >>> def C_str(self): return 'A C instance!'
    @@ -270,8 +258,7 @@
           

    -
    -class point {...};
    +
    class point {...};
     
     BOOST_PYTHON_MODULE(_geom)
     {
    @@ -284,8 +271,7 @@
           

    -
    -from _geom import *
    +
    from _geom import *
     
     # a regular function
     def point_str(self):
    @@ -317,8 +303,7 @@
             You can even add a little syntactic sugar with the use of metaclasses. Let's
             create a special metaclass that "injects" methods in other classes.
           

    -
    -# The one Boost.Python uses for all wrapped classes.
    +
    # The one Boost.Python uses for all wrapped classes.
     # You can use here any class exported by Boost instead of "point"
     BoostPythonMetaclass = point.__class__
     
    @@ -341,8 +326,7 @@
     

    Now let's see how it got:

    -
    ->>> print point()
    +
    >>> print point()
     Point(x=10, y=10)
     >>> point().foo()
     foo!
    @@ -350,8 +334,7 @@
     

    Another useful idea is to replace constructors with factory functions:

    -
    -_point = point
    +
    _point = point
     
     def point(x=0, y=0):
         return _point(x, y)
    @@ -374,8 +357,7 @@
           

    -
    -/* file point.cpp */
    +
    /* file point.cpp */
     #include <point.h>
     #include <boost/python.hpp>
     
    @@ -397,8 +379,7 @@
             Now you create a file main.cpp, which contains the BOOST_PYTHON_MODULE
             macro, and call the various export functions inside it.
           

    -
    -void export_point();
    +
    void export_point();
     void export_triangle();
     
     BOOST_PYTHON_MODULE(_geom)
    @@ -411,8 +392,7 @@
             Compiling and linking together all this files produces the same result as
             the usual approach:
           

    -
    -#include <boost/python.hpp>
    +
    #include <boost/python.hpp>
     #include <point.h>
     #include <triangle.h>
     
    diff --git a/doc/tutorial/doc/tutorial.qbk b/doc/tutorial/doc/tutorial.qbk
    index 83b0a912..f1697fae 100644
    --- a/doc/tutorial/doc/tutorial.qbk
    +++ b/doc/tutorial/doc/tutorial.qbk
    @@ -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]
    @@ -1385,10 +1381,10 @@ interpreter. This may be fixed in a future version of boost.python.]
     [section Using the interpreter]
     
     As you probably already know, objects in Python are reference-counted.
    -Naturally, the [^PyObject]s of the Python\/C API are also reference-counted.
    +Naturally, the [^PyObject]s of the Python C API are also reference-counted.
     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
    +automatic in Python, the Python C API requires you to do it
    +[@http://www.python.org/doc/current/c-api/refcounting.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.
    @@ -1470,7 +1466,7 @@ If an exception occurs in the evaluation of the python expression,
     The [^error_already_set] exception class doesn't carry any information in itself.
     To find out more about the Python exception that occurred, you need to use the
     [@http://www.python.org/doc/api/exceptionHandling.html exception handling functions]
    -of the Python/C API in your catch-statement. This can be as simple as calling
    +of the Python C API in your catch-statement. This can be as simple as calling
     [@http://www.python.org/doc/api/exceptionHandling.html#l2h-70 PyErr_Print()] to
     print the exception's traceback to the console, or comparing the type of the
     exception with those of the [@http://www.python.org/doc/api/standardExceptions.html
    diff --git a/doc/v2/object.html b/doc/v2/object.html
    index f35fa579..6fa48fa5 100644
    --- a/doc/v2/object.html
    +++ b/doc/v2/object.html
    @@ -655,6 +655,11 @@ namespace boost { namespace python { namespace api
           template <class A0, class A1,...class An>
           object operator()(A0 const&, A1 const&,...An const&) const;
     
    +      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
           //
           typedef unspecified bool_type;
    @@ -704,6 +709,25 @@ object operator()(A0 const& a1, A1 const& a2,...An const& aN) const;
           call<object>(object(*static_cast<U*>(this)).ptr(), a1,
           a2,...aN)
         
    +
    +
    +object operator()(detail::args_proxy const &args) const; 
    +
    +
    +
    Effects: + call object with arguments given by the tuple args
    +
    +
    +object operator()(detail::args_proxy const &args, 
    +                  detail::kwds_proxy const &kwds) const; 
    +
    +
    +
    Effects: + call object with arguments given by the tuple args, and named + arguments given by the dictionary kwds
    +
    + +
     operator bool_type() const;
     
    diff --git a/example/tutorial/Jamroot b/example/tutorial/Jamroot old mode 100755 new mode 100644 index 8d381593..2e7ffe57 --- a/example/tutorial/Jamroot +++ b/example/tutorial/Jamroot @@ -2,6 +2,15 @@ # 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 ; + +if ! [ python.configured ] +{ + ECHO "notice: no Python configured in user-config.jam" ; + ECHO "notice: will use default configuration" ; + using python ; +} + # Specify the path to the Boost project. If you move this project, # adjust this path to refer to the Boost root directory. use-project boost diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp index 9a3d974b..5d2d7d23 100644 --- a/include/boost/python/call.hpp +++ b/include/boost/python/call.hpp @@ -38,7 +38,10 @@ namespace boost { namespace python { # endif // CALL_DWA2002411_HPP -#elif BOOST_PP_ITERATION_DEPTH() == 1 +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, call.hpp) @@ -76,4 +79,5 @@ call(PyObject* callable # undef N +#endif // BOOST_PP_ITERATION_DEPTH() #endif diff --git a/include/boost/python/call_method.hpp b/include/boost/python/call_method.hpp index 0bca0610..410f6682 100644 --- a/include/boost/python/call_method.hpp +++ b/include/boost/python/call_method.hpp @@ -37,7 +37,10 @@ namespace boost { namespace python { # endif // CALL_METHOD_DWA2002411_HPP -#elif BOOST_PP_ITERATION_DEPTH() == 1 +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, call_method.hpp) @@ -76,4 +79,5 @@ call_method(PyObject* self, char const* name # undef N +#endif // BOOST_PP_ITERATION_DEPTH() #endif // BOOST_PP_IS_ITERATING diff --git a/include/boost/python/converter/rvalue_from_python_data.hpp b/include/boost/python/converter/rvalue_from_python_data.hpp index 7d2b3e07..471a5255 100644 --- a/include/boost/python/converter/rvalue_from_python_data.hpp +++ b/include/boost/python/converter/rvalue_from_python_data.hpp @@ -117,9 +117,9 @@ struct rvalue_from_python_data : rvalue_from_python_storage // Implementataions // template -inline rvalue_from_python_data::rvalue_from_python_data(rvalue_from_python_stage1_data const& stage1) +inline rvalue_from_python_data::rvalue_from_python_data(rvalue_from_python_stage1_data const& _stage1) { - this->stage1 = stage1; + this->stage1 = _stage1; } template diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index 6b49c469..c0910776 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -45,10 +45,14 @@ struct shared_ptr_from_python if (data->convertible == source) new (storage) shared_ptr(); else + { + boost::shared_ptr hold_convertible_ref_count( + (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); + // use aliasing constructor new (storage) shared_ptr( - static_cast(data->convertible), - shared_ptr_deleter(handle<>(borrowed(source))) - ); + hold_convertible_ref_count, + static_cast(data->convertible)); + } data->convertible = storage; } diff --git a/include/boost/python/data_members.hpp b/include/boost/python/data_members.hpp index 8cbc0ac3..b0851fb1 100644 --- a/include/boost/python/data_members.hpp +++ b/include/boost/python/data_members.hpp @@ -265,7 +265,8 @@ inline object make_getter(D const& d, Policies const& policies) template inline object make_getter(D& x) { - detail::not_specified policy; + detail::not_specified policy + = detail::not_specified(); // suppress a SunPro warning return detail::make_getter(x, policy, is_member_pointer(), 0L); } @@ -273,7 +274,8 @@ inline object make_getter(D& x) template inline object make_getter(D const& d) { - detail::not_specified policy; + detail::not_specified policy + = detail::not_specified(); // Suppress a SunPro warning return detail::make_getter(d, policy, is_member_pointer(), 0L); } # endif diff --git a/include/boost/python/detail/decorated_type_id.hpp b/include/boost/python/detail/decorated_type_id.hpp old mode 100755 new mode 100644 index 2e44ac2c..535508b4 --- a/include/boost/python/detail/decorated_type_id.hpp +++ b/include/boost/python/detail/decorated_type_id.hpp @@ -55,8 +55,8 @@ inline decorated_type_info::decorated_type_info(type_info base_t, decoration dec inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const { return m_decoration < rhs.m_decoration - || m_decoration == rhs.m_decoration - && m_base_type < rhs.m_base_type; + || (m_decoration == rhs.m_decoration + && m_base_type < rhs.m_base_type); } inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const diff --git a/include/boost/python/detail/result.hpp b/include/boost/python/detail/result.hpp old mode 100755 new mode 100644 index 80e4387f..9b8b4864 --- a/include/boost/python/detail/result.hpp +++ b/include/boost/python/detail/result.hpp @@ -86,7 +86,10 @@ result(X const&, short = 0) { return 0; } # endif // RESULT_DWA2002521_HPP /* --------------- function pointers --------------- */ -#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, result.hpp(function pointers)) @@ -128,4 +131,5 @@ boost::type* result(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q, int = 0) # undef N # undef Q +#endif // BOOST_PP_ITERATION_DEPTH() #endif diff --git a/include/boost/python/detail/target.hpp b/include/boost/python/detail/target.hpp index 5079699a..137801bb 100644 --- a/include/boost/python/detail/target.hpp +++ b/include/boost/python/detail/target.hpp @@ -37,7 +37,10 @@ T& (* target(R (T::*)) )() { return 0; } # endif // TARGET_DWA2002521_HPP /* --------------- function pointers --------------- */ -#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == BOOST_PYTHON_FUNCTION_POINTER +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, target.hpp(function_pointers)) @@ -79,4 +82,5 @@ T& (* target(R (T::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, A)) Q) )() # undef N # undef Q +#endif // BOOST_PP_ITERATION_DEPTH() #endif diff --git a/include/boost/python/object/class_metadata.hpp b/include/boost/python/object/class_metadata.hpp old mode 100755 new mode 100644 index 05740b8e..0738bbe3 --- a/include/boost/python/object/class_metadata.hpp +++ b/include/boost/python/object/class_metadata.hpp @@ -236,7 +236,7 @@ struct class_metadata // // Support for converting smart pointers to python // - inline static void maybe_register_pointer_to_python(void*,void*,void*) {} + inline static void maybe_register_pointer_to_python(...) {} #ifndef BOOST_PYTHON_NO_PY_SYGNATURES inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*) diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 9d5de98d..eb3c603d 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -47,7 +47,10 @@ template struct make_holder; # endif // MAKE_HOLDER_DWA20011215_HPP -#elif BOOST_PP_ITERATION_DEPTH() == 1 +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, make_holder.hpp) @@ -102,4 +105,5 @@ struct make_holder # undef N +#endif // BOOST_PP_ITERATION_DEPTH() #endif diff --git a/include/boost/python/object/pointer_holder.hpp b/include/boost/python/object/pointer_holder.hpp index 7fad2a25..2dc6dda9 100644 --- a/include/boost/python/object/pointer_holder.hpp +++ b/include/boost/python/object/pointer_holder.hpp @@ -127,7 +127,14 @@ void* pointer_holder::holds(type_info dst_t, bool null_ptr_only) ) return &this->m_p; - Value* p = get_pointer(this->m_p); + Value* p +# if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + = static_cast( get_pointer(this->m_p) ) +# else + = get_pointer(this->m_p) +# endif + ; + if (p == 0) return 0; @@ -163,7 +170,10 @@ void* pointer_holder_back_reference::holds(type_info dst_t, bool # endif // POINTER_HOLDER_DWA20011215_HPP /* --------------- pointer_holder --------------- */ -#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, pointer_holder.hpp) @@ -205,4 +215,5 @@ void* pointer_holder_back_reference::holds(type_info dst_t, bool # undef N +#endif // BOOST_PP_ITERATION_DEPTH() #endif diff --git a/include/boost/python/object/value_holder.hpp b/include/boost/python/object/value_holder.hpp index e53866a1..f4d452ca 100644 --- a/include/boost/python/object/value_holder.hpp +++ b/include/boost/python/object/value_holder.hpp @@ -117,7 +117,10 @@ void* value_holder_back_reference::holds( // --------------- value_holder --------------- -#elif BOOST_PP_ITERATION_DEPTH() == 1 && BOOST_PP_ITERATION_FLAGS() == 1 +// 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 # if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \ && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) # line BOOST_PP_LINE(__LINE__, value_holder.hpp(value_holder)) @@ -163,4 +166,5 @@ void* value_holder_back_reference::holds( # undef N +#endif // BOOST_PP_ITERATION_DEPTH() #endif diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index b4a0ea82..0342ef2e 100644 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -42,6 +42,12 @@ namespace boost { namespace python { +namespace detail +{ + class kwds_proxy; + class args_proxy; +} + namespace converter { template struct arg_to_python; @@ -102,6 +108,11 @@ namespace api # define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, )) # 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 // @@ -219,11 +230,11 @@ namespace api inline object_base(object_base const&); inline object_base(PyObject* ptr); - object_base& operator=(object_base const& rhs); - ~object_base(); + inline object_base& operator=(object_base const& rhs); + inline ~object_base(); // Underlying object access -- returns a borrowed reference - PyObject* ptr() const; + inline PyObject* ptr() const; private: PyObject* m_ptr; @@ -393,7 +404,7 @@ namespace api static PyObject* get(T const& x, U) { - return python::incref(get_managed_object(x, tag)); + return python::incref(get_managed_object(x, boost::python::tag)); } }; @@ -416,6 +427,62 @@ template 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 +detail::args_proxy api::object_operators::operator* () const +{ + object_cref2 x = *static_cast(this); + return boost::python::detail::args_proxy(x); +} + +template +object api::object_operators::operator()(detail::args_proxy const &args) const +{ + U const& self = *static_cast(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 +object api::object_operators::operator()(detail::args_proxy const &args, + detail::kwds_proxy const &kwds) const +{ + U const& self = *static_cast(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)) {} diff --git a/include/boost/python/object_protocol.hpp b/include/boost/python/object_protocol.hpp old mode 100755 new mode 100644 index e8d35866..7c1c0283 --- a/include/boost/python/object_protocol.hpp +++ b/include/boost/python/object_protocol.hpp @@ -10,9 +10,11 @@ # include # include +# include + namespace boost { namespace python { namespace api { -# if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) +# if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) // attempt to use SFINAE to prevent functions accepting T const& from // coming up as ambiguous with the one taking a char const* when a // string literal is passed @@ -22,45 +24,45 @@ namespace boost { namespace python { namespace api { # endif template -object getattr(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) +object getattr(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) { return getattr(object(target), object(key)); } template -object getattr(Target const& target, Key const& key, Default const& default_ BOOST_PYTHON_NO_ARRAY_ARG(key)) +object getattr(Target const& target, Key const& key, Default const& default_ BOOST_PYTHON_NO_ARRAY_ARG(Key)) { return getattr(object(target), object(key), object(default_)); } template -void setattr(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(key)) +void setattr(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(Key)) { setattr(target, object(key), object(value)); } template -void delattr(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) +void delattr(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) { delattr(target, object(key)); } template -object getitem(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) +object getitem(Target const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) { return getitem(object(target), object(key)); } template -void setitem(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(key)) +void setitem(object const& target, Key const& key, Value const& value BOOST_PYTHON_NO_ARRAY_ARG(Key)) { setitem(target, object(key), object(value)); } template -void delitem(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(key)) +void delitem(object const& target, Key const& key BOOST_PYTHON_NO_ARRAY_ARG(Key)) { delitem(target, object(key)); } diff --git a/include/boost/python/object_slices.hpp b/include/boost/python/object_slices.hpp index e70faff7..748c2e95 100644 --- a/include/boost/python/object_slices.hpp +++ b/include/boost/python/object_slices.hpp @@ -27,6 +27,12 @@ struct slice_policies : const_slice_policies static void del(object const& target, key_type const& key); }; +template +inline slice_policies::key_type slice_key(T x, U y) +{ + return slice_policies::key_type(handle<>(x), handle<>(y)); +} + // // implementation // @@ -35,7 +41,7 @@ object_slice object_operators::slice(object_cref start, object_cref finish) { object_cref2 x = *static_cast(this); - return object_slice(x, std::make_pair(borrowed(start.ptr()), borrowed(finish.ptr()))); + return object_slice(x, api::slice_key(borrowed(start.ptr()), borrowed(finish.ptr()))); } template @@ -43,7 +49,7 @@ const_object_slice object_operators::slice(object_cref start, object_cref finish) const { object_cref2 x = *static_cast(this); - return const_object_slice(x, std::make_pair(borrowed(start.ptr()), borrowed(finish.ptr()))); + return const_object_slice(x, api::slice_key(borrowed(start.ptr()), borrowed(finish.ptr()))); } template @@ -51,7 +57,7 @@ object_slice object_operators::slice(slice_nil, object_cref finish) { object_cref2 x = *static_cast(this); - return object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr()))); + return object_slice(x, api::slice_key(allow_null((PyObject*)0), borrowed(finish.ptr()))); } template @@ -59,7 +65,7 @@ const_object_slice object_operators::slice(slice_nil, object_cref finish) const { object_cref2 x = *static_cast(this); - return const_object_slice(x, std::make_pair(allow_null((PyObject*)0), borrowed(finish.ptr()))); + return const_object_slice(x, api::slice_key(allow_null((PyObject*)0), borrowed(finish.ptr()))); } template @@ -67,7 +73,7 @@ object_slice object_operators::slice(slice_nil, slice_nil) { object_cref2 x = *static_cast(this); - return object_slice(x, std::make_pair(allow_null((PyObject*)0), allow_null((PyObject*)0))); + return object_slice(x, api::slice_key(allow_null((PyObject*)0), allow_null((PyObject*)0))); } template @@ -75,7 +81,7 @@ const_object_slice object_operators::slice(slice_nil, slice_nil) const { object_cref2 x = *static_cast(this); - return const_object_slice(x, std::make_pair(allow_null((PyObject*)0), allow_null((PyObject*)0))); + return const_object_slice(x, api::slice_key(allow_null((PyObject*)0), allow_null((PyObject*)0))); } template @@ -83,7 +89,7 @@ object_slice object_operators::slice(object_cref start, slice_nil) { object_cref2 x = *static_cast(this); - return object_slice(x, std::make_pair(borrowed(start.ptr()), allow_null((PyObject*)0))); + return object_slice(x, api::slice_key(borrowed(start.ptr()), allow_null((PyObject*)0))); } template @@ -91,7 +97,7 @@ const_object_slice object_operators::slice(object_cref start, slice_nil) const { object_cref2 x = *static_cast(this); - return const_object_slice(x, std::make_pair(borrowed(start.ptr()), allow_null((PyObject*)0))); + return const_object_slice(x, api::slice_key(borrowed(start.ptr()), allow_null((PyObject*)0))); } # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 template diff --git a/include/boost/python/signature.hpp b/include/boost/python/signature.hpp index c4151814..1bb2b226 100644 --- a/include/boost/python/signature.hpp +++ b/include/boost/python/signature.hpp @@ -113,7 +113,10 @@ struct most_derived # endif // SIGNATURE_JDG20020813_HPP -#elif BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING) +// 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) # define N BOOST_PP_ITERATION() @@ -176,4 +179,5 @@ get_signature( # undef Q # undef N +#endif // BOOST_PP_ITERATION_DEPTH() #endif // !defined(BOOST_PP_IS_ITERATING) diff --git a/src/converter/builtin_converters.cpp b/src/converter/builtin_converters.cpp index 97976e03..b3fcd9ea 100644 --- a/src/converter/builtin_converters.cpp +++ b/src/converter/builtin_converters.cpp @@ -99,8 +99,13 @@ namespace if (number_methods == 0) return 0; - return (PyInt_Check(obj) || PyLong_Check(obj)) - ? &number_methods->nb_int : 0; + return ( +#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT) + !PyBool_Check(obj) && +#endif + (PyInt_Check(obj) || PyLong_Check(obj))) + + ? &number_methods->nb_int : 0; } static PyTypeObject const* get_pytype() { return &PyInt_Type;} }; @@ -135,7 +140,11 @@ namespace if (number_methods == 0) return 0; - return (PyInt_Check(obj) || PyLong_Check(obj)) + return ( +#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT) + !PyBool_Check(obj) && +#endif + (PyInt_Check(obj) || PyLong_Check(obj))) ? &py_object_identity : 0; } static PyTypeObject const* get_pytype() { return &PyInt_Type;} @@ -146,10 +155,27 @@ namespace { static T extract(PyObject* intermediate) { - return numeric_cast( - PyLong_Check(intermediate) - ? PyLong_AsUnsignedLong(intermediate) - : PyInt_AS_LONG(intermediate)); + if (PyLong_Check(intermediate)) { + // PyLong_AsUnsignedLong() checks for negative overflow, so no + // need to check it here. + unsigned long result = PyLong_AsUnsignedLong(intermediate); + if (PyErr_Occurred()) + throw_error_already_set(); + return numeric_cast(result); + } else { + // None of PyInt_AsUnsigned*() functions check for negative + // overflow, so use PyInt_AS_LONG instead and check if number is + // negative, issuing the exception appropriately. + long result = PyInt_AS_LONG(intermediate); + if (PyErr_Occurred()) + throw_error_already_set(); + if (result < 0) { + PyErr_SetString(PyExc_OverflowError, "can't convert negative" + " value to unsigned"); + throw_error_already_set(); + } + return numeric_cast(result); + } } }; @@ -226,7 +252,11 @@ namespace { static unaryfunc* get_slot(PyObject* obj) { +#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT) + return obj == Py_None || PyBool_Check(obj) ? &py_object_identity : 0; +#else return obj == Py_None || PyInt_Check(obj) ? &py_object_identity : 0; +#endif } static bool extract(PyObject* intermediate) diff --git a/src/dict.cpp b/src/dict.cpp index ee2ee29f..441b0257 100644 --- a/src/dict.cpp +++ b/src/dict.cpp @@ -29,7 +29,7 @@ namespace detail::new_reference dict_base::call(object const& arg_) { return (detail::new_reference)PyObject_CallFunction( - (PyObject*)&PyDict_Type, "(O)", + (PyObject*)&PyDict_Type, const_cast("(O)"), arg_.ptr()); } diff --git a/src/exec.cpp b/src/exec.cpp index 050cc63e..5dfe033b 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -15,6 +16,15 @@ namespace python object BOOST_PYTHON_DECL eval(str string, object global, object local) { + // Set suitable default values for global and local dicts. + if (!global) + { + if (PyObject *g = PyEval_GetGlobals()) + global = object(detail::borrowed_reference(g)); + else + global = dict(); + } + if (!local) local = global; // should be 'char const *' but older python versions don't use 'const' yet. char *s = python::extract(string); PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr()); @@ -24,6 +34,15 @@ object BOOST_PYTHON_DECL eval(str string, object global, object local) object BOOST_PYTHON_DECL exec(str string, object global, object local) { + // Set suitable default values for global and local dicts. + if (!global) + { + if (PyObject *g = PyEval_GetGlobals()) + global = object(detail::borrowed_reference(g)); + else + global = dict(); + } + if (!local) local = global; // should be 'char const *' but older python versions don't use 'const' yet. char *s = python::extract(string); PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr()); @@ -31,15 +50,42 @@ object BOOST_PYTHON_DECL exec(str string, object global, object local) return object(detail::new_reference(result)); } +object BOOST_PYTHON_DECL exec_statement(str string, object global, object local) +{ + // Set suitable default values for global and local dicts. + if (!global) + { + if (PyObject *g = PyEval_GetGlobals()) + global = object(detail::borrowed_reference(g)); + else + global = dict(); + } + if (!local) local = global; + // should be 'char const *' but older python versions don't use 'const' yet. + char *s = python::extract(string); + PyObject* result = PyRun_String(s, Py_single_input, global.ptr(), local.ptr()); + if (!result) throw_error_already_set(); + return object(detail::new_reference(result)); +} + // Execute python source code from file filename. // global and local are the global and local scopes respectively, // used during execution. object BOOST_PYTHON_DECL exec_file(str filename, object global, object local) { + // Set suitable default values for global and local dicts. + if (!global) + { + if (PyObject *g = PyEval_GetGlobals()) + global = object(detail::borrowed_reference(g)); + else + global = dict(); + } + if (!local) local = global; // should be 'char const *' but older python versions don't use 'const' yet. char *f = python::extract(filename); // Let python open the file to avoid potential binary incompatibilities. - PyObject *pyfile = PyFile_FromString(f, "r"); + PyObject *pyfile = PyFile_FromString(f, const_cast("r")); if (!pyfile) throw std::invalid_argument(std::string(f) + " : no such file"); python::handle<> file(pyfile); PyObject* result = PyRun_File(PyFile_AsFile(file.get()), diff --git a/src/list.cpp b/src/list.cpp index 3c26950e..2c29251b 100644 --- a/src/list.cpp +++ b/src/list.cpp @@ -13,7 +13,7 @@ detail::new_non_null_reference list_base::call(object const& arg_) return (detail::new_non_null_reference) (expect_non_null)( PyObject_CallFunction( - (PyObject*)&PyList_Type, "(O)", + (PyObject*)&PyList_Type, const_cast("(O)"), arg_.ptr())); } diff --git a/src/long.cpp b/src/long.cpp index a534bf29..1ec8ebc0 100644 --- a/src/long.cpp +++ b/src/long.cpp @@ -9,21 +9,21 @@ namespace boost { namespace python { namespace detail { new_non_null_reference long_base::call(object const& arg_) { return (detail::new_non_null_reference)PyObject_CallFunction( - (PyObject*)&PyLong_Type, "(O)", + (PyObject*)&PyLong_Type, const_cast("(O)"), arg_.ptr()); } new_non_null_reference long_base::call(object const& arg_, object const& base) { return (detail::new_non_null_reference)PyObject_CallFunction( - (PyObject*)&PyLong_Type, "(OO)", + (PyObject*)&PyLong_Type, const_cast("(OO)"), arg_.ptr(), base.ptr()); } long_base::long_base() : object( detail::new_reference( - PyObject_CallFunction((PyObject*)&PyLong_Type, "()")) + PyObject_CallFunction((PyObject*)&PyLong_Type, const_cast("()"))) ) {} diff --git a/src/object/class.cpp b/src/object/class.cpp index 9daf42b7..64d1d6d0 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -74,7 +74,7 @@ extern "C" { propertyobject *gs = (propertyobject *)self; - return PyObject_CallFunction(gs->prop_get, "()"); + return PyObject_CallFunction(gs->prop_get, const_cast("()")); } static int @@ -95,9 +95,9 @@ extern "C" return -1; } if (value == NULL) - res = PyObject_CallFunction(func, "()"); + res = PyObject_CallFunction(func, const_cast("()")); else - res = PyObject_CallFunction(func, "(O)", value); + res = PyObject_CallFunction(func, const_cast("(O)"), value); if (res == NULL) return -1; Py_DECREF(res); @@ -108,7 +108,7 @@ extern "C" static PyTypeObject static_data_object = { PyObject_HEAD_INIT(0)//&PyType_Type) 0, - "Boost.Python.StaticProperty", + const_cast("Boost.Python.StaticProperty"), PyType_Type.tp_basicsize, 0, 0, /* tp_dealloc */ @@ -212,7 +212,7 @@ extern "C" static PyTypeObject class_metatype_object = { PyObject_HEAD_INIT(0)//&PyType_Type) 0, - "Boost.Python.class", + const_cast("Boost.Python.class"), PyType_Type.tp_basicsize, 0, 0, /* tp_dealloc */ @@ -316,7 +316,7 @@ namespace objects { // Attempt to find the __instance_size__ attribute. If not present, no problem. PyObject* d = type_->tp_dict; - PyObject* instance_size_obj = PyObject_GetAttrString(d, "__instance_size__"); + PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast("__instance_size__")); long instance_size = instance_size_obj ? PyInt_AsLong(instance_size_obj) : 0; @@ -357,20 +357,20 @@ namespace objects static PyGetSetDef instance_getsets[] = { - {"__dict__", instance_get_dict, instance_set_dict, NULL, 0}, + {const_cast("__dict__"), instance_get_dict, instance_set_dict, NULL, 0}, {0, 0, 0, 0, 0} }; static PyMemberDef instance_members[] = { - {"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0, 0}, + {const_cast("__weakref__"), T_OBJECT, offsetof(instance<>, weakrefs), 0, 0}, {0, 0, 0, 0, 0} }; static PyTypeObject class_type_object = { PyObject_HEAD_INIT(0) //&class_metatype_object) 0, - "Boost.Python.instance", + const_cast("Boost.Python.instance"), offsetof(instance<>,storage), /* tp_basicsize */ 1, /* tp_itemsize */ instance_dealloc, /* tp_dealloc */ @@ -506,13 +506,12 @@ namespace objects // Build a tuple of the base Python type objects. If no bases // were declared, we'll use our class_type() as the single base // class. - std::size_t const num_bases = (std::max)(num_types - 1, static_cast(1)); - assert(num_bases <= ssize_t_max); - handle<> bases(PyTuple_New(static_cast(num_bases))); + ssize_t const num_bases = (std::max)(num_types - 1, static_cast(1)); + handle<> bases(PyTuple_New(num_bases)); - for (std::size_t i = 1; i <= num_bases; ++i) + for (ssize_t i = 1; i <= num_bases; ++i) { - type_handle c = (i >= num_types) ? class_type() : get_class(types[i]); + type_handle c = (i >= static_cast(num_types)) ? class_type() : get_class(types[i]); // PyTuple_SET_ITEM steals this reference PyTuple_SET_ITEM(bases.get(), static_cast(i - 1), upcast(c.release())); } @@ -572,7 +571,7 @@ namespace objects { object property( (python::detail::new_reference) - PyObject_CallFunction((PyObject*)&PyProperty_Type, "Osss", fget.ptr(), 0, 0, docstr)); + PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast("Osss"), fget.ptr(), 0, 0, docstr)); this->setattr(name, property); } @@ -582,7 +581,7 @@ namespace objects { object property( (python::detail::new_reference) - PyObject_CallFunction((PyObject*)&PyProperty_Type, "OOss", fget.ptr(), fset.ptr(), 0, docstr)); + PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast("OOss"), fget.ptr(), fset.ptr(), 0, docstr)); this->setattr(name, property); } @@ -591,7 +590,7 @@ namespace objects { object property( (python::detail::new_reference) - PyObject_CallFunction(static_data(), "O", fget.ptr())); + PyObject_CallFunction(static_data(), const_cast("O"), fget.ptr())); this->setattr(name, property); } @@ -600,7 +599,7 @@ namespace objects { object property( (python::detail::new_reference) - PyObject_CallFunction(static_data(), "OO", fget.ptr(), fset.ptr())); + PyObject_CallFunction(static_data(), const_cast("OO"), fget.ptr(), fset.ptr())); this->setattr(name, property); } @@ -615,13 +614,13 @@ namespace objects { extern "C" PyObject* no_init(PyObject*, PyObject*) { - ::PyErr_SetString(::PyExc_RuntimeError, "This class cannot be instantiated from Python"); + ::PyErr_SetString(::PyExc_RuntimeError, const_cast("This class cannot be instantiated from Python")); return NULL; } static ::PyMethodDef no_init_def = { - "__init__", no_init, METH_VARARGS, - "Raises an exception\n" - "This class cannot be instantiated from Python\n" + const_cast("__init__"), no_init, METH_VARARGS, + const_cast("Raises an exception\n" + "This class cannot be instantiated from Python\n") }; } @@ -650,7 +649,7 @@ namespace objects ::PyErr_Format( PyExc_TypeError - , "staticmethod expects callable object; got an object of type %s, which is not callable" + , const_cast("staticmethod expects callable object; got an object of type %s, which is not callable") , callable->ob_type->tp_name ); diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 2fb215ca..b4cc4984 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -14,7 +14,7 @@ #include #include -namespace boost { namespace python { namespace objects { +namespace boost { namespace python { namespace objects { struct enum_object { @@ -23,7 +23,7 @@ struct enum_object }; static PyMemberDef enum_members[] = { - {"name", T_OBJECT_EX, offsetof(enum_object,name),READONLY, 0}, + {const_cast("name"), T_OBJECT_EX, offsetof(enum_object,name),READONLY, 0}, {0, 0, 0, 0, 0} }; @@ -32,7 +32,7 @@ extern "C" { static PyObject* enum_repr(PyObject* self_) { - const char *mod = PyString_AsString(PyObject_GetAttrString( self_, "__module__")); + const char *mod = PyString_AsString(PyObject_GetAttrString( self_, const_cast("__module__"))); enum_object* self = downcast(self_); if (!self->name) { @@ -43,7 +43,7 @@ extern "C" char* name = PyString_AsString(self->name); if (name == 0) return 0; - + return PyString_FromFormat("%s.%s.%s", mod, self_->ob_type->tp_name, name); } } @@ -65,7 +65,7 @@ extern "C" static PyTypeObject enum_type_object = { PyObject_HEAD_INIT(0) // &PyType_Type 0, - "Boost.Python.enum", + const_cast("Boost.Python.enum"), sizeof(enum_object), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ @@ -139,15 +139,16 @@ namespace dict d; d["__slots__"] = tuple(); d["values"] = dict(); + d["names"] = dict(); 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); - + scope().attr(name) = result; return result; @@ -167,7 +168,7 @@ enum_base::enum_base( converter::registration& converters = const_cast( converter::registry::lookup(id)); - + converters.m_class_object = downcast(this->ptr()); converter::registry::insert(to_python, id); converter::registry::insert(convertible, construct, id); @@ -186,23 +187,24 @@ void enum_base::add_value(char const* name_, long value) dict d = extract(this->attr("values"))(); d[value] = x; - + // Set the name field in the new enum instanec enum_object* p = downcast(x.ptr()); Py_XDECREF(p->name); p->name = incref(name.ptr()); + + dict names_dict = extract(this->attr("names"))(); + names_dict[x.attr("name")] = x; } void enum_base::export_values() { - dict d = extract(this->attr("values"))(); - list values = d.values(); + dict d = extract(this->attr("names"))(); + list items = d.items(); scope current; - - for (unsigned i = 0, max = len(values); i < max; ++i) - { - api::setattr(current, object(values[i].attr("name")), values[i]); - } + + for (unsigned i = 0, max = len(items); i < max; ++i) + api::setattr(current, items[i][0], items[i][1]); } PyObject* enum_base::to_python(PyTypeObject* type_, long x) diff --git a/src/object/function.cpp b/src/object/function.cpp index 2285ae10..d49d0228 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -166,7 +166,7 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const else { // build a new arg tuple, will adjust its size later - assert(max_arity <= ssize_t_max); + assert(max_arity <= static_cast(ssize_t_max)); inner_args = handle<>( PyTuple_New(static_cast(max_arity))); @@ -297,7 +297,7 @@ object function::signatures(bool show_return_type) const void function::argument_error(PyObject* args, PyObject* /*keywords*/) const { static handle<> exception( - PyErr_NewException("Boost.Python.ArgumentError", PyExc_TypeError, 0)); + PyErr_NewException(const_cast("Boost.Python.ArgumentError"), PyExc_TypeError, 0)); object message = "Python argument types in\n %s.%s(" % make_tuple(this->m_namespace, this->m_name); @@ -440,7 +440,7 @@ void function::add_to_namespace( else if (PyType_Check(ns)) dict = ((PyTypeObject*)ns)->tp_dict; else - dict = PyObject_GetAttrString(ns, "__dict__"); + dict = PyObject_GetAttrString(ns, const_cast("__dict__")); if (dict == 0) throw_error_already_set(); @@ -487,7 +487,7 @@ void function::add_to_namespace( new_func->m_name = name; handle<> name_space_name( - allow_null(::PyObject_GetAttrString(name_space.ptr(), "__name__"))); + allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast("__name__")))); if (name_space_name) new_func->m_namespace = object(name_space_name); @@ -656,18 +656,18 @@ extern "C" } static PyGetSetDef function_getsetlist[] = { - {"__name__", (getter)function_get_name, 0, 0, 0 }, - {"func_name", (getter)function_get_name, 0, 0, 0 }, - {"__class__", (getter)function_get_class, 0, 0, 0 }, // see note above - {"__doc__", (getter)function_get_doc, (setter)function_set_doc, 0, 0}, - {"func_doc", (getter)function_get_doc, (setter)function_set_doc, 0, 0}, + {const_cast("__name__"), (getter)function_get_name, 0, 0, 0 }, + {const_cast("func_name"), (getter)function_get_name, 0, 0, 0 }, + {const_cast("__class__"), (getter)function_get_class, 0, 0, 0 }, // see note above + {const_cast("__doc__"), (getter)function_get_doc, (setter)function_set_doc, 0, 0}, + {const_cast("func_doc"), (getter)function_get_doc, (setter)function_set_doc, 0, 0}, {NULL, 0, 0, 0, 0} /* Sentinel */ }; PyTypeObject function_type = { PyObject_HEAD_INIT(0) 0, - "Boost.Python.function", + const_cast("Boost.Python.function"), sizeof(function), 0, (destructor)function_dealloc, /* tp_dealloc */ @@ -753,7 +753,8 @@ namespace detail } void BOOST_PYTHON_DECL pure_virtual_called() { - PyErr_SetString(PyExc_RuntimeError, "Pure virtual function called"); + PyErr_SetString( + PyExc_RuntimeError, const_cast("Pure virtual function called")); throw_error_already_set(); } } diff --git a/src/object/function_doc_signature.cpp b/src/object/function_doc_signature.cpp old mode 100755 new mode 100644 index 49f2c350..d6c8879a --- a/src/object/function_doc_signature.cpp +++ b/src/object/function_doc_signature.cpp @@ -52,9 +52,9 @@ namespace boost { namespace python { namespace objects { //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() + 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; } diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 7d542865..7dc9db1c 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -10,7 +10,7 @@ #endif #include #include -#include +#include #include #include #include diff --git a/src/object/life_support.cpp b/src/object/life_support.cpp index a1768cba..013253b5 100644 --- a/src/object/life_support.cpp +++ b/src/object/life_support.cpp @@ -38,7 +38,7 @@ extern "C" PyTypeObject life_support_type = { PyObject_HEAD_INIT(0)//(&PyType_Type) 0, - "Boost.Python.life_support", + const_cast("Boost.Python.life_support"), sizeof(life_support), 0, life_support_dealloc, /* tp_dealloc */ diff --git a/src/object/stl_iterator.cpp b/src/object/stl_iterator.cpp old mode 100755 new mode 100644 index e2b66cea..e32d3214 --- a/src/object/stl_iterator.cpp +++ b/src/object/stl_iterator.cpp @@ -2,6 +2,10 @@ // 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) +// +// Credits: +// Andreas Kl\:ockner for fixing increment() to handle +// error conditions. #include #include @@ -27,6 +31,8 @@ void stl_input_iterator_impl::increment() { this->ob_ = boost::python::handle<>( boost::python::allow_null(PyIter_Next(this->it_.ptr()))); + if (PyErr_Occurred()) + throw boost::python::error_already_set(); } bool stl_input_iterator_impl::equal(stl_input_iterator_impl const &that) const diff --git a/src/str.cpp b/src/str.cpp index 7ee748a3..ddde1a53 100644 --- a/src/str.cpp +++ b/src/str.cpp @@ -10,7 +10,7 @@ namespace boost { namespace python { namespace detail { detail::new_reference str_base::call(object const& arg_) { return (detail::new_reference)PyObject_CallFunction( - (PyObject*)&PyString_Type, "(O)", + (PyObject*)&PyString_Type, const_cast("(O)"), arg_.ptr()); } @@ -26,7 +26,7 @@ namespace { ssize_t str_size_as_py_ssize_t(std::size_t n) { - if (n > ssize_t_max) + if (n > static_cast(ssize_t_max)) { throw std::range_error("str size > ssize_t_max"); } @@ -68,8 +68,9 @@ str str_base:: name ( BOOST_PP_ENUM_PARAMS(arity, object_cref x) ) const return str(new_reference( \ expect_non_null( \ PyObject_CallMethod( \ - this->ptr(), #name, \ - "(" BOOST_PP_REPEAT(arity, BOOST_PYTHON_FORMAT_OBJECT, _) ")" \ + this->ptr(), const_cast( #name ), \ + const_cast( \ + "(" BOOST_PP_REPEAT(arity, BOOST_PYTHON_FORMAT_OBJECT, _) ")") \ BOOST_PP_REPEAT_1(arity, BOOST_PYTHON_OBJECT_PTR, _))))); \ } diff --git a/src/tuple.cpp b/src/tuple.cpp index b5696504..6719713b 100644 --- a/src/tuple.cpp +++ b/src/tuple.cpp @@ -9,7 +9,7 @@ namespace boost { namespace python { namespace detail { detail::new_reference tuple_base::call(object const& arg_) { return (detail::new_reference)PyObject_CallFunction( - (PyObject*)&PyTuple_Type, "(O)", + (PyObject*)&PyTuple_Type, const_cast("(O)"), arg_.ptr()); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c9ea1958..d28a7595 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,25 +19,43 @@ macro(bpl_test TESTNAME) cdr(BPL_TEST_DEFAULT_ARGS ${BPL_TEST_DEFAULT_ARGS}) get_filename_component(BPL_TEST_PYBASE ${BPL_TEST_PYSOURCE} NAME_WE) + + # Process all the .cpp file and extension module names 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}) + set(BPL_EXTENSION_MODULE ${BPL_SRC_NAME}_ext) else(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}") - boost_python_extension(${BPL_SRC_NAME} ${SRC}) + set(BPL_EXTENSION_MODULE ${BPL_SRC_NAME}) endif(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}") + + boost_python_extension(${BPL_EXTENSION_MODULE} ${SRC}) + + else (BPL_SRC_EXT STREQUAL ".cpp") + set(BPL_EXTENSION_MODULE ${SRC}) + endif (BPL_SRC_EXT STREQUAL ".cpp") + + add_dependencies(${PROJECT_NAME}-test ${BPL_EXTENSION_MODULE}) 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") + add_dependencies(${PROJECT_NAME}-test ${TESTNAME}_ext) + endif(BPL_TEST_DEFAULT_ARGS) + add_dependencies(${PROJECT_NAME}-test ${BPL_TEST_PYSOURCE}) + # We'll need the full patch to run the Python test set(BPL_TEST_PYSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${BPL_TEST_PYSOURCE}) @@ -107,6 +125,13 @@ 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) +# +# See the contents of this file for more details on an existing +# overload resoluton bug. +# +# boost_python_extension(overload_resolution test_overload_resolution.cpp) +# + bpl_test(test_pointer_adoption) bpl_test(operators) bpl_test(callbacks) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 3e4f3cc1..5f66be63 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -42,7 +42,7 @@ test-suite python : [ - run exec.cpp ../build//boost_python/static $(PY) + run exec.cpp /boost/python//boost_python/static $(PY) : # program args : exec.py # input files : # requirements @@ -75,6 +75,7 @@ bpl-test crossmod_exception [ bpl-test return_arg ] [ bpl-test staticmethod ] [ bpl-test shared_ptr ] +[ bpl-test enable_shared_from_this ] [ bpl-test andreas_beyer ] [ bpl-test polymorphism ] [ bpl-test polymorphism2 ] @@ -171,7 +172,8 @@ bpl-test crossmod_opaque /boost/python//boost_python ] [ bpl-test map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ] -[ py-run import_.cpp : import_.py ] + +[ run import_.cpp /boost/python//boost_python $(PY) : : import_.py ] # if $(TEST_BIENSTMAN_NON_BUGS) # { diff --git a/test/andreas_beyer.cpp b/test/andreas_beyer.cpp old mode 100755 new mode 100644 index da3aa751..b28b1566 --- a/test/andreas_beyer.cpp +++ b/test/andreas_beyer.cpp @@ -25,8 +25,8 @@ class B { B() { a = A::A_ptr(new A()); } - void set(A::A_ptr a) { - this->a = a; + void set(A::A_ptr _a) { + this->a = _a; } A::A_ptr get() { return a; diff --git a/test/back_reference.cpp b/test/back_reference.cpp index b5d1378c..266ed291 100644 --- a/test/back_reference.cpp +++ b/test/back_reference.cpp @@ -27,7 +27,7 @@ struct X X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } - void set(int x) { BOOST_ASSERT(magic == 7654321); this->x = x; } + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } int value() const { BOOST_ASSERT(magic == 7654321); return x; } static int count() { return counter; } private: diff --git a/test/callbacks.cpp b/test/callbacks.cpp index 255ed1b7..66bd3524 100644 --- a/test/callbacks.cpp +++ b/test/callbacks.cpp @@ -34,7 +34,7 @@ struct X X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } - void set(int x) { BOOST_ASSERT(magic == 7654321); this->x = x; } + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } int value() const { BOOST_ASSERT(magic == 7654321); return x; } static int count() { return counter; } private: diff --git a/test/complicated.hpp b/test/complicated.hpp index 5c15e80a..5ff19aea 100644 --- a/test/complicated.hpp +++ b/test/complicated.hpp @@ -19,10 +19,10 @@ struct complicated int n; }; -inline complicated::complicated(simple const&s, int n) - : s(s.s), n(n) +inline complicated::complicated(simple const&s, int _n) + : s(s.s), n(_n) { - std::cout << "constructing complicated: " << this->s << ", " << n << std::endl; + std::cout << "constructing complicated: " << this->s << ", " << _n << std::endl; } inline complicated::~complicated() diff --git a/test/enable_shared_from_this.cpp b/test/enable_shared_from_this.cpp new file mode 100644 index 00000000..c246284a --- /dev/null +++ b/test/enable_shared_from_this.cpp @@ -0,0 +1,48 @@ +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include "test_class.hpp" + +#include + +using namespace boost::python; +using boost::shared_ptr; + +class Test; +typedef shared_ptr TestPtr; + +class Test : public boost::enable_shared_from_this { +public: + static TestPtr construct() { + return TestPtr(new Test); + } + + void act() { + TestPtr kungFuDeathGrip(shared_from_this()); + } + + void take(TestPtr t) { + } +}; + +BOOST_PYTHON_MODULE(enable_shared_from_this_ext) +{ + class_("Test") + .def("construct", &Test::construct).staticmethod("construct") + .def("act", &Test::act) + .def("take", &Test::take) + ; +} + +#include "module_tail.cpp" + + diff --git a/test/enable_shared_from_this.py b/test/enable_shared_from_this.py new file mode 100755 index 00000000..cca46ec8 --- /dev/null +++ b/test/enable_shared_from_this.py @@ -0,0 +1,26 @@ +# 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 enable_shared_from_this_ext import * + +>>> x = Test.construct() +>>> x.take(x) +>>> x.act() +''' + +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) + diff --git a/test/enum.cpp b/test/enum.cpp index 5719bc39..e5c4f4fa 100644 --- a/test/enum.cpp +++ b/test/enum.cpp @@ -12,7 +12,7 @@ #endif using namespace boost::python; -enum color { red = 1, green = 2, blue = 4 }; +enum color { red = 1, green = 2, blue = 4, blood = 1 }; #if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) namespace boost // Pro7 has a hard time detecting enums @@ -34,6 +34,7 @@ BOOST_PYTHON_MODULE(enum_ext) .value("red", red) .value("green", green) .value("blue", blue) + .value("blood", blood) .export_values() ; diff --git a/test/enum.py b/test/enum.py index b78160ec..c3ba3fe7 100644 --- a/test/enum.py +++ b/test/enum.py @@ -4,8 +4,8 @@ ''' >>> from enum_ext import * ->>> identity(color.red) -enum_ext.color.red +>>> identity(color.red) # in case of duplicated enums it always take the last enum +enum_ext.color.blood >>> identity(color.green) enum_ext.color.green @@ -13,8 +13,8 @@ enum_ext.color.green >>> identity(color.blue) enum_ext.color.blue ->>> identity(color(1)) -enum_ext.color.red +>>> identity(color(1)) # in case of duplicated enums it always take the last enum +enum_ext.color.blood >>> identity(color(2)) enum_ext.color.green @@ -28,7 +28,7 @@ enum_ext.color.blue --- check export to scope --- >>> identity(red) -enum_ext.color.red +enum_ext.color.blood >>> identity(green) enum_ext.color.green @@ -42,10 +42,18 @@ enum_ext.color.blue >>> c = colorized() >>> c.x -enum_ext.color.red +enum_ext.color.blood >>> c.x = green >>> c.x enum_ext.color.green +>>> red == blood +True +>>> red == green +False +>>> hash(red) == hash(blood) +True +>>> hash(red) == hash(green) +False ''' # pickling of enums only works with Python 2.3 or higher diff --git a/test/exec.cpp b/test/exec.cpp index bad33c6f..31883d89 100644 --- a/test/exec.cpp +++ b/test/exec.cpp @@ -59,7 +59,7 @@ void eval_test() void exec_test() { // Register the module with the interpreter - if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1) + if (PyImport_AppendInittab(const_cast("embedded_hello"), initembedded_hello) == -1) throw std::runtime_error("Failed to add embedded_hello to the interpreter's " "builtin modules"); // Retrieve the main module diff --git a/test/m1.cpp b/test/m1.cpp index 407924fe..ff075076 100644 --- a/test/m1.cpp +++ b/test/m1.cpp @@ -34,7 +34,7 @@ struct NoddyObject : PyObject PyTypeObject NoddyType = { PyObject_HEAD_INIT(NULL) 0, - "Noddy", + const_cast("Noddy"), sizeof(NoddyObject), 0, dealloc, /* tp_dealloc */ @@ -106,7 +106,7 @@ struct extract_simple_object PyTypeObject SimpleType = { PyObject_HEAD_INIT(NULL) 0, - "Simple", + const_cast("Simple"), sizeof(SimpleObject), 0, dealloc, /* tp_dealloc */ @@ -159,7 +159,7 @@ PyTypeObject SimpleType = { PyObject* new_simple() { SimpleObject* simple = PyObject_New(SimpleObject, &SimpleType); - simple->x.s = "hello, world"; + simple->x.s = const_cast("hello, world"); return (PyObject*)simple; } diff --git a/test/object.cpp b/test/object.cpp index 04afe841..b1f01518 100644 --- a/test/object.cpp +++ b/test/object.cpp @@ -187,6 +187,11 @@ 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; @@ -377,6 +382,7 @@ BOOST_PYTHON_MODULE(object_ext) 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); diff --git a/test/object.py b/test/object.py index 82634082..84972e64 100644 --- a/test/object.py +++ b/test/object.py @@ -134,7 +134,12 @@ 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 diff --git a/test/pickle1.cpp b/test/pickle1.cpp index 28845fc9..7988f211 100644 --- a/test/pickle1.cpp +++ b/test/pickle1.cpp @@ -27,8 +27,8 @@ namespace boost_python_test { private: std::string country; public: - world(const std::string& country) { - this->country = country; + world(const std::string& _country) { + this->country = _country; } std::string greet() const { return "Hello from " + country + "!"; } std::string get_country() const { return country; } diff --git a/test/pickle2.cpp b/test/pickle2.cpp index 1c08cbd0..7cdf05f0 100644 --- a/test/pickle2.cpp +++ b/test/pickle2.cpp @@ -34,8 +34,8 @@ namespace boost_python_test { class world { public: - world(const std::string& country) : secret_number(0) { - this->country = country; + world(const std::string& _country) : secret_number(0) { + this->country = _country; } std::string greet() const { return "Hello from " + country + "!"; } std::string get_country() const { return country; } diff --git a/test/pickle3.cpp b/test/pickle3.cpp index 6472def8..14b0dbdd 100644 --- a/test/pickle3.cpp +++ b/test/pickle3.cpp @@ -35,8 +35,8 @@ namespace boost_python_test { class world { public: - world(const std::string& country) : secret_number(0) { - this->country = country; + world(const std::string& _country) : secret_number(0) { + this->country = _country; } std::string greet() const { return "Hello from " + country + "!"; } std::string get_country() const { return country; } diff --git a/test/pickle4.cpp b/test/pickle4.cpp index d9758c28..1374cc7d 100644 --- a/test/pickle4.cpp +++ b/test/pickle4.cpp @@ -23,8 +23,8 @@ namespace boost_python_test { private: std::string country; public: - world(const std::string& country) { - this->country = country; + world(const std::string& _country) { + this->country = _country; } std::string greet() const { return "Hello from " + country + "!"; } std::string get_country() const { return country; } diff --git a/test/slice.cpp b/test/slice.cpp index 8b1d1bf5..032bf7cf 100644 --- a/test/slice.cpp +++ b/test/slice.cpp @@ -100,7 +100,11 @@ bool accept_slice( slice) { return true; } || BOOST_WORKAROUND( BOOST_INTEL_WIN, == 710) int check_slice_get_indicies(slice index); #endif -int check_slice_get_indicies(const slice index) +int check_slice_get_indicies( +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + const +#endif + slice index) { // A vector of integers from [-5, 5]. std::vector coll(11); diff --git a/test/staticmethod.cpp b/test/staticmethod.cpp index 5947e538..dcd75ca8 100644 --- a/test/staticmethod.cpp +++ b/test/staticmethod.cpp @@ -20,7 +20,7 @@ struct X X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } - void set(int x) { BOOST_ASSERT(magic == 7654321); this->x = x; } + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } int value() const { BOOST_ASSERT(magic == 7654321); return x; } static int count() { return counter; } private: diff --git a/test/stl_iterator.py b/test/stl_iterator.py index c044e85a..2c324c0a 100644 --- a/test/stl_iterator.py +++ b/test/stl_iterator.py @@ -12,6 +12,16 @@ 3 4 5 +>>> def generator(): +... yield 1 +... yield 2 +... raise RuntimeError, "oops" +>>> try: +... x.assign(iter(generator())) +... print "NOT OK" +... except RuntimeError: +... print "OK" +OK ''' def run(args = None): import sys diff --git a/test/test_builtin_converters.cpp b/test/test_builtin_converters.cpp index daefe561..f66e61bd 100644 --- a/test/test_builtin_converters.cpp +++ b/test/test_builtin_converters.cpp @@ -17,6 +17,10 @@ struct by_value { return x; } + static int size(void) + { + return sizeof(T); + } }; template @@ -61,7 +65,17 @@ BOOST_PYTHON_MODULE(builtin_converters_ext) { def("get_type", get_type); def("return_null_handle", return_null_handle); - + +// These methods are used solely for getting some C++ type sizes + def("bool_size", by_value::size); + def("char_size", by_value::size); + def("int_size", by_value::size); + def("short_size", by_value::size); + def("long_size", by_value::size); +#ifdef HAVE_LONG_LONG + def("long_long_size", by_value::size); +#endif + def("rewrap_value_bool", by_value::rewrap); def("rewrap_value_char", by_value::rewrap); def("rewrap_value_signed_char", by_value::rewrap); diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index 3bfce5b8..7b0084fa 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -4,12 +4,33 @@ r""" >>> from builtin_converters_ext import * +# Provide values for integer converter tests +>>> def _signed_values(s): +... base = 2 ** (8 * s - 1) +... return [[-base, -1, 1, base - 1], [-base - 1, base]] +>>> def _unsigned_values(s): +... base = 2 ** (8 * s) +... return [[1, base - 1], [-1L, -1, base]] + +# Wrappers to simplify tests +>>> def should_pass(method, values): +... result = map(method, values[0]) +... if result != values[0]: +... print "Got %s but expected %s" % (result, values[0]) +>>> def test_overflow(method, values): +... for v in values[1]: +... try: method(v) +... except OverflowError: pass +... else: print "OverflowError expected" + # Synthesize idendity functions in case long long not supported >>> if not 'rewrap_value_long_long' in dir(): ... def rewrap_value_long_long(x): return long(x) ... def rewrap_value_unsigned_long_long(x): return long(x) ... def rewrap_const_reference_long_long(x): return long(x) ... def rewrap_const_reference_unsigned_long_long(x): return long(x) +>>> if not 'long_long_size' in dir(): +... def long_long_size(): return long_size() >>> try: bool_exists = bool ... except: pass @@ -62,15 +83,37 @@ False 42L show that we have range checking. - ->>> try: rewrap_value_unsigned_short(-42) -... except OverflowError: pass -... else: print 'expected an OverflowError!' ->>> try: rewrap_value_int(sys.maxint * 2) -... except OverflowError: pass -... else: print 'expected an OverflowError!' +>>> should_pass(rewrap_value_signed_char, _signed_values(char_size())) +>>> should_pass(rewrap_value_short, _signed_values(short_size())) +>>> should_pass(rewrap_value_int, _signed_values(int_size())) +>>> should_pass(rewrap_value_long, _signed_values(long_size())) +>>> should_pass(rewrap_value_long_long, _signed_values(long_long_size())) +>>> should_pass(rewrap_value_unsigned_char, _unsigned_values(char_size())) +>>> should_pass(rewrap_value_unsigned_short, _unsigned_values(short_size())) +>>> should_pass(rewrap_value_unsigned_int, _unsigned_values(int_size())) +>>> should_pass(rewrap_value_unsigned_long, _unsigned_values(long_size())) +>>> should_pass(rewrap_value_unsigned_long_long, +... _unsigned_values(long_long_size())) + +>>> test_overflow(rewrap_value_signed_char, _signed_values(char_size())) +>>> test_overflow(rewrap_value_short, _signed_values(short_size())) +>>> test_overflow(rewrap_value_int, _signed_values(int_size())) +>>> test_overflow(rewrap_value_long, _signed_values(long_size())) +>>> test_overflow(rewrap_value_long_long, _signed_values(long_long_size())) + +>>> test_overflow(rewrap_value_unsigned_char, _unsigned_values(char_size())) +>>> test_overflow(rewrap_value_unsigned_short, _unsigned_values(short_size())) +>>> test_overflow(rewrap_value_unsigned_int, _unsigned_values(int_size())) +>>> test_overflow(rewrap_value_unsigned_long, _unsigned_values(long_size())) + +# Exceptionally for PyLong_AsUnsignedLongLong(), a negative value raises +# TypeError on Python versions prior to 2.7 +>>> for v in _unsigned_values(long_long_size())[1]: +... try: rewrap_value_unsigned_long_long(v) +... except (OverflowError, TypeError): pass +... else: print "OverflowError or TypeError expected" >>> assert abs(rewrap_value_float(4.2) - 4.2) < .000001 >>> rewrap_value_double(4.2) - 4.2 diff --git a/test/test_class.hpp b/test/test_class.hpp index 6eb5e1e4..5404fdba 100644 --- a/test/test_class.hpp +++ b/test/test_class.hpp @@ -13,7 +13,7 @@ struct test_class test_class(test_class const& rhs) : x(rhs.x), magic(7654321 + n) { ++counter; } virtual ~test_class() { BOOST_TEST(magic == 7654321 + n); magic = 6666666; x = 9999; --counter; } - void set(int x) { BOOST_TEST(magic == 7654321 + n); this->x = x; } + void set(int _x) { BOOST_TEST(magic == 7654321 + n); this->x = _x; } int value() const { BOOST_TEST(magic == 7654321 + n); return x; } operator int() const { return x; } static int count() { return counter; } diff --git a/test/test_overload_resolution.cpp b/test/test_overload_resolution.cpp new file mode 100644 index 00000000..e15bcc6a --- /dev/null +++ b/test/test_overload_resolution.cpp @@ -0,0 +1,53 @@ +// Copyright Troy D. Straszheim 2009 +// 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) +// +// +// example that shows problems with overloading and automatic conversion. +// if you call one of the below functions from python with bool/int/double, +// you'll see that the overload called is first match, not best match. +// See overload matching in luabind for an example of how to do this better. +// +// see this mail: +// http://mail.python.org/pipermail/cplusplus-sig/2009-March/014362.html +// +// This test isn't called by the cmake/jamfiles. For future use. +// +#include +#include +#include +#include +#include +#include +#include + +using boost::python::def; +using boost::python::handle; +using boost::python::object; +using boost::python::borrowed; + +std::string takes_bool(bool b) { return "bool"; } +std::string takes_int(int b) { return "int"; } +std::string takes_double(double b) { return "double"; } + + +BOOST_PYTHON_MODULE(overload_resolution) +{ + def("bid", takes_bool); + def("bid", takes_int); + def("bid", takes_double); + + def("dib", takes_double); + def("dib", takes_int); + def("dib", takes_bool); + + def("idb", takes_int); + def("idb", takes_double); + def("idb", takes_bool); + + def("bdi", takes_bool); + def("bdi", takes_double); + def("bdi", takes_int); +} + diff --git a/test/test_pointer_adoption.cpp b/test/test_pointer_adoption.cpp index eeda8a9b..a4e14af5 100644 --- a/test/test_pointer_adoption.cpp +++ b/test/test_pointer_adoption.cpp @@ -65,7 +65,7 @@ struct B B() : x(0) {} B(A* x_) : x(x_) {} - inner const* adopt(A* x) { this->x = x; return &x->get_inner(); } + inner const* adopt(A* _x) { this->x = _x; return &_x->get_inner(); } std::string a_content() { diff --git a/test/virtual_functions.cpp b/test/virtual_functions.cpp index d871192a..774b11b1 100644 --- a/test/virtual_functions.cpp +++ b/test/virtual_functions.cpp @@ -22,7 +22,7 @@ struct X X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; } virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; } - void set(int x) { BOOST_ASSERT(magic == 7654321); this->x = x; } + void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; } int value() const { BOOST_ASSERT(magic == 7654321); return x; } static int count() { return counter; } private: