Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r56806 - in branches/release: boost/python boost/python/converter boost/python/detail boost/python/object libs/python libs/python/build libs/python/doc libs/python/src libs/python/src/converter libs/python/src/object libs/python/test
From: rwgk_at_[hidden]
Date: 2009-10-13 18:38:05


Author: rwgk
Date: 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
New Revision: 56806
URL: http://svn.boost.org/trac/boost/changeset/56806

Log:
boost/python, libs/python: all changes from trunk merged into branches/release
Properties modified:
   branches/release/boost/python/ (props changed)
   branches/release/libs/python/ (props changed)
Text files modified:
   branches/release/boost/python/converter/builtin_converters.hpp | 22 +++++
   branches/release/boost/python/converter/pyobject_traits.hpp | 2
   branches/release/boost/python/detail/operator_id.hpp | 4 +
   branches/release/boost/python/detail/wrap_python.hpp | 13 +++
   branches/release/boost/python/enum.hpp | 4 +
   branches/release/boost/python/exec.hpp | 7 +
   branches/release/boost/python/list.hpp | 12 ++
   branches/release/boost/python/lvalue_from_pytype.hpp | 4
   branches/release/boost/python/module_init.hpp | 39 ++++++---
   branches/release/boost/python/object/iterator.hpp | 4 +
   branches/release/boost/python/object/make_instance.hpp | 2
   branches/release/boost/python/object_core.hpp | 13 +++
   branches/release/boost/python/opaque_pointer_converter.hpp | 3
   branches/release/boost/python/operators.hpp | 4 +
   branches/release/boost/python/str.hpp | 8 ++
   branches/release/libs/python/build/Jamfile.v2 | 152 +++++++++++++++++++++++----------------
   branches/release/libs/python/doc/news.html | 36 +++++++++
   branches/release/libs/python/src/converter/builtin_converters.cpp | 121 ++++++++++++++++++++++++++++---
   branches/release/libs/python/src/converter/from_python.cpp | 21 ++++
   branches/release/libs/python/src/converter/registry.cpp | 7 +
   branches/release/libs/python/src/dict.cpp | 2
   branches/release/libs/python/src/exec.cpp | 10 ++
   branches/release/libs/python/src/list.cpp | 22 +++++
   branches/release/libs/python/src/module.cpp | 19 ++++
   branches/release/libs/python/src/object/class.cpp | 99 +++++++++++++++++++------
   branches/release/libs/python/src/object/enum.cpp | 40 ++++++++-
   branches/release/libs/python/src/object/function.cpp | 26 +++++-
   branches/release/libs/python/src/object/life_support.cpp | 7 -
   branches/release/libs/python/src/object_operators.cpp | 11 ++
   branches/release/libs/python/src/object_protocol.cpp | 10 ++
   branches/release/libs/python/src/str.cpp | 105 ++++++++++++++++++--------
   branches/release/libs/python/test/Jamfile.v2 | 9 +
   branches/release/libs/python/test/a_map_indexing_suite.cpp | 8 ++
   branches/release/libs/python/test/crossmod_opaque.py | 2
   branches/release/libs/python/test/defaults.py | 7 -
   branches/release/libs/python/test/dict.py | 2
   branches/release/libs/python/test/exec.cpp | 10 ++
   branches/release/libs/python/test/exec.py | 4
   branches/release/libs/python/test/iterator.py | 2
   branches/release/libs/python/test/list.cpp | 7 +
   branches/release/libs/python/test/list.py | 6
   branches/release/libs/python/test/long.py | 12 +-
   branches/release/libs/python/test/m1.cpp | 6 -
   branches/release/libs/python/test/m2.cpp | 10 ++
   branches/release/libs/python/test/map_indexing_suite.py | 2
   branches/release/libs/python/test/opaque.py | 2
   branches/release/libs/python/test/pickle2.py | 2
   branches/release/libs/python/test/str.cpp | 5 +
   branches/release/libs/python/test/str.py | 2
   branches/release/libs/python/test/test_builtin_converters.py | 36 +++------
   branches/release/libs/python/test/tuple.py | 2
   branches/release/libs/python/test/upcast.cpp | 4
   52 files changed, 722 insertions(+), 247 deletions(-)

Modified: branches/release/boost/python/converter/builtin_converters.hpp
==============================================================================
--- branches/release/boost/python/converter/builtin_converters.hpp (original)
+++ branches/release/boost/python/converter/builtin_converters.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -90,6 +90,14 @@
         BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
 
 // Specialize converters for signed and unsigned T to Python Int
+#if PY_VERSION_HEX >= 0x03000000
+
+# define BOOST_PYTHON_TO_INT(T) \
+ BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyLong_FromLong(x), &PyLong_Type) \
+ BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, ::PyLong_FromUnsignedLong(x), &PyLong_Type)
+
+#else
+
 # define BOOST_PYTHON_TO_INT(T) \
     BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x), &PyInt_Type) \
     BOOST_PYTHON_TO_PYTHON_BY_VALUE( \
@@ -98,6 +106,7 @@
                 (std::numeric_limits<long>::max)()) \
         ? ::PyLong_FromUnsignedLong(x) \
         : ::PyInt_FromLong(x), &PyInt_Type)
+#endif
 
 // Bool is not signed.
 #if PY_VERSION_HEX >= 0x02030000
@@ -116,17 +125,24 @@
 // using Python's macro instead of Boost's - we don't seem to get the
 // config right all the time.
 # ifdef HAVE_LONG_LONG
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x), &PyInt_Type)
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyInt_Type)
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x), &PyLong_Type)
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyLong_Type)
 # endif
     
 # undef BOOST_TO_PYTHON_INT
 
+#if PY_VERSION_HEX >= 0x03000000
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyUnicode_Type)
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyUnicode_Type)
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyUnicode_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyUnicode_Type)
+#else
 BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyString_Type)
 BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyString_Type)
 BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type)
+#endif
+
 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
-BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type)
+BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())), &PyUnicode_Type)
 # endif
 BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x), &PyFloat_Type)
 BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x), &PyFloat_Type)

Modified: branches/release/boost/python/converter/pyobject_traits.hpp
==============================================================================
--- branches/release/boost/python/converter/pyobject_traits.hpp (original)
+++ branches/release/boost/python/converter/pyobject_traits.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -34,7 +34,9 @@
 // This is not an exhaustive list; should be expanded.
 BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type);
 BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List);
+#if PY_VERSION_HEX < 0x03000000
 BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int);
+#endif
 BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long);
 BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict);
 BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple);

Modified: branches/release/boost/python/detail/operator_id.hpp
==============================================================================
--- branches/release/boost/python/detail/operator_id.hpp (original)
+++ branches/release/boost/python/detail/operator_id.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -47,7 +47,11 @@
     op_ixor,
     op_ior,
     op_complex,
+#if PY_VERSION_HEX >= 0x03000000
+ op_bool,
+#else
     op_nonzero,
+#endif
     op_repr
 };
 

Modified: branches/release/boost/python/detail/wrap_python.hpp
==============================================================================
--- branches/release/boost/python/detail/wrap_python.hpp (original)
+++ branches/release/boost/python/detail/wrap_python.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -175,6 +175,19 @@
         ( (op)->ob_type = (typeobj), _Py_NewReference((PyObject *)(op)), (op) )
 #endif
 
+// Define Python 3 macros for Python 2.x
+#if PY_VERSION_HEX < 0x02060000
+
+# define Py_TYPE(o) (((PyObject*)(o))->ob_type)
+# define Py_REFCNT(o) (((PyObject*)(o))->ob_refcnt)
+# define Py_SIZE(o) (((PyVarObject*)(o))->ob_size)
+
+# define PyVarObject_HEAD_INIT(type, size) \
+ PyObject_HEAD_INIT(type) size,
+
+#endif
+
+
 #ifdef __MWERKS__
 # pragma warn_possunwant off
 #elif _MSC_VER

Modified: branches/release/boost/python/enum.hpp
==============================================================================
--- branches/release/boost/python/enum.hpp (original)
+++ branches/release/boost/python/enum.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -79,7 +79,11 @@
 template <class T>
 void enum_<T>::construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data)
 {
+#if PY_VERSION_HEX >= 0x03000000
+ T x = static_cast<T>(PyLong_AS_LONG(obj));
+#else
     T x = static_cast<T>(PyInt_AS_LONG(obj));
+#endif
     void* const storage = ((converter::rvalue_from_python_storage<T>*)data)->storage.bytes;
     new (storage) T(x);
     data->convertible = storage;

Modified: branches/release/boost/python/exec.hpp
==============================================================================
--- branches/release/boost/python/exec.hpp (original)
+++ branches/release/boost/python/exec.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -20,6 +20,13 @@
 BOOST_PYTHON_DECL
 eval(str string, object global = object(), object local = object());
 
+// Execute an individual python statement from str.
+// global and local are the global and local scopes respectively,
+// used during execution.
+object
+BOOST_PYTHON_DECL
+exec_statement(str string, object global = object(), object local = object());
+
 // Execute python source code from str.
 // global and local are the global and local scopes respectively,
 // used during execution.

Modified: branches/release/boost/python/list.hpp
==============================================================================
--- branches/release/boost/python/list.hpp (original)
+++ branches/release/boost/python/list.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -19,7 +19,7 @@
   {
       void append(object_cref); // append object to end
 
- long count(object_cref value) const; // return number of occurrences of value
+ ssize_t count(object_cref value) const; // return number of occurrences of value
 
       void extend(object_cref sequence); // extend list by appending sequence elements
     
@@ -37,8 +37,12 @@
       void reverse(); // reverse *IN PLACE*
 
       void sort(); // sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1
+#if PY_VERSION_HEX >= 0x03000000
+ void sort(args_proxy const &args,
+ kwds_proxy const &kwds);
+#else
       void sort(object_cref cmpfunc);
-
+#endif
 
    protected:
       list_base(); // new list
@@ -113,13 +117,15 @@
         base::remove(object(value));
     }
 
+#if PY_VERSION_HEX <= 0x03000000
     void sort() { base::sort(); }
-
+
     template <class T>
     void sort(T const& value)
     {
         base::sort(object(value));
     }
+#endif
     
  public: // implementation detail -- for internal use only
     BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list, base)

Modified: branches/release/boost/python/lvalue_from_pytype.hpp
==============================================================================
--- branches/release/boost/python/lvalue_from_pytype.hpp (original)
+++ branches/release/boost/python/lvalue_from_pytype.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -63,7 +63,7 @@
 {
     static MemberType& execute(InstanceType& c)
     {
- (void)c.ob_type; // static assertion
+ (void)Py_TYPE(&c); // static assertion
         return c.*member;
     }
 };
@@ -75,7 +75,7 @@
 {
     static InstanceType& execute(InstanceType& c)
     {
- (void)c.ob_type; // static assertion
+ (void)Py_TYPE(&c); // static assertion
         return c;
     }
 };

Modified: branches/release/boost/python/module_init.hpp
==============================================================================
--- branches/release/boost/python/module_init.hpp (original)
+++ branches/release/boost/python/module_init.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -11,40 +11,49 @@
 
 namespace boost { namespace python { namespace detail {
 
-BOOST_PYTHON_DECL void init_module(char const* name, void(*)());
+BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)());
 
 }}}
 
-# if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(BOOST_PYTHON_STATIC_MODULE)
+# if PY_VERSION_HEX >= 0x03000000
+
+# define _BOOST_PYTHON_MODULE_INIT(name) \
+PyObject* PyInit_##name() \
+{ \
+ return boost::python::detail::init_module( \
+ #name,&init_module_##name); \
+} \
+void init_module_##name()
+
+# else
 
-# define BOOST_PYTHON_MODULE_INIT(name) \
-void init_module_##name(); \
-extern "C" __declspec(dllexport) void init##name() \
+# define _BOOST_PYTHON_MODULE_INIT(name) \
+void init##name() \
 { \
     boost::python::detail::init_module( \
         #name,&init_module_##name); \
 } \
 void init_module_##name()
 
+# endif
+
+# if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(BOOST_PYTHON_STATIC_MODULE)
+
+# define BOOST_PYTHON_MODULE_INIT(name) \
+void init_module_##name(); \
+extern "C" __declspec(dllexport) _BOOST_PYTHON_MODULE_INIT(name)
+
 # elif BOOST_PYTHON_USE_GCC_SYMBOL_VISIBILITY
 
 # define BOOST_PYTHON_MODULE_INIT(name) \
 void init_module_##name(); \
-extern "C" __attribute__ ((visibility("default"))) void init##name() \
-{ \
- boost::python::detail::init_module(#name, &init_module_##name); \
-} \
-void init_module_##name()
+extern "C" __attribute__ ((visibility("default"))) _BOOST_PYTHON_MODULE_INIT(name)
 
 # else
 
 # define BOOST_PYTHON_MODULE_INIT(name) \
 void init_module_##name(); \
-extern "C" void init##name() \
-{ \
- boost::python::detail::init_module(#name, &init_module_##name); \
-} \
-void init_module_##name()
+extern "C" _BOOST_PYTHON_MODULE_INIT(name)
 
 # endif
 

Modified: branches/release/boost/python/object/iterator.hpp
==============================================================================
--- branches/release/boost/python/object/iterator.hpp (original)
+++ branches/release/boost/python/object/iterator.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -129,7 +129,11 @@
       return class_<range_>(name, no_init)
           .def("__iter__", identity_function())
           .def(
+#if PY_VERSION_HEX >= 0x03000000
+ "__next__"
+#else
               "next"
+#endif
             , make_function(
                 next_fn()
               , policies

Modified: branches/release/boost/python/object/make_instance.hpp
==============================================================================
--- branches/release/boost/python/object/make_instance.hpp (original)
+++ branches/release/boost/python/object/make_instance.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -43,7 +43,7 @@
               
             // Note the position of the internally-stored Holder,
             // for the sake of destruction
- instance->ob_size = offsetof(instance_t, storage);
+ Py_SIZE(instance) = offsetof(instance_t, storage);
 
             // Release ownership of the python object
             protect.cancel();

Modified: branches/release/boost/python/object_core.hpp
==============================================================================
--- branches/release/boost/python/object_core.hpp (original)
+++ branches/release/boost/python/object_core.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -126,6 +126,10 @@
       const_object_objattribute attr(object const&) const;
       object_objattribute attr(object const&);
 
+ // Wrap 'in' operator (aka. __contains__)
+ template <class T>
+ object contains(T const& key) const;
+
       // item access
       //
       const_object_item operator[](object_cref) const;
@@ -483,6 +487,15 @@
  
 }
 
+
+template <typename U>
+template <class T>
+object api::object_operators<U>::contains(T const& key) const
+{
+ return this->attr("__contains__")(object(key));
+}
+
+
 inline object::object()
     : object_base(python::incref(Py_None))
 {}

Modified: branches/release/boost/python/opaque_pointer_converter.hpp
==============================================================================
--- branches/release/boost/python/opaque_pointer_converter.hpp (original)
+++ branches/release/boost/python/opaque_pointer_converter.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -121,8 +121,7 @@
 template <class Pointee>
 PyTypeObject opaque<Pointee>::type_object =
 {
- PyObject_HEAD_INIT(0)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
     0,
     sizeof( BOOST_DEDUCED_TYPENAME opaque<Pointee>::python_instance ),
     0,

Modified: branches/release/boost/python/operators.hpp
==============================================================================
--- branches/release/boost/python/operators.hpp (original)
+++ branches/release/boost/python/operators.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -341,7 +341,11 @@
 BOOST_PYTHON_UNARY_OPERATOR(pos, +, operator+)
 BOOST_PYTHON_UNARY_OPERATOR(abs, abs, abs)
 BOOST_PYTHON_UNARY_OPERATOR(invert, ~, operator~)
+#if PY_VERSION_HEX >= 0x03000000
+BOOST_PYTHON_UNARY_OPERATOR(bool, !!, operator!)
+#else
 BOOST_PYTHON_UNARY_OPERATOR(nonzero, !!, operator!)
+#endif
 BOOST_PYTHON_UNARY_OPERATOR(int, long, int_)
 BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
 BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)

Modified: branches/release/boost/python/str.hpp
==============================================================================
--- branches/release/boost/python/str.hpp (original)
+++ branches/release/boost/python/str.hpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -37,10 +37,12 @@
     
       long count(object_cref sub, object_cref start, object_cref end) const;
 
+#if PY_VERSION_HEX < 0x03000000
       object decode() const;
       object decode(object_cref encoding) const;
 
       object decode(object_cref encoding, object_cref errors) const;
+#endif
 
       object encode() const;
       object encode(object_cref encoding) const;
@@ -185,6 +187,7 @@
         return base::count(object(sub), object(start));
     }
 
+#if PY_VERSION_HEX < 0x03000000
     object decode() const { return base::decode(); }
     
     template<class T>
@@ -198,6 +201,7 @@
     {
         return base::decode(object(encoding),object(errors));
     }
+#endif
 
     object encode() const { return base::encode(); }
 
@@ -404,7 +408,11 @@
 {
   template <>
   struct object_manager_traits<str>
+#if PY_VERSION_HEX >= 0x03000000
+ : pytype_object_manager_traits<&PyUnicode_Type,str>
+#else
       : pytype_object_manager_traits<&PyString_Type,str>
+#endif
   {
   };
 }

Modified: branches/release/libs/python/build/Jamfile.v2
==============================================================================
--- branches/release/libs/python/build/Jamfile.v2 (original)
+++ branches/release/libs/python/build/Jamfile.v2 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -4,6 +4,7 @@
 
 import os ;
 import modules ;
+import feature ;
 
 import python ;
 
@@ -22,6 +23,22 @@
     }
 }
 
+rule find-py3-version
+{
+ local versions = [ feature.values python ] ;
+ local py3ver ;
+ for local v in $(versions)
+ {
+ if $(v) >= 3.0
+ {
+ py3ver = $(v) ;
+ }
+ }
+ return $(py3ver) ;
+}
+
+py3-version = [ find-py3-version ] ;
+
 project boost/python
   : source-location ../src
   ;
@@ -29,66 +46,79 @@
 rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
 rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
 
-lib boost_python
- : # sources
- numeric.cpp
- list.cpp
- long.cpp
- dict.cpp
- tuple.cpp
- str.cpp
- slice.cpp
-
- converter/from_python.cpp
- converter/registry.cpp
- converter/type_id.cpp
- object/enum.cpp
- object/class.cpp
- object/function.cpp
- object/inheritance.cpp
- object/life_support.cpp
- object/pickle_support.cpp
- errors.cpp
- module.cpp
- converter/builtin_converters.cpp
- converter/arg_to_python_base.cpp
- object/iterator.cpp
- object/stl_iterator.cpp
- object_protocol.cpp
- object_operators.cpp
- wrapper.cpp
- import.cpp
- exec.cpp
- object/function_doc_signature.cpp
- : # requirements
- <link>static:<define>BOOST_PYTHON_STATIC_LIB
- <define>BOOST_PYTHON_SOURCE
-
- # On Windows, all code using Python has to link to the Python
- # import library.
- #
- # On *nix we never link libboost_python to libpython. When
- # extending Python, all Python symbols are provided by the
- # Python interpreter executable. When embedding Python, the
- # client executable is expected to explicitly link to
- # /python//python (the target representing libpython) itself.
- #
- # python_for_extensions is a target defined by Boost.Build to
- # provide the Python include paths, and on Windows, the Python
- # import library, as usage requirements.
- [ cond [ python.configured ] : <library>/python//python_for_extensions ]
-
- # we prevent building when there is no python available
- # as it's not possible anyway, and to cause dependents to
- # fail to build
- [ unless [ python.configured ] : <build>no ]
-
- <python-debugging>on:<define>BOOST_DEBUG_PYTHON
- : # default build
- <link>shared
- : # usage requirements
- <link>static:<define>BOOST_PYTHON_STATIC_LIB
- <python-debugging>on:<define>BOOST_DEBUG_PYTHON
- ;
+rule lib_boost_python ( is-py3 ? )
+{
 
+ lib [ cond $(is-py3) : boost_python3 : boost_python ]
+ : # sources
+ numeric.cpp
+ list.cpp
+ long.cpp
+ dict.cpp
+ tuple.cpp
+ str.cpp
+ slice.cpp
+
+ converter/from_python.cpp
+ converter/registry.cpp
+ converter/type_id.cpp
+ object/enum.cpp
+ object/class.cpp
+ object/function.cpp
+ object/inheritance.cpp
+ object/life_support.cpp
+ object/pickle_support.cpp
+ errors.cpp
+ module.cpp
+ converter/builtin_converters.cpp
+ converter/arg_to_python_base.cpp
+ object/iterator.cpp
+ object/stl_iterator.cpp
+ object_protocol.cpp
+ object_operators.cpp
+ wrapper.cpp
+ import.cpp
+ exec.cpp
+ object/function_doc_signature.cpp
+ : # requirements
+ <link>static:<define>BOOST_PYTHON_STATIC_LIB
+ <define>BOOST_PYTHON_SOURCE
+
+ # On Windows, all code using Python has to link to the Python
+ # import library.
+ #
+ # On *nix we never link libboost_python to libpython. When
+ # extending Python, all Python symbols are provided by the
+ # Python interpreter executable. When embedding Python, the
+ # client executable is expected to explicitly link to
+ # /python//python (the target representing libpython) itself.
+ #
+ # python_for_extensions is a target defined by Boost.Build to
+ # provide the Python include paths, and on Windows, the Python
+ # import library, as usage requirements.
+ [ cond [ python.configured ] : <library>/python//python_for_extensions ]
+
+ # we prevent building when there is no python available
+ # as it's not possible anyway, and to cause dependents to
+ # fail to build
+ [ unless [ python.configured ] : <build>no ]
+
+ <python-debugging>on:<define>BOOST_DEBUG_PYTHON
+ [ cond $(is-py3) : <python>$(py3-version) ]
+ : # default build
+ <link>shared
+ : # usage requirements
+ <link>static:<define>BOOST_PYTHON_STATIC_LIB
+ <python-debugging>on:<define>BOOST_DEBUG_PYTHON
+ ;
+
+}
+
+lib_boost_python ;
 boost-install boost_python ;
+
+if $(py3-version)
+{
+ lib_boost_python yes ;
+ boost-install boost_python3 ;
+}

Modified: branches/release/libs/python/doc/news.html
==============================================================================
--- branches/release/libs/python/doc/news.html (original)
+++ branches/release/libs/python/doc/news.html 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -32,7 +32,43 @@
   <hr>
 
   <dl class="page-index">
+
     <dt>Current SVN</dt>
+ <dd>
+ <ul>
+ <li>Python 3 support:</li>
+ <ul>
+ <li>All the current Boost.Python test cases passed. Extension modules using
+ Boost.Python expected to support Python 3 smoothly.</li>
+ <li>Introduced <code>object.contains</code> where <code>x.contains(y)</code>
+ is equivalent to Python code <code>y in x</code>.
+ Now <code>dict.has_key</code> is just a wrapper of <code>object.contains</code>.
+ </li>
+ <li>When building against Python 3, <code>str.decode</code> will be removed.</li>
+ <li>When building against Python 3, the original signature of <code>list.sort</code>, which is:
+ <pre>void sort(object_cref cmpfunc);</pre>
+ will change to:
+ <pre>void sort(args_proxy const &args, kwds_proxy const &kwds);</pre>
+
+ This is because in Python 3 <code>list.sort</code> requires all its arguments be keyword arguments.
+ So you should call it like this:
+ <pre>x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true))));</pre>
+
+ </li>
+ <li>According to PEP 3123,
+ when building Boost.Python against Python older than 2.6, the following macros will
+ be defined in Boost.Python header:
+ <pre>
+# define Py_TYPE(o) (((PyObject*)(o))->ob_type)
+# define Py_REFCNT(o) (((PyObject*)(o))->ob_refcnt)
+# define Py_SIZE(o) (((PyVarObject*)(o))->ob_size)</pre>
+ So extension writers can use these macro directly, to make code clean and compatible with Python 3.
+ </li>
+ </ul>
+ </ul>
+ </dd>
+
+ <dt>1.39.0 Release</dt>
 
     <dd>
       <ul>

Modified: branches/release/libs/python/src/converter/builtin_converters.cpp
==============================================================================
--- branches/release/libs/python/src/converter/builtin_converters.cpp (original)
+++ branches/release/libs/python/src/converter/builtin_converters.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -37,12 +37,20 @@
 
 namespace
 {
+
   // An lvalue conversion function which extracts a char const* from a
   // Python String.
+#if PY_VERSION_HEX < 0x03000000
   void* convert_to_cstring(PyObject* obj)
   {
       return PyString_Check(obj) ? PyString_AsString(obj) : 0;
   }
+#else
+ void* convert_to_cstring(PyObject* obj)
+ {
+ return PyUnicode_Check(obj) ? _PyUnicode_AsString(obj) : 0;
+ }
+#endif
 
   // Given a target type and a SlotPolicy describing how to perform a
   // given conversion, registers from_python converters which use the
@@ -90,6 +98,52 @@
       }
   };
 
+ // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
+ // "slot" which just returns its argument.
+ extern "C" PyObject* identity_unaryfunc(PyObject* x)
+ {
+ Py_INCREF(x);
+ return x;
+ }
+ unaryfunc py_object_identity = identity_unaryfunc;
+
+#if PY_VERSION_HEX >= 0x03000000
+ // As in Python 3 there is only one integer type, we can have much
+ // simplified logic.
+ // XXX(bhy) maybe the code will work with 2.6 or even 2.5?
+ struct int_rvalue_from_python_base
+ {
+ static unaryfunc* get_slot(PyObject* obj)
+ {
+ return PyLong_Check(obj) ? &py_object_identity : 0;
+ }
+ static PyTypeObject const* get_pytype() {return &PyLong_Type;}
+ };
+
+ template <class T>
+ struct signed_int_rvalue_from_python : int_rvalue_from_python_base
+ {
+ static T extract(PyObject* intermediate)
+ {
+ long x = PyLong_AsLong(intermediate);
+ if (PyErr_Occurred())
+ throw_error_already_set();
+ return numeric_cast<T>(x);
+ }
+ };
+
+ template <class T>
+ struct unsigned_int_rvalue_from_python : int_rvalue_from_python_base
+ {
+ static T extract(PyObject* intermediate)
+ {
+ unsigned long x = PyLong_AsUnsignedLong(intermediate);
+ if (PyErr_Occurred())
+ throw_error_already_set();
+ return numeric_cast<T>(x);
+ }
+ };
+#else // PY_VERSION_HEX >= 0x03000000
   // A SlotPolicy for extracting signed integer types from Python objects
   struct signed_int_rvalue_from_python_base
   {
@@ -121,16 +175,7 @@
           return numeric_cast<T>(x);
       }
   };
-
- // identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
- // "slot" which just returns its argument.
- extern "C" PyObject* identity_unaryfunc(PyObject* x)
- {
- Py_INCREF(x);
- return x;
- }
- unaryfunc py_object_identity = identity_unaryfunc;
-
+
   // A SlotPolicy for extracting unsigned integer types from Python objects
   struct unsigned_int_rvalue_from_python_base
   {
@@ -178,6 +223,7 @@
           }
       }
   };
+#endif // PY_VERSION_HEX >= 0x03000000
 
 // Checking Python's macro instead of Boost's - we don't seem to get
 // the config right all the time. Furthermore, Python's is defined
@@ -190,6 +236,9 @@
   {
       static unaryfunc* get_slot(PyObject* obj)
       {
+#if PY_VERSION_HEX >= 0x03000000
+ return PyLong_Check(obj) ? &py_object_identity : 0;
+#else
           PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
           if (number_methods == 0)
               return 0;
@@ -202,19 +251,22 @@
               return &number_methods->nb_long;
           else
               return 0;
+#endif
       }
- static PyTypeObject const* get_pytype() { return &PyInt_Type;}
+ static PyTypeObject const* get_pytype() { return &PyLong_Type;}
   };
   
   struct long_long_rvalue_from_python : long_long_rvalue_from_python_base
   {
       static BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
       {
+#if PY_VERSION_HEX < 0x03000000
           if (PyInt_Check(intermediate))
           {
               return PyInt_AS_LONG(intermediate);
           }
           else
+#endif
           {
               BOOST_PYTHON_LONG_LONG result = PyLong_AsLongLong(intermediate);
               
@@ -230,11 +282,13 @@
   {
       static unsigned BOOST_PYTHON_LONG_LONG extract(PyObject* intermediate)
       {
+#if PY_VERSION_HEX < 0x03000000
           if (PyInt_Check(intermediate))
           {
               return numeric_cast<unsigned BOOST_PYTHON_LONG_LONG>(PyInt_AS_LONG(intermediate));
           }
           else
+#endif
           {
               unsigned BOOST_PYTHON_LONG_LONG result = PyLong_AsUnsignedLongLong(intermediate);
               
@@ -252,7 +306,9 @@
   {
       static unaryfunc* get_slot(PyObject* obj)
       {
-#if PY_VERSION_HEX >= 0x02040000 && defined(BOOST_PYTHON_BOOL_INT_STRICT)
+#if PY_VERSION_HEX >= 0x03000000
+ return obj == Py_None || PyLong_Check(obj) ? &py_object_identity : 0;
+#elif 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;
@@ -285,8 +341,10 @@
 
           // For integer types, return the tp_int conversion slot to avoid
           // creating a new object. We'll handle that below
+#if PY_VERSION_HEX < 0x03000000
           if (PyInt_Check(obj))
               return &number_methods->nb_int;
+#endif
 
           return (PyLong_Check(obj) || PyFloat_Check(obj))
               ? &number_methods->nb_float : 0;
@@ -294,11 +352,13 @@
       
       static double extract(PyObject* intermediate)
       {
+#if PY_VERSION_HEX < 0x03000000
           if (PyInt_Check(intermediate))
           {
               return PyInt_AS_LONG(intermediate);
           }
           else
+#endif
           {
               return PyFloat_AS_DOUBLE(intermediate);
           }
@@ -306,22 +366,36 @@
       static PyTypeObject const* get_pytype() { return &PyFloat_Type;}
   };
 
+ unaryfunc py_unicode_as_string_unaryfunc = PyUnicode_AsUTF8String;
+
   // A SlotPolicy for extracting C++ strings from Python objects.
   struct string_rvalue_from_python
   {
       // If the underlying object is "string-able" this will succeed
       static unaryfunc* get_slot(PyObject* obj)
       {
- return (PyString_Check(obj))
- ? &obj->ob_type->tp_str : 0;
+#if PY_VERSION_HEX >= 0x03000000
+ return (PyUnicode_Check(obj)) ? &py_unicode_as_string_unaryfunc : 0;
+#else
+ return (PyString_Check(obj)) ? &obj->ob_type->tp_str : 0;
+
+#endif
       };
 
       // Remember that this will be used to construct the result object
+#if PY_VERSION_HEX >= 0x03000000
+ static std::string extract(PyObject* intermediate)
+ {
+ return std::string(PyBytes_AsString(intermediate),PyBytes_Size(intermediate));
+ }
+ static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
+#else
       static std::string extract(PyObject* intermediate)
       {
           return std::string(PyString_AsString(intermediate),PyString_Size(intermediate));
       }
       static PyTypeObject const* get_pytype() { return &PyString_Type;}
+#endif
   };
 
 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
@@ -341,7 +415,11 @@
       {
           return PyUnicode_Check(obj)
               ? &py_object_identity
+#if PY_VERSION_HEX >= 0x03000000
+ : PyBytes_Check(obj)
+#else
             : PyString_Check(obj)
+#endif
               ? &py_encode_string
             : 0;
       };
@@ -384,10 +462,12 @@
                   PyComplex_RealAsDouble(intermediate)
                   , PyComplex_ImagAsDouble(intermediate));
           }
+#if PY_VERSION_HEX < 0x03000000
           else if (PyInt_Check(intermediate))
           {
               return PyInt_AS_LONG(intermediate);
           }
+#endif
           else
           {
               return PyFloat_AS_DOUBLE(intermediate);
@@ -399,12 +479,20 @@
 
 BOOST_PYTHON_DECL PyObject* do_return_to_python(char x)
 {
+#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_FromStringAndSize(&x, 1);
+#else
     return PyString_FromStringAndSize(&x, 1);
+#endif
 }
   
 BOOST_PYTHON_DECL PyObject* do_return_to_python(char const* x)
 {
+#if PY_VERSION_HEX >= 0x03000000
+ return x ? PyUnicode_FromString(x) : boost::python::detail::none();
+#else
     return x ? PyString_FromString(x) : boost::python::detail::none();
+#endif
 }
   
 BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject* x)
@@ -459,13 +547,18 @@
     slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>();
     
     // Add an lvalue converter for char which gets us char const*
+#if PY_VERSION_HEX < 0x03000000
     registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
+#else
+ registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyUnicode_Type>::get_pytype);
+#endif
 
     // Register by-value converters to std::string, std::wstring
 #if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
     slot_rvalue_from_python<std::wstring, wstring_rvalue_from_python>();
 # endif
     slot_rvalue_from_python<std::string, string_rvalue_from_python>();
+
 }
 
 }}} // namespace boost::python::converter

Modified: branches/release/libs/python/src/converter/from_python.cpp
==============================================================================
--- branches/release/libs/python/src/converter/from_python.cpp (original)
+++ branches/release/libs/python/src/converter/from_python.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -96,7 +96,12 @@
     if (!data.convertible)
     {
         handle<> msg(
- ::PyString_FromFormat(
+#if PY_VERSION_HEX >= 0x03000000
+ ::PyUnicode_FromFormat
+#else
+ ::PyString_FromFormat
+#endif
+ (
                 "No registered converter was able to produce a C++ rvalue of type %s from this Python object of type %s"
                 , converters.target_type.name()
                 , source->ob_type->tp_name
@@ -196,7 +201,12 @@
   void throw_no_lvalue_from_python(PyObject* source, registration const& converters, char const* ref_type)
   {
       handle<> msg(
- ::PyString_FromFormat(
+#if PY_VERSION_HEX >= 0x03000000
+ ::PyUnicode_FromFormat
+#else
+ ::PyString_FromFormat
+#endif
+ (
               "No registered converter was able to extract a C++ %s to type %s"
               " from this Python object of type %s"
               , ref_type
@@ -218,7 +228,12 @@
       if (source->ob_refcnt <= 1)
       {
           handle<> msg(
- ::PyString_FromFormat(
+#if PY_VERSION_HEX >= 0x3000000
+ ::PyUnicode_FromFormat
+#else
+ ::PyString_FromFormat
+#endif
+ (
                   "Attempt to return dangling %s to object of type: %s"
                   , ref_type
                   , converters.target_type.name()));

Modified: branches/release/libs/python/src/converter/registry.cpp
==============================================================================
--- branches/release/libs/python/src/converter/registry.cpp (original)
+++ branches/release/libs/python/src/converter/registry.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -70,7 +70,12 @@
     if (this->m_to_python == 0)
     {
         handle<> msg(
- ::PyString_FromFormat(
+#if PY_VERSION_HEX >= 0x3000000
+ ::PyUnicode_FromFormat
+#else
+ ::PyString_FromFormat
+#endif
+ (
                 "No to_python (by-value) converter found for C++ type: %s"
                 , this->target_type.name()
                 )

Modified: branches/release/libs/python/src/dict.cpp
==============================================================================
--- branches/release/libs/python/src/dict.cpp (original)
+++ branches/release/libs/python/src/dict.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -84,7 +84,7 @@
 
 bool dict_base::has_key(object_cref k) const
 {
- return extract<bool>(this->attr("has_key")(k));
+ return extract<bool>(this->contains(k));
 }
 
 list dict_base::items() const

Modified: branches/release/libs/python/src/exec.cpp
==============================================================================
--- branches/release/libs/python/src/exec.cpp (original)
+++ branches/release/libs/python/src/exec.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -88,11 +88,19 @@
   if (local.ptr() == none.ptr()) local = global;
   // should be 'char const *' but older python versions don't use 'const' yet.
   char *f = python::extract<char *>(filename);
+#if PY_VERSION_HEX >= 0x03000000
+ // TODO(bhy) temporary workaround for Python 3.
+ // should figure out a way to avoid binary incompatibilities as the Python 2
+ // version did.
+ FILE *fs = fopen(f, "r");
+#else
   // Let python open the file to avoid potential binary incompatibilities.
   PyObject *pyfile = PyFile_FromString(f, const_cast<char*>("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()),
+ FILE *fs = PyFile_AsFile(file.get());
+#endif
+ PyObject* result = PyRun_File(fs,
                 f,
                 Py_file_input,
                 global.ptr(), local.ptr());

Modified: branches/release/libs/python/src/list.cpp
==============================================================================
--- branches/release/libs/python/src/list.cpp (original)
+++ branches/release/libs/python/src/list.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -48,7 +48,11 @@
 long list_base::index(object_cref value) const
 {
     object result_obj(this->attr("index")(value));
+#if PY_VERSION_HEX >= 0x03000000
+ ssize_t result = PyLong_AsSsize_t(result_obj.ptr());
+#else
     long result = PyInt_AsLong(result_obj.ptr());
+#endif
     if (result == -1)
         throw_error_already_set();
     return result;
@@ -69,7 +73,11 @@
 
 void list_base::insert(object const& index, object_cref x)
 {
+#if PY_VERSION_HEX >= 0x03000000
+ ssize_t index_ = PyLong_AsSsize_t(index.ptr());
+#else
     long index_ = PyInt_AsLong(index.ptr());
+#endif
     if (index_ == -1 && PyErr_Occurred())
         throw_error_already_set();
     this->insert(index_, x);
@@ -121,17 +129,29 @@
     }
 }
 
+#if PY_VERSION_HEX >= 0x03000000
+void list_base::sort(args_proxy const &args,
+ kwds_proxy const &kwds)
+{
+ this->attr("sort")(args, kwds);
+}
+#else
 void list_base::sort(object_cref cmpfunc)
 {
     this->attr("sort")(cmpfunc);
 }
+#endif
 
 // For some reason, moving this to the end of the TU suppresses an ICE
 // with vc6.
-long list_base::count(object_cref value) const
+ssize_t list_base::count(object_cref value) const
 {
     object result_obj(this->attr("count")(value));
+#if PY_VERSION_HEX >= 0x03000000
+ ssize_t result = PyLong_AsSsize_t(result_obj.ptr());
+#else
     long result = PyInt_AsLong(result_obj.ptr());
+#endif
     if (result == -1)
         throw_error_already_set();
     return result;

Modified: branches/release/libs/python/src/module.cpp
==============================================================================
--- branches/release/libs/python/src/module.cpp (original)
+++ branches/release/libs/python/src/module.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -24,11 +24,25 @@
   PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } };
 }
 
-BOOST_PYTHON_DECL void init_module(char const* name, void(*init_function)())
+BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*init_function)())
 {
-
+#if PY_VERSION_HEX >= 0x03000000
+ static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ name,
+ 0, /* m_doc */
+ -1, /* m_size */
+ initial_methods,
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+ };
+ PyObject* m = PyModule_Create(&moduledef);
+#else
     PyObject* m
         = Py_InitModule(const_cast<char*>(name), initial_methods);
+#endif
 
     if (m != 0)
     {
@@ -38,6 +52,7 @@
         
         handle_exception(init_function);
     }
+ return m;
 }
 
 }}} // namespace boost::python::detail

Modified: branches/release/libs/python/src/object/class.cpp
==============================================================================
--- branches/release/libs/python/src/object/class.cpp (original)
+++ branches/release/libs/python/src/object/class.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -67,8 +67,44 @@
       PyObject *prop_set;
       PyObject *prop_del;
       PyObject *prop_doc;
+ int getter_doc;
   } propertyobject;
 
+ // Copied from Python source and removed the part for setting docstring,
+ // since we don't have a setter for __doc__ and trying to set it will
+ // cause the init fail.
+ static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
+ {
+ PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
+ static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
+ propertyobject *prop = (propertyobject *)self;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
+ kwlist, &get, &set, &del, &doc))
+ return -1;
+
+ if (get == Py_None)
+ get = NULL;
+ if (set == Py_None)
+ set = NULL;
+ if (del == Py_None)
+ del = NULL;
+
+ Py_XINCREF(get);
+ Py_XINCREF(set);
+ Py_XINCREF(del);
+ Py_XINCREF(doc);
+
+ prop->prop_get = get;
+ prop->prop_set = set;
+ prop->prop_del = del;
+ prop->prop_doc = doc;
+ prop->getter_doc = 0;
+
+ return 0;
+ }
+
+
   static PyObject *
   static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
   {
@@ -106,10 +142,9 @@
 }
 
 static PyTypeObject static_data_object = {
- PyObject_HEAD_INIT(0)//&PyType_Type)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
     const_cast<char*>("Boost.Python.StaticProperty"),
- PyType_Type.tp_basicsize,
+ sizeof(propertyobject),
     0,
     0, /* tp_dealloc */
     0, /* tp_print */
@@ -143,7 +178,7 @@
     static_data_descr_get, /* tp_descr_get */
     static_data_descr_set, /* tp_descr_set */
     0, /* tp_dictoffset */
- 0, /* tp_init */
+ property_init, /* tp_init */
     0, /* tp_alloc */
     0, // filled in with type_new /* tp_new */
     0, // filled in with __PyObject_GC_Del /* tp_free */
@@ -160,17 +195,20 @@
 
 namespace objects
 {
+#if PY_VERSION_HEX < 0x03000000
+ // XXX Not sure why this run into compiling error in Python 3
   extern "C"
   {
       // This declaration needed due to broken Python 2.2 headers
       extern DL_IMPORT(PyTypeObject) PyProperty_Type;
   }
+#endif
 
   BOOST_PYTHON_DECL PyObject* static_data()
   {
       if (static_data_object.tp_dict == 0)
       {
- static_data_object.ob_type = &PyType_Type;
+ Py_TYPE(&static_data_object) = &PyType_Type;
           static_data_object.tp_base = &PyProperty_Type;
           if (PyType_Ready(&static_data_object))
               return 0;
@@ -203,15 +241,14 @@
         // If we found a static data descriptor, call it directly to
         // force it to set the static data member
         if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
- return a->ob_type->tp_descr_set(a, obj, value);
+ return Py_TYPE(a)->tp_descr_set(a, obj, value);
         else
             return PyType_Type.tp_setattro(obj, name, value);
     }
 }
 
 static PyTypeObject class_metatype_object = {
- PyObject_HEAD_INIT(0)//&PyType_Type)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
     const_cast<char*>("Boost.Python.class"),
     PyType_Type.tp_basicsize,
     0,
@@ -266,7 +303,7 @@
 // object.
 void instance_holder::install(PyObject* self) throw()
 {
- assert(self->ob_type->ob_type == &class_metatype_object);
+ assert(Py_TYPE(Py_TYPE(self)) == &class_metatype_object);
     m_next = ((objects::instance<>*)self)->objects;
     ((objects::instance<>*)self)->objects = this;
 }
@@ -279,7 +316,7 @@
   {
       if (class_metatype_object.tp_dict == 0)
       {
- class_metatype_object.ob_type = &PyType_Type;
+ Py_TYPE(&class_metatype_object) = &PyType_Type;
           class_metatype_object.tp_base = &PyType_Type;
           if (PyType_Ready(&class_metatype_object))
               return type_handle();
@@ -308,7 +345,7 @@
 
           Py_XDECREF(kill_me->dict);
           
- inst->ob_type->tp_free(inst);
+ Py_TYPE(inst)->tp_free(inst);
       }
 
       static PyObject *
@@ -318,7 +355,12 @@
           PyObject* d = type_->tp_dict;
           PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));
 
- long instance_size = instance_size_obj ? PyInt_AsLong(instance_size_obj) : 0;
+ ssize_t instance_size = instance_size_obj ?
+#if PY_VERSION_HEX >= 0x03000000
+ PyLong_AsSsize_t(instance_size_obj) : 0;
+#else
+ PyInt_AsLong(instance_size_obj) : 0;
+#endif
           
           if (instance_size < 0)
               instance_size = 0;
@@ -332,7 +374,12 @@
               // like, so we'll store the total size of the object
               // there. A negative number indicates that the extra
               // instance memory is not yet allocated to any holders.
- result->ob_size = -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
+#if PY_VERSION_HEX >= 0x02060000
+ Py_SIZE(result) =
+#else
+ result->ob_size =
+#endif
+ -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
           }
           return (PyObject*)result;
       }
@@ -368,8 +415,7 @@
   };
 
   static PyTypeObject class_type_object = {
- PyObject_HEAD_INIT(0) //&class_metatype_object)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
       const_cast<char*>("Boost.Python.instance"),
       offsetof(instance<>,storage), /* tp_basicsize */
       1, /* tp_itemsize */
@@ -424,7 +470,7 @@
   {
       if (class_type_object.tp_dict == 0)
       {
- class_type_object.ob_type = incref(class_metatype().get());
+ Py_TYPE(&class_type_object) = incref(class_metatype().get());
           class_type_object.tp_base = &PyBaseObject_Type;
           if (PyType_Ready(&class_type_object))
               return type_handle();
@@ -436,7 +482,7 @@
   BOOST_PYTHON_DECL void*
   find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
   {
- if (inst->ob_type->ob_type != &class_metatype_object)
+ if (Py_TYPE(Py_TYPE(inst)) != &class_metatype_object)
           return 0;
     
       instance<>* self = reinterpret_cast<instance<>*>(inst);
@@ -526,7 +572,7 @@
           d["__doc__"] = doc;
       
       object result = object(class_metatype())(name, bases, d);
- assert(PyType_IsSubtype(result.ptr()->ob_type, &PyType_Type));
+ assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
       
       if (scope().ptr() != Py_None)
           scope().attr(name) = result;
@@ -589,8 +635,9 @@
   void class_base::add_static_property(char const* name, object const& fget)
   {
       object property(
- (python::detail::new_reference)
- PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr()));
+ (python::detail::new_reference)
+ PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr())
+ );
       
       this->setattr(name, property);
   }
@@ -650,7 +697,7 @@
         ::PyErr_Format(
             PyExc_TypeError
           , const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
- , callable->ob_type->tp_name
+ , Py_TYPE(callable)->tp_name
             );
         
         throw_error_already_set();
@@ -680,18 +727,18 @@
 
 void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
 {
- assert(self_->ob_type->ob_type == &class_metatype_object);
+ assert(Py_TYPE(Py_TYPE(self_)) == &class_metatype_object);
     objects::instance<>* self = (objects::instance<>*)self_;
     
     int total_size_needed = holder_offset + holder_size;
     
- if (-self->ob_size >= total_size_needed)
+ if (-Py_SIZE(self) >= total_size_needed)
     {
         // holder_offset should at least point into the variable-sized part
         assert(holder_offset >= offsetof(objects::instance<>,storage));
 
         // Record the fact that the storage is occupied, noting where it starts
- self->ob_size = holder_offset;
+ Py_SIZE(self) = holder_offset;
         return (char*)self + holder_offset;
     }
     else
@@ -705,9 +752,9 @@
 
 void instance_holder::deallocate(PyObject* self_, void* storage) throw()
 {
- assert(self_->ob_type->ob_type == &class_metatype_object);
+ assert(Py_TYPE(Py_TYPE(self_)) == &class_metatype_object);
     objects::instance<>* self = (objects::instance<>*)self_;
- if (storage != (char*)self + self->ob_size)
+ if (storage != (char*)self + Py_SIZE(self))
     {
         PyMem_Free(storage);
     }

Modified: branches/release/libs/python/src/object/enum.cpp
==============================================================================
--- branches/release/libs/python/src/object/enum.cpp (original)
+++ branches/release/libs/python/src/object/enum.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -18,7 +18,11 @@
 
 struct enum_object
 {
+#if PY_VERSION_HEX >= 0x03000000
+ PyLongObject base_object;
+#else
     PyIntObject base_object;
+#endif
     PyObject* name;
 };
 
@@ -32,19 +36,32 @@
 {
     static PyObject* enum_repr(PyObject* self_)
     {
- const char *mod = PyString_AsString(PyObject_GetAttrString( self_, const_cast<char*>("__module__")));
+ // XXX(bhy) Potentional memory leak here since PyObject_GetAttrString returns a new reference
+ // const char *mod = PyString_AsString(PyObject_GetAttrString( self_, const_cast<char*>("__module__")));
+ PyObject *mod = PyObject_GetAttrString( self_, "__module__");
         enum_object* self = downcast<enum_object>(self_);
         if (!self->name)
         {
- return PyString_FromFormat("%s.%s(%ld)", mod, self_->ob_type->tp_name, PyInt_AS_LONG(self_));
+ return
+#if PY_VERSION_HEX >= 0x03000000
+ PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_));
+#else
+ PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_));
+#endif
         }
         else
         {
- char* name = PyString_AsString(self->name);
+ PyObject* name = self->name;
             if (name == 0)
                 return 0;
 
- return PyString_FromFormat("%s.%s.%s", mod, self_->ob_type->tp_name, name);
+ return
+#if PY_VERSION_HEX >= 0x03000000
+ PyUnicode_FromFormat("%S.%s.%S", mod, self_->ob_type->tp_name, name);
+#else
+ PyString_FromFormat("%s.%s.%s",
+ PyString_AsString(mod), self_->ob_type->tp_name, PyString_AsString(name));
+#endif
         }
     }
 
@@ -53,7 +70,11 @@
         enum_object* self = downcast<enum_object>(self_);
         if (!self->name)
         {
+#if PY_VERSION_HEX >= 0x03000000
+ return PyLong_Type.tp_str(self_);
+#else
             return PyInt_Type.tp_str(self_);
+#endif
         }
         else
         {
@@ -63,8 +84,7 @@
 }
 
 static PyTypeObject enum_type_object = {
- PyObject_HEAD_INIT(0) // &PyType_Type
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0) // &PyType_Type
     const_cast<char*>("Boost.Python.enum"),
     sizeof(enum_object), /* tp_basicsize */
     0, /* tp_itemsize */
@@ -84,7 +104,9 @@
     0, /* tp_setattro */
     0, /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT
+#if PY_VERSION_HEX < 0x03000000
     | Py_TPFLAGS_CHECKTYPES
+#endif
     | Py_TPFLAGS_HAVE_GC
     | Py_TPFLAGS_BASETYPE, /* tp_flags */
     0, /* tp_doc */
@@ -125,8 +147,12 @@
   {
       if (enum_type_object.tp_dict == 0)
       {
- enum_type_object.ob_type = incref(&PyType_Type);
+ Py_TYPE(&enum_type_object) = incref(&PyType_Type);
+#if PY_VERSION_HEX >= 0x03000000
+ enum_type_object.tp_base = &PyLong_Type;
+#else
           enum_type_object.tp_base = &PyInt_Type;
+#endif
           if (PyType_Ready(&enum_type_object))
               throw_error_already_set();
       }

Modified: branches/release/libs/python/src/object/function.cpp
==============================================================================
--- branches/release/libs/python/src/object/function.cpp (original)
+++ branches/release/libs/python/src/object/function.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -105,9 +105,9 @@
     }
     
     PyObject* p = this;
- if (function_type.ob_type == 0)
+ if (Py_TYPE(&function_type) == 0)
     {
- function_type.ob_type = &PyType_Type;
+ Py_TYPE(&function_type) = &PyType_Type;
         ::PyType_Ready(&function_type);
     }
     
@@ -435,9 +435,13 @@
         function* new_func = downcast<function>(attribute.ptr());
         PyObject* dict = 0;
         
+#if PY_VERSION_HEX < 0x03000000
+ // Old-style class gone in Python 3
         if (PyClass_Check(ns))
             dict = ((PyClassObject*)ns)->cl_dict;
- else if (PyType_Check(ns))
+ else
+#endif
+ if (PyType_Check(ns))
             dict = ((PyTypeObject*)ns)->tp_dict;
         else
             dict = PyObject_GetAttrString(ns, const_cast<char*>("__dict__"));
@@ -595,9 +599,18 @@
     static PyObject *
     function_descr_get(PyObject *func, PyObject *obj, PyObject *type_)
     {
+#if PY_VERSION_HEX >= 0x03000000
+ // The implement is different in Python 3 because of the removal of unbound method
+ if (obj == Py_None || obj == NULL) {
+ Py_INCREF(func);
+ return func;
+ }
+ return PyMethod_New(func, obj);
+#else
         if (obj == Py_None)
             obj = NULL;
         return PyMethod_New(func, obj, type_);
+#endif
     }
 
     static void
@@ -641,7 +654,11 @@
     {
         function* f = downcast<function>(op);
         if (f->name().ptr() == Py_None)
+#if PY_VERSION_HEX >= 0x03000000
+ return PyUnicode_InternFromString("<unnamed Boost.Python function>");
+#else
             return PyString_InternFromString("<unnamed Boost.Python function>");
+#endif
         else
             return python::incref(f->name().ptr());
     }
@@ -665,8 +682,7 @@
 };
 
 PyTypeObject function_type = {
- PyObject_HEAD_INIT(0)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
     const_cast<char*>("Boost.Python.function"),
     sizeof(function),
     0,

Modified: branches/release/libs/python/src/object/life_support.cpp
==============================================================================
--- branches/release/libs/python/src/object/life_support.cpp (original)
+++ branches/release/libs/python/src/object/life_support.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -36,8 +36,7 @@
 }
 
 PyTypeObject life_support_type = {
- PyObject_HEAD_INIT(0)//(&PyType_Type)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)//(&PyType_Type)
     const_cast<char*>("Boost.Python.life_support"),
     sizeof(life_support),
     0,
@@ -92,9 +91,9 @@
     if (nurse == Py_None || nurse == patient)
         return nurse;
     
- if (life_support_type.ob_type == 0)
+ if (Py_TYPE(&life_support_type) == 0)
     {
- life_support_type.ob_type = &PyType_Type;
+ Py_TYPE(&life_support_type) = &PyType_Type;
         PyType_Ready(&life_support_type);
     }
     

Modified: branches/release/libs/python/src/object_operators.cpp
==============================================================================
--- branches/release/libs/python/src/object_operators.cpp (original)
+++ branches/release/libs/python/src/object_operators.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -38,7 +38,13 @@
 BOOST_PYTHON_BINARY_OPERATOR(+, Add)
 BOOST_PYTHON_BINARY_OPERATOR(-, Subtract)
 BOOST_PYTHON_BINARY_OPERATOR(*, Multiply)
+#if PY_VERSION_HEX >= 0x03000000
+// We choose FloorDivide instead of TrueDivide to keep the semantic
+// conform with C/C++'s '/' operator
+BOOST_PYTHON_BINARY_OPERATOR(/, FloorDivide)
+#else
 BOOST_PYTHON_BINARY_OPERATOR(/, Divide)
+#endif
 BOOST_PYTHON_BINARY_OPERATOR(%, Remainder)
 BOOST_PYTHON_BINARY_OPERATOR(<<, Lshift)
 BOOST_PYTHON_BINARY_OPERATOR(>>, Rshift)
@@ -58,7 +64,12 @@
 BOOST_PYTHON_INPLACE_OPERATOR(+, Add)
 BOOST_PYTHON_INPLACE_OPERATOR(-, Subtract)
 BOOST_PYTHON_INPLACE_OPERATOR(*, Multiply)
+#if PY_VERSION_HEX >= 0x03000000
+// Same reason as above for choosing FloorDivide instead of TrueDivide
+BOOST_PYTHON_INPLACE_OPERATOR(/, FloorDivide)
+#else
 BOOST_PYTHON_INPLACE_OPERATOR(/, Divide)
+#endif
 BOOST_PYTHON_INPLACE_OPERATOR(%, Remainder)
 BOOST_PYTHON_INPLACE_OPERATOR(<<, Lshift)
 BOOST_PYTHON_INPLACE_OPERATOR(>>, Rshift)

Modified: branches/release/libs/python/src/object_protocol.cpp
==============================================================================
--- branches/release/libs/python/src/object_protocol.cpp (original)
+++ branches/release/libs/python/src/object_protocol.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -103,6 +103,7 @@
   static PyObject *
   apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
   {
+#if PY_VERSION_HEX < 0x03000000
       PyTypeObject *tp = u->ob_type;
       PySequenceMethods *sq = tp->tp_as_sequence;
 
@@ -114,7 +115,9 @@
               return NULL;
           return PySequence_GetSlice(u, ilow, ihigh);
       }
- else {
+ else
+#endif
+ {
           PyObject *slice = PySlice_New(v, w, NULL);
           if (slice != NULL) {
               PyObject *res = PyObject_GetItem(u, slice);
@@ -130,6 +133,7 @@
   assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
       /* u[v:w] = x */
   {
+#if PY_VERSION_HEX < 0x03000000
       PyTypeObject *tp = u->ob_type;
       PySequenceMethods *sq = tp->tp_as_sequence;
 
@@ -144,7 +148,9 @@
           else
               return PySequence_SetSlice(u, ilow, ihigh, x);
       }
- else {
+ else
+#endif
+ {
           PyObject *slice = PySlice_New(v, w, NULL);
           if (slice != NULL) {
               int res;

Modified: branches/release/libs/python/src/str.cpp
==============================================================================
--- branches/release/libs/python/src/str.cpp (original)
+++ branches/release/libs/python/src/str.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -10,16 +10,33 @@
 detail::new_reference str_base::call(object const& arg_)
 {
     return (detail::new_reference)PyObject_CallFunction(
- (PyObject*)&PyString_Type, const_cast<char*>("(O)"),
+#if PY_VERSION_HEX >= 0x03000000
+ (PyObject*)&PyUnicode_Type,
+#else
+ (PyObject*)&PyString_Type,
+#endif
+ const_cast<char*>("(O)"),
         arg_.ptr());
 }
 
 str_base::str_base()
- : object(detail::new_reference(::PyString_FromString("")))
+ : object(detail::new_reference(
+#if PY_VERSION_HEX >= 0x03000000
+ ::PyUnicode_FromString("")
+#else
+ ::PyString_FromString("")
+#endif
+ ))
 {}
 
 str_base::str_base(const char* s)
- : object(detail::new_reference(::PyString_FromString(s)))
+ : object(detail::new_reference(
+#if PY_VERSION_HEX >= 0x03000000
+ ::PyUnicode_FromString(s)
+#else
+ ::PyString_FromString(s)
+#endif
+ ))
 {}
 
 namespace {
@@ -38,9 +55,12 @@
 str_base::str_base(char const* start, char const* finish)
     : object(
         detail::new_reference(
- ::PyString_FromStringAndSize(
- start, str_size_as_py_ssize_t(finish - start)
- )
+#if PY_VERSION_HEX >= 0x03000000
+ ::PyUnicode_FromStringAndSize
+#else
+ ::PyString_FromStringAndSize
+#endif
+ (start, str_size_as_py_ssize_t(finish - start))
         )
     )
 {}
@@ -48,9 +68,12 @@
 str_base::str_base(char const* start, std::size_t length) // new str
     : object(
         detail::new_reference(
- ::PyString_FromStringAndSize(
- start, str_size_as_py_ssize_t(length)
- )
+#if PY_VERSION_HEX >= 0x03000000
+ ::PyUnicode_FromStringAndSize
+#else
+ ::PyString_FromStringAndSize
+#endif
+ ( start, str_size_as_py_ssize_t(length) )
         )
     )
 {}
@@ -92,6 +115,7 @@
     return extract<long>(this->attr("count")(sub,start,end));
 }
 
+#if PY_VERSION_HEX < 0x03000000
 object str_base::decode() const
 {
     return this->attr("decode")();
@@ -106,6 +130,7 @@
 {
     return this->attr("decode")(encoding,errors);
 }
+#endif
 
 object str_base::encode() const
 {
@@ -122,9 +147,16 @@
     return this->attr("encode")(encoding,errors);
 }
 
+
+#if PY_VERSION_HEX >= 0x03000000
+ #define _BOOST_PYTHON_ASLONG PyLong_AsLong
+#else
+ #define _BOOST_PYTHON_ASLONG PyInt_AsLong
+#endif
+
 bool str_base::endswith(object_cref suffix) const
 {
- bool result = PyInt_AsLong(this->attr("endswith")(suffix).ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("endswith")(suffix).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -135,7 +167,7 @@
 
 long str_base::find(object_cref sub) const
 {
- long result = PyInt_AsLong(this->attr("find")(sub).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -143,7 +175,7 @@
 
 long str_base::find(object_cref sub, object_cref start) const
 {
- long result = PyInt_AsLong(this->attr("find")(sub,start).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -151,7 +183,7 @@
 
 long str_base::find(object_cref sub, object_cref start, object_cref end) const
 {
- long result = PyInt_AsLong(this->attr("find")(sub,start,end).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("find")(sub,start,end).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -159,7 +191,7 @@
 
 long str_base::index(object_cref sub) const
 {
- long result = PyInt_AsLong(this->attr("index")(sub).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -167,7 +199,7 @@
 
 long str_base::index(object_cref sub, object_cref start) const
 {
- long result = PyInt_AsLong(this->attr("index")(sub,start).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -175,7 +207,7 @@
 
 long str_base::index(object_cref sub, object_cref start, object_cref end) const
 {
- long result = PyInt_AsLong(this->attr("index")(sub,start,end).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("index")(sub,start,end).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -183,7 +215,7 @@
 
 bool str_base::isalnum() const
 {
- bool result = PyInt_AsLong(this->attr("isalnum")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("isalnum")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -191,7 +223,7 @@
 
 bool str_base::isalpha() const
 {
- bool result = PyInt_AsLong(this->attr("isalpha")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("isalpha")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -199,7 +231,7 @@
 
 bool str_base::isdigit() const
 {
- bool result = PyInt_AsLong(this->attr("isdigit")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("isdigit")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -207,7 +239,7 @@
 
 bool str_base::islower() const
 {
- bool result = PyInt_AsLong(this->attr("islower")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("islower")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -215,7 +247,7 @@
 
 bool str_base::isspace() const
 {
- bool result = PyInt_AsLong(this->attr("isspace")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("isspace")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -223,7 +255,7 @@
 
 bool str_base::istitle() const
 {
- bool result = PyInt_AsLong(this->attr("istitle")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("istitle")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -231,7 +263,7 @@
 
 bool str_base::isupper() const
 {
- bool result = PyInt_AsLong(this->attr("isupper")().ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("isupper")().ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -246,7 +278,7 @@
 
 long str_base::rfind(object_cref sub) const
 {
- long result = PyInt_AsLong(this->attr("rfind")(sub).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -254,7 +286,7 @@
 
 long str_base::rfind(object_cref sub, object_cref start) const
 {
- long result = PyInt_AsLong(this->attr("rfind")(sub,start).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -262,7 +294,7 @@
 
 long str_base::rfind(object_cref sub, object_cref start, object_cref end) const
 {
- long result = PyInt_AsLong(this->attr("rfind")(sub,start,end).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("rfind")(sub,start,end).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -270,7 +302,7 @@
 
 long str_base::rindex(object_cref sub) const
 {
- long result = PyInt_AsLong(this->attr("rindex")(sub).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -278,7 +310,7 @@
 
 long str_base::rindex(object_cref sub, object_cref start) const
 {
- long result = PyInt_AsLong(this->attr("rindex")(sub,start).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -286,7 +318,7 @@
 
 long str_base::rindex(object_cref sub, object_cref start, object_cref end) const
 {
- long result = PyInt_AsLong(this->attr("rindex")(sub,start,end).ptr());
+ long result = _BOOST_PYTHON_ASLONG(this->attr("rindex")(sub,start,end).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -322,7 +354,7 @@
 
 bool str_base::startswith(object_cref prefix) const
 {
- bool result = PyInt_AsLong(this->attr("startswith")(prefix).ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -330,7 +362,7 @@
 
 bool str_base::startswith(object_cref prefix, object_cref start) const
 {
- bool result = PyInt_AsLong(this->attr("startswith")(prefix,start).ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
@@ -338,12 +370,14 @@
 
 bool str_base::startswith(object_cref prefix, object_cref start, object_cref end) const
 {
- bool result = PyInt_AsLong(this->attr("startswith")(prefix,start,end).ptr());
+ bool result = _BOOST_PYTHON_ASLONG(this->attr("startswith")(prefix,start,end).ptr());
     if (PyErr_Occurred())
         throw_error_already_set();
     return result;
 }
 
+#undef _BOOST_PYTHON_ASLONG
+
 BOOST_PYTHON_DEFINE_STR_METHOD(strip, 0)
 BOOST_PYTHON_DEFINE_STR_METHOD(swapcase, 0)
 BOOST_PYTHON_DEFINE_STR_METHOD(title, 0)
@@ -357,7 +391,12 @@
     {
         const_cast<converter::registration &>(
             converter::registry::lookup(boost::python::type_id<boost::python::str>())
- ).m_class_object = &PyString_Type;
+ )
+#if PY_VERSION_HEX >= 0x03000000
+ .m_class_object = &PyUnicode_Type;
+#else
+ .m_class_object = &PyString_Type;
+#endif
     }
 }register_str_pytype_ptr_;
     

Modified: branches/release/libs/python/test/Jamfile.v2
==============================================================================
--- branches/release/libs/python/test/Jamfile.v2 (original)
+++ branches/release/libs/python/test/Jamfile.v2 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -77,12 +77,15 @@
 [ bpl-test shared_ptr ]
 [ bpl-test enable_shared_from_this ]
 [ bpl-test andreas_beyer ]
+[ bpl-test wrapper_held_type ]
+
+[ bpl-test polymorphism2_auto_ptr
+ : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp
+]
+
 [ bpl-test polymorphism ]
 [ bpl-test polymorphism2 ]
 
-[ bpl-test wrapper_held_type ]
-[ bpl-test polymorphism2_auto_ptr ]
-
 [ bpl-test auto_ptr ]
 
 [ bpl-test minimal ]

Modified: branches/release/libs/python/test/a_map_indexing_suite.cpp
==============================================================================
--- branches/release/libs/python/test/a_map_indexing_suite.cpp (original)
+++ branches/release/libs/python/test/a_map_indexing_suite.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -48,7 +48,11 @@
 
   static void* convertible(PyObject* obj_ptr)
   {
+#if PY_VERSION_HEX >= 0x03000000
+ if (!PyLong_Check(obj_ptr)) return 0;
+#else
     if (!PyInt_Check(obj_ptr)) return 0;
+#endif
     return obj_ptr;
   }
 
@@ -60,7 +64,11 @@
         (boost::python::converter::rvalue_from_python_storage< A >*)
         data)-> storage.bytes;
 
+#if PY_VERSION_HEX >= 0x03000000
+ new (storage) A((int)PyLong_AsLong(obj_ptr));
+#else
     new (storage) A((int)PyInt_AsLong(obj_ptr));
+#endif
     data->convertible = storage;
   }
 };

Modified: branches/release/libs/python/test/crossmod_opaque.py
==============================================================================
--- branches/release/libs/python/test/crossmod_opaque.py (original)
+++ branches/release/libs/python/test/crossmod_opaque.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -1,4 +1,4 @@
-# -*- coding: iso-latin-1 -*-
+# -*- coding: latin-1 -*-
 # Copyright Gottfried Ganßauge 2006.
 # Distributed under the Boost Software License, Version 1.0. (See
 # accompanying file LICENSE_1_0.txt or copy at

Modified: branches/release/libs/python/test/defaults.py
==============================================================================
--- branches/release/libs/python/test/defaults.py (original)
+++ branches/release/libs/python/test/defaults.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -2,13 +2,6 @@
 # Software License, Version 1.0. (See accompanying
 # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 """
-# Use builtin True/False when available:
->>> try:
-... assert(True == 1)
-... except:
-... True = 1
-... False = 0
-
>>> from defaults_ext import *
>>> bar(1)
 'int(1); char(D); string(default); double(0.0); '

Modified: branches/release/libs/python/test/dict.py
==============================================================================
--- branches/release/libs/python/test/dict.py (original)
+++ branches/release/libs/python/test/dict.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -20,7 +20,7 @@
 [(1, {'key2': 'value2'}), ('key1', 'value1')]
>>> print dict_from_sequence([(1,1),(2,2),(3,3)])
 {1: 1, 2: 2, 3: 3}
->>> test_templates(printer)
+>>> test_templates(printer) #doctest: +NORMALIZE_WHITESPACE
 a test string
 13
 None

Modified: branches/release/libs/python/test/exec.cpp
==============================================================================
--- branches/release/libs/python/test/exec.cpp (original)
+++ branches/release/libs/python/test/exec.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -59,7 +59,13 @@
 void exec_test()
 {
   // Register the module with the interpreter
- if (PyImport_AppendInittab(const_cast<char*>("embedded_hello"), initembedded_hello) == -1)
+ if (PyImport_AppendInittab(const_cast<char*>("embedded_hello"),
+#if PY_VERSION_HEX >= 0x03000000
+ PyInit_embedded_hello
+#else
+ initembedded_hello
+#endif
+ ) == -1)
     throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
                  "builtin modules");
   // Retrieve the main module
@@ -105,7 +111,7 @@
 {
   // Execute a statement that raises a python exception.
   python::dict global;
- python::object result = python::exec("print unknown \n", global, global);
+ python::object result = python::exec("print(unknown) \n", global, global);
 }
 
 void exercise_embedding_html()

Modified: branches/release/libs/python/test/exec.py
==============================================================================
--- branches/release/libs/python/test/exec.py (original)
+++ branches/release/libs/python/test/exec.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -2,5 +2,5 @@
 # Software License, Version 1.0. (See accompanying
 # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
-print 'Hello World !'
-number = 42
+if 1:
+ number = 42

Modified: branches/release/libs/python/test/iterator.py
==============================================================================
--- branches/release/libs/python/test/iterator.py (original)
+++ branches/release/libs/python/test/iterator.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -53,7 +53,7 @@
>>> ll.push_back(x)
>>> x.push_back(7)
>>> ll.push_back(x)
->>> for a in ll:
+>>> for a in ll: #doctest: +NORMALIZE_WHITESPACE
 ... for b in a:
 ... print b,
 ... print

Modified: branches/release/libs/python/test/list.cpp
==============================================================================
--- branches/release/libs/python/test/list.cpp (original)
+++ branches/release/libs/python/test/list.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -7,6 +7,8 @@
 #include <boost/python/def.hpp>
 #include <boost/python/class.hpp>
 #include <boost/python/list.hpp>
+#include <boost/python/tuple.hpp>
+#include <boost/python/dict.hpp>
 #include <boost/python/make_function.hpp>
 #include <boost/lexical_cast.hpp>
 #define BOOST_ENABLE_ASSERT_HANDLER
@@ -109,11 +111,16 @@
 
     print("sorted:");
     x.pop(2); // make sorting predictable
+ x.pop(2); // remove [1,2] so the list is sortable in py3k
     x.sort();
     print(x);
 
     print("reverse sorted:");
+#if PY_VERSION_HEX >= 0x03000000
+ x.sort(*tuple(), **dict(make_tuple(make_tuple("reverse", true))));
+#else
     x.sort(&notcmp);
+#endif
     print(x);
 
     list w;

Modified: branches/release/libs/python/test/list.py
==============================================================================
--- branches/release/libs/python/test/list.py (original)
+++ branches/release/libs/python/test/list.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -73,7 +73,7 @@
 ...
 
>>> y = X(42)
->>> exercise(letters, y, printer)
+>>> exercise(letters, y, printer) #doctest: +NORMALIZE_WHITESPACE
 after append:
 ['h', 'e', 'l', 'l', 'o', '.', [1, 2], X(42), 5, X(3)]
 number of X(42) instances: 1
@@ -97,9 +97,9 @@
 reversing...
 ['y', 'x', X(3), [1, 2], '.', 'o', 'l', 'l', 'e', 'h']
 sorted:
-[[1, 2], '.', 'e', 'h', 'l', 'l', 'o', 'x', 'y']
+['.', 'e', 'h', 'l', 'l', 'o', 'x', 'y']
 reverse sorted:
-['y', 'x', 'o', 'l', 'l', 'h', 'e', '.', [1, 2]]
+['y', 'x', 'o', 'l', 'l', 'h', 'e', '.']
 '''
 
 def run(args = None):

Modified: branches/release/libs/python/test/long.py
==============================================================================
--- branches/release/libs/python/test/long.py (original)
+++ branches/release/libs/python/test/long.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -3,12 +3,12 @@
 # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 '''
>>> from long_ext import *
->>> new_long()
-0L
->>> longify(42)
-42L
->>> longify_string('300')
-300L
+>>> print new_long()
+0
+>>> print longify(42)
+42
+>>> print longify_string('300')
+300
>>> is_long(20L)
 'yes'
>>> is_long('20')

Modified: branches/release/libs/python/test/m1.cpp
==============================================================================
--- branches/release/libs/python/test/m1.cpp (original)
+++ branches/release/libs/python/test/m1.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -32,8 +32,7 @@
 };
 
 PyTypeObject NoddyType = {
- PyObject_HEAD_INIT(NULL)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
     const_cast<char*>("Noddy"),
     sizeof(NoddyObject),
     0,
@@ -104,8 +103,7 @@
 };
 
 PyTypeObject SimpleType = {
- PyObject_HEAD_INIT(NULL)
- 0,
+ PyVarObject_HEAD_INIT(NULL, 0)
     const_cast<char*>("Simple"),
     sizeof(SimpleObject),
     0,

Modified: branches/release/libs/python/test/m2.cpp
==============================================================================
--- branches/release/libs/python/test/m2.cpp (original)
+++ branches/release/libs/python/test/m2.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -13,6 +13,11 @@
 #include <boost/python/return_value_policy.hpp>
 #include "simple_type.hpp"
 
+#if PY_VERSION_HEX >= 0x03000000
+# define PyString_FromString PyUnicode_FromString
+# define PyInt_FromLong PyLong_FromLong
+#endif
+
 // Get a simple (by value) from the argument, and return the
 // string it holds.
 PyObject* unwrap_simple(simple x)
@@ -52,6 +57,11 @@
     return PyInt_FromLong(x);
 }
 
+#if PY_VERSION_HEX >= 0x03000000
+# undef PyString_FromString
+# undef PyInt_FromLong
+#endif
+
 // rewrap<T> extracts a T from the argument, then converts the T back
 // to a PyObject* and returns it.
 template <class T>

Modified: branches/release/libs/python/test/map_indexing_suite.py
==============================================================================
--- branches/release/libs/python/test/map_indexing_suite.py (original)
+++ branches/release/libs/python/test/map_indexing_suite.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -197,7 +197,7 @@
>>> tm["kimpo"] = X("bbb")
>>> print_xmap(tm)
 [ (joel, aaa) (kimpo, bbb) ]
->>> for el in tm:
+>>> for el in tm: #doctest: +NORMALIZE_WHITESPACE
 ... print el.key(),
 ... dom = el.data()
 joel kimpo

Modified: branches/release/libs/python/test/opaque.py
==============================================================================
--- branches/release/libs/python/test/opaque.py (original)
+++ branches/release/libs/python/test/opaque.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -1,4 +1,4 @@
-# -*- coding: iso-latin-1 -*-
+# -*- coding: latin-1 -*-
 # Copyright Gottfried Ganßauge 2003..2006. Distributed under the Boost
 # Software License, Version 1.0. (See accompanying
 # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Modified: branches/release/libs/python/test/pickle2.py
==============================================================================
--- branches/release/libs/python/test/pickle2.py (original)
+++ branches/release/libs/python/test/pickle2.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -29,7 +29,7 @@
>>> wd.__dict__
     {'x': 1}
>>> try: pstr = pickle.dumps(wd)
- ... except RuntimeError, err: print err[0]
+ ... except RuntimeError, err: print err
     ...
     Incomplete pickle support (__getstate_manages_dict__ not set)
 '''

Modified: branches/release/libs/python/test/str.cpp
==============================================================================
--- branches/release/libs/python/test/str.cpp (original)
+++ branches/release/libs/python/test/str.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -26,8 +26,13 @@
     print(data.capitalize());
     print('[' + data.center(30) + ']');
     print(data.count("t"));
+#if PY_VERSION_HEX < 0x03000000
     print(data.encode("utf-8"));
     print(data.decode("utf-8"));
+#else
+ print(data.encode("utf-8").attr("decode")("utf-8"));
+ print(data.encode("utf-8").attr("decode")("utf-8"));
+#endif
     
     BOOST_ASSERT(!data.endswith("xx"));
     BOOST_ASSERT(!data.startswith("test"));

Modified: branches/release/libs/python/test/str.py
==============================================================================
--- branches/release/libs/python/test/str.py (original)
+++ branches/release/libs/python/test/str.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -7,7 +7,7 @@
 ... for x in args: print x,
 ... print
 ...
->>> work_with_string(printer)
+>>> work_with_string(printer) #doctest: +NORMALIZE_WHITESPACE
 ['this', 'is', 'a', 'demo', 'string']
 ['this', 'is', 'a', 'demo string']
 this<->is<->a<->demo<->string

Modified: branches/release/libs/python/test/test_builtin_converters.py
==============================================================================
--- branches/release/libs/python/test/test_builtin_converters.py (original)
+++ branches/release/libs/python/test/test_builtin_converters.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -77,10 +77,10 @@
>>> hex(rewrap_value_unsigned_long(0x80000001L)).replace('L','')
 '0x80000001'
 
->>> rewrap_value_long_long(42)
-42L
->>> rewrap_value_unsigned_long_long(42)
-42L
+>>> rewrap_value_long_long(42) == 42
+True
+>>> rewrap_value_unsigned_long_long(42) == 42
+True
 
    show that we have range checking.
 
@@ -130,23 +130,13 @@
>>> rewrap_value_string('yo, wassup?')
 'yo, wassup?'
 
->>> try:
-... if unicode: pass
-... except:
-... print "u'yo, wassup?'"
-... else:
-... eval("rewrap_value_wstring(u'yo, wassup?')")
-u'yo, wassup?'
-
+>>> print rewrap_value_wstring(u'yo, wassup?')
+yo, wassup?
+
    test that overloading on unicode works:
 
->>> try:
-... if unicode: pass
-... except:
-... print "u'yo, wassup?'"
-... else:
-... eval("rewrap_value_string(u'yo, wassup?')")
-u'yo, wassup?'
+>>> print rewrap_value_string(u'yo, wassup?')
+yo, wassup?
 
    wrap strings with embedded nulls:
    
@@ -198,10 +188,10 @@
 42
>>> rewrap_const_reference_unsigned_long(42)
 42
->>> rewrap_const_reference_long_long(42)
-42L
->>> rewrap_const_reference_unsigned_long_long(42)
-42L
+>>> rewrap_const_reference_long_long(42) == 42
+True
+>>> rewrap_const_reference_unsigned_long_long(42) == 42
+True
 
 
>>> assert abs(rewrap_const_reference_float(4.2) - 4.2) < .000001

Modified: branches/release/libs/python/test/tuple.py
==============================================================================
--- branches/release/libs/python/test/tuple.py (original)
+++ branches/release/libs/python/test/tuple.py 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -11,7 +11,7 @@
 ('t', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 't', 'e', 's', 't', ' ', 's', 't', 'r', 'i', 'n', 'g')
>>> t1 = convert_to_tuple("this is")
>>> t2 = (1,2,3,4)
->>> test_operators(t1,t2,printer)
+>>> test_operators(t1,t2,printer) #doctest: +NORMALIZE_WHITESPACE
 ('t', 'h', 'i', 's', ' ', 'i', 's', 1, 2, 3, 4)
>>> make_tuple()
 ()

Modified: branches/release/libs/python/test/upcast.cpp
==============================================================================
--- branches/release/libs/python/test/upcast.cpp (original)
+++ branches/release/libs/python/test/upcast.cpp 2009-10-13 18:37:59 EDT (Tue, 13 Oct 2009)
@@ -13,7 +13,7 @@
 {
     PyTypeObject o;
     Y y;
- BOOST_TEST(&boost::python::upcast<PyObject>(&o)->ob_refcnt == &o.ob_refcnt);
- BOOST_TEST(&boost::python::upcast<PyObject>(&y)->ob_refcnt == &y.ob_refcnt);
+ BOOST_TEST(&Py_REFCNT(boost::python::upcast<PyObject>(&o)) == &Py_REFCNT(&o));
+ BOOST_TEST(&Py_REFCNT(boost::python::upcast<PyObject>(&y)) == &Py_REFCNT(&y));
     return boost::report_errors();
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk