$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r52118 - in sandbox-branches/bhy/py3k: boost/python boost/python/converter boost/python/detail libs/python/src libs/python/src/converter libs/python/src/object
From: divinekid_at_[hidden]
Date: 2009-04-01 15:03:27
Author: bhy
Date: 2009-04-01 15:03:25 EDT (Wed, 01 Apr 2009)
New Revision: 52118
URL: http://svn.boost.org/trac/boost/changeset/52118
Log:
preliminary work - 14 BPL .cpp files can be compiled with Python 3 now.
Text files modified: 
   sandbox-branches/bhy/py3k/boost/python/converter/builtin_converters.hpp |    25 ++++++++-                               
   sandbox-branches/bhy/py3k/boost/python/converter/pyobject_traits.hpp    |     2                                         
   sandbox-branches/bhy/py3k/boost/python/detail/wrap_python.hpp           |    13 +++++                                   
   sandbox-branches/bhy/py3k/boost/python/list.hpp                         |     2                                         
   sandbox-branches/bhy/py3k/boost/python/str.hpp                          |     4 +                                       
   sandbox-branches/bhy/py3k/libs/python/src/converter/from_python.cpp     |    21 ++++++-                                 
   sandbox-branches/bhy/py3k/libs/python/src/converter/registry.cpp        |     7 ++                                      
   sandbox-branches/bhy/py3k/libs/python/src/list.cpp                      |    17 ++++++                                  
   sandbox-branches/bhy/py3k/libs/python/src/object/class.cpp              |    55 ++++++++++++--------                    
   sandbox-branches/bhy/py3k/libs/python/src/object/enum.cpp               |    43 +++++++++++++---                        
   sandbox-branches/bhy/py3k/libs/python/src/object/function.cpp           |    26 ++++++++-                               
   sandbox-branches/bhy/py3k/libs/python/src/str.cpp                       |   104 +++++++++++++++++++++++++++------------ 
   12 files changed, 242 insertions(+), 77 deletions(-)
Modified: sandbox-branches/bhy/py3k/boost/python/converter/builtin_converters.hpp
==============================================================================
--- sandbox-branches/bhy/py3k/boost/python/converter/builtin_converters.hpp	(original)
+++ sandbox-branches/bhy/py3k/boost/python/converter/builtin_converters.hpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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
@@ -115,18 +124,28 @@
 
 // using Python's macro instead of Boost's - we don't seem to get the
 // config right all the time.
+// XXX(bhy) It was PyInt_Type instead of PyLong_Type here.
+// But why PyInt_Type? PyLong_From* converter is used here!
 # 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, ::PyBytes_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)
+// XXX(bhy) Here, similar to the above, PyString_Type -> PyUnicode_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: sandbox-branches/bhy/py3k/boost/python/converter/pyobject_traits.hpp
==============================================================================
--- sandbox-branches/bhy/py3k/boost/python/converter/pyobject_traits.hpp	(original)
+++ sandbox-branches/bhy/py3k/boost/python/converter/pyobject_traits.hpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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: sandbox-branches/bhy/py3k/boost/python/detail/wrap_python.hpp
==============================================================================
--- sandbox-branches/bhy/py3k/boost/python/detail/wrap_python.hpp	(original)
+++ sandbox-branches/bhy/py3k/boost/python/detail/wrap_python.hpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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: sandbox-branches/bhy/py3k/boost/python/list.hpp
==============================================================================
--- sandbox-branches/bhy/py3k/boost/python/list.hpp	(original)
+++ sandbox-branches/bhy/py3k/boost/python/list.hpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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
+      Py_ssize_t count(object_cref value) const; // return number of occurrences of value
 
       void extend(object_cref sequence); // extend list by appending sequence elements
     
Modified: sandbox-branches/bhy/py3k/boost/python/str.hpp
==============================================================================
--- sandbox-branches/bhy/py3k/boost/python/str.hpp	(original)
+++ sandbox-branches/bhy/py3k/boost/python/str.hpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 2009)
@@ -404,7 +404,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: sandbox-branches/bhy/py3k/libs/python/src/converter/from_python.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/converter/from_python.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/converter/from_python.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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: sandbox-branches/bhy/py3k/libs/python/src/converter/registry.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/converter/registry.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/converter/registry.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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: sandbox-branches/bhy/py3k/libs/python/src/list.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/list.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/list.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 2009)
@@ -48,7 +48,14 @@
 long list_base::index(object_cref value) const
 {
     object result_obj(this->attr("index")(value));
+    // TODO(bhy) In Python 2.5, PyInt_AsSsize_t did the same thing as PyLong_AsSsize_t,
+    // i.e., it can accepts both int and long. So we may have a better way to do this,
+    // so we can support ssize_t with Python 2.x.
+#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 +76,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);
@@ -128,10 +139,14 @@
 
 // For some reason, moving this to the end of the TU suppresses an ICE
 // with vc6.
-long list_base::count(object_cref value) const
+Py_ssize_t list_base::count(object_cref value) const
 {
     object result_obj(this->attr("count")(value));
+#if PY_VERSION_HEX >= 0x03000000
+    Py_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: sandbox-branches/bhy/py3k/libs/python/src/object/class.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/object/class.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/object/class.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 2009)
@@ -106,8 +106,7 @@
 }
 
 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,
     0,
@@ -160,17 +159,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 +205,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 +267,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 +280,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 +309,7 @@
 
           Py_XDECREF(kill_me->dict);
           
-          inst->ob_type->tp_free(inst);
+          Py_TYPE(inst)->tp_free(inst);
       }
 
       static PyObject *
@@ -318,7 +319,13 @@
           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;
+          // TODO(bhy) ssize_t for Python 2.x
+          Py_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 +339,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 +380,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 +435,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 +447,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);
@@ -527,7 +538,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;
@@ -651,7 +662,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();
@@ -681,18 +692,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
@@ -706,9 +717,9 @@
 
 void instance_holder::deallocate(PyObject* self_, void* storage) throw()
 {
-    assert(self_->ob_type->ob_type == &class_metatype_object);
+    assert(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: sandbox-branches/bhy/py3k/libs/python/src/object/enum.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/object/enum.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/object/enum.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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,33 @@
 {
     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)", mod, self_->ob_type->tp_name, PyInt_AS_LONG(self_));
+#endif
         }
         else
         {
-            char* name = PyString_AsString(self->name);
+            //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
+#else
+                PyString_FromFormat
+#endif
+                ("%S.%s.%S", mod, self_->ob_type->tp_name, name);
         }
     }
 
@@ -53,7 +71,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 +85,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 +105,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 +148,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 >= 0x02060000
+          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: sandbox-branches/bhy/py3k/libs/python/src/object/function.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/object/function.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/object/function.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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: sandbox-branches/bhy/py3k/libs/python/src/str.cpp
==============================================================================
--- sandbox-branches/bhy/py3k/libs/python/src/str.cpp	(original)
+++ sandbox-branches/bhy/py3k/libs/python/src/str.cpp	2009-04-01 15:03:25 EDT (Wed, 01 Apr 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) )
         )
     )
 {}
@@ -122,9 +145,17 @@
     return this->attr("encode")(encoding,errors);
 }
 
+
+// XXX(bhy) Why not use extract<long> instead of Python C-API?
+#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 +166,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 +174,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 +182,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 +190,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 +198,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 +206,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 +214,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 +222,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 +230,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 +238,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 +246,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 +254,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 +262,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 +277,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 +285,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 +293,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 +301,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 +309,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 +317,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 +353,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 +361,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 +369,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 +390,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_;