Boost logo

Boost :

From: scott snyder (snyder_at_[hidden])
Date: 2001-12-09 19:00:33


hi -

Here's a revised version of the inplace operator patches for Boost.Python.
This version includes an update for the documentation; the `comprehensive'
test has also been extended to test these features.

I also fixed a problem with the inplace power operator. I call attention
to this because i think the same problem is also present in the existing
non-inplace version, from which i copied it.

We have the following in classes.cpp:

PyObject* instance::power(PyObject* exponent, PyObject* modulus)
{
    if (as_object(modulus->ob_type) == Py_None)
        return callback<PyObject*>::call_method(this, "__pow__", exponent);
    else
        return callback<PyObject*>::call_method(this, "__pow__", exponent, modulus);
}

When the ordinary (2-arg) version of power is used, `modulus' is Py_None.
But `as_object(Py_None->ob_type)' is not Py_None --- the type of None
isn't None. I think that the test should be written as just

    if (modulus == Py_None)

(since there's only one None object).

Before i made that change for the inplace version, i was getting
errors about passing the wrong number of arguments.

And here's one other trivial typo i came across:

Index: libs/python/src/types.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/src/types.cpp,v
retrieving revision 1.5
diff -u -p -r1.5 types.cpp
--- libs/python/src/types.cpp 2001/11/15 00:51:33 1.5
+++ libs/python/src/types.cpp 2001/12/09 21:48:54
@@ -970,7 +1062,7 @@ PyObject* type_object_base::instance_num
 
 PyObject* type_object_base::instance_number_power(PyObject*, PyObject*, PyObject*) const
 {
- return unimplemented("instance_number_divmod");
+ return unimplemented("instance_number_power");
 }
 
 PyObject* type_object_base::instance_number_negative(PyObject*) const

The diffs (against the current cvs) follow.
If this looks ok, i'll move on to the other two patches.

thanks,
sss

Index: boost/python/classes.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/python/classes.hpp,v
retrieving revision 1.2
diff -u -p -r1.2 classes.hpp
--- boost/python/classes.hpp 2001/07/31 07:12:14 1.2
+++ boost/python/classes.hpp 2001/12/09 21:48:45
@@ -78,6 +78,19 @@ class instance
     PyObject* gt(PyObject* other);
     PyObject* ge(PyObject* other);
 
+ // Inplace operations.
+ PyObject* inplace_add(PyObject* other);
+ PyObject* inplace_subtract(PyObject* other);
+ PyObject* inplace_multiply(PyObject* other);
+ PyObject* inplace_divide(PyObject* other);
+ PyObject* inplace_remainder(PyObject* other);
+ PyObject* inplace_power(PyObject* exponent, PyObject* modulus);
+ PyObject* inplace_lshift(PyObject* other);
+ PyObject* inplace_rshift(PyObject* other);
+ PyObject* inplace_and(PyObject* other);
+ PyObject* inplace_or(PyObject* other);
+ PyObject* inplace_xor(PyObject* other);
+
  private: // noncopyable, without the size bloat
     instance(const instance&);
     void operator=(const instance&);
@@ -178,6 +191,18 @@ class class_t
     PyObject* instance_number_oct(PyObject*) const;
     PyObject* instance_number_hex(PyObject*) const;
 
+ PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
+ PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
+
  private: // Implement rich comparisons
     PyObject* instance_lt(PyObject*, PyObject*) const;
     PyObject* instance_le(PyObject*, PyObject*) const;
@@ -491,6 +516,72 @@ template <class T>
 PyObject* class_t<T>::instance_number_hex(PyObject* obj) const
 {
     return downcast<T>(obj)->hex();
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_add(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_add(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_subtract(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_subtract(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_multiply(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_multiply(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_divide(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_divide(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_remainder(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_remainder(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus) const
+{
+ return downcast<T>(obj)->inplace_power(exponent, modulus);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_lshift(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_lshift(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_rshift(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_rshift(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_and(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_and(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_or(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_or(other);
+}
+
+template <class T>
+PyObject* class_t<T>::instance_number_inplace_xor(PyObject* obj, PyObject* other) const
+{
+ return downcast<T>(obj)->inplace_xor(other);
 }
 
 template <class T>
Index: boost/python/detail/types.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/python/detail/types.hpp,v
retrieving revision 1.3
diff -u -p -r1.3 types.hpp
--- boost/python/detail/types.hpp 2001/07/31 07:12:14 1.3
+++ boost/python/detail/types.hpp 2001/12/09 21:48:45
@@ -57,7 +57,11 @@ class type_object_base : public python_t
         number_positive, number_absolute, number_nonzero, number_invert,
         number_lshift, number_rshift, number_and, number_xor, number_or,
         number_coerce, number_int, number_long, number_float, number_oct,
- number_hex
+ number_hex, number_inplace_add, number_inplace_subtract,
+ number_inplace_multiply, number_inplace_divide,
+ number_inplace_remainder, number_inplace_power,
+ number_inplace_lshift, number_inplace_rshift,
+ number_inplace_and, number_inplace_or, number_inplace_xor
     };
     
     void enable(capability);
@@ -115,6 +119,18 @@ class type_object_base : public python_t
     virtual PyObject* instance_number_float(PyObject*) const;
     virtual PyObject* instance_number_oct(PyObject*) const;
     virtual PyObject* instance_number_hex(PyObject*) const;
+
+ virtual PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
+ virtual PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
 
  public: // Callbacks for rich comparisons
     virtual PyObject* instance_lt(PyObject*, PyObject*) const;
Index: libs/python/doc/special.html
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/doc/special.html,v
retrieving revision 1.9
diff -u -p -r1.9 special.html
--- libs/python/doc/special.html 2001/07/31 07:12:14 1.9
+++ libs/python/doc/special.html 2001/12/09 21:48:54
@@ -287,6 +287,35 @@ bignum_class.def(&amp;rmod, "__rmod__")
         found first (be it ``<code>int</code>`` or ``<code>float</code>'') will be
         used for either of the two types.
 
+<h3><a name="inplace">Inplace Operators</a></h3>
+<p>
+ Boost.Python can also be used to expose inplace numeric operations
+ (i.e., <code>+=</code> and so forth). These operators must be wrapped
+ manually, as described in the previous section. For example, suppose
+ the class BigNum has an <code>operator+=</code>:
+
+<blockquote><pre>
+BigNum& operator+= (BigNum const&amp; right);
+</pre></blockquote>
+
+ This can be exposed by first writing a wrapper function:
+
+<blockquote><pre>
+BigNum& iadd (BigNum&amp; self, const BigNum&amp; right)
+{
+ return self += right;
+}
+</pre></blockquote>
+
+ and then exposing the wrapper with
+
+<blockquote><pre>
+bignum_class.def(&amp;iadd, "__iadd__");
+</pre></blockquote>
+
+
+
+
 <h3><a name="coercion">Coercion</a></h3>
 
 
Index: libs/python/src/classes.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/src/classes.cpp,v
retrieving revision 1.6
diff -u -p -r1.6 classes.cpp
--- libs/python/src/classes.cpp 2001/07/31 07:12:14 1.6
+++ libs/python/src/classes.cpp 2001/12/09 21:48:54
@@ -766,6 +766,64 @@ PyObject* instance::ge(PyObject* other)
     return callback<PyObject*>::call_method(this, "__ge__", other);
 }
 
+PyObject* instance::inplace_add(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__iadd__", other);
+}
+
+PyObject* instance::inplace_subtract(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__isub__", other);
+}
+
+PyObject* instance::inplace_multiply(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__imul__", other);
+}
+
+PyObject* instance::inplace_divide(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__idiv__", other);
+}
+
+PyObject* instance::inplace_remainder(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__imod__", other);
+}
+
+PyObject* instance::inplace_power(PyObject* exponent, PyObject* modulus)
+{
+ if (modulus == Py_None)
+ return callback<PyObject*>::call_method(this, "__ipow__", exponent);
+ else
+ return callback<PyObject*>::call_method(this, "__ipow__", exponent, modulus);
+}
+
+PyObject* instance::inplace_lshift(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__ilshift__", other);
+}
+
+PyObject* instance::inplace_rshift(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__irshift__", other);
+}
+
+PyObject* instance::inplace_and(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__iand__", other);
+}
+
+PyObject* instance::inplace_or(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__ior__", other);
+}
+
+PyObject* instance::inplace_xor(PyObject* other)
+{
+ return callback<PyObject*>::call_method(this, "__ixor__", other);
+}
+
 namespace {
   struct named_capability
   {
@@ -783,6 +841,17 @@ namespace {
       { "__le__", detail::type_object_base::richcompare },
       { "__eq__", detail::type_object_base::richcompare },
       { "__ne__", detail::type_object_base::richcompare },
+ { "__iadd__", detail::type_object_base::number_inplace_add },
+ { "__isub__", detail::type_object_base::number_inplace_subtract },
+ { "__imul__", detail::type_object_base::number_inplace_multiply },
+ { "__idiv__", detail::type_object_base::number_inplace_divide },
+ { "__imod__", detail::type_object_base::number_inplace_remainder },
+ { "__ipow__", detail::type_object_base::number_inplace_power },
+ { "__ilshift__", detail::type_object_base::number_inplace_lshift },
+ { "__irshift__", detail::type_object_base::number_inplace_rshift },
+ { "__iand__", detail::type_object_base::number_inplace_and },
+ { "__ixor__", detail::type_object_base::number_inplace_xor },
+ { "__ior__", detail::type_object_base::number_inplace_or },
       { "__repr__", detail::type_object_base::repr },
       { "__str__", detail::type_object_base::str },
       { "__call__", detail::type_object_base::call },
Index: libs/python/src/types.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/src/types.cpp,v
retrieving revision 1.5
diff -u -p -r1.5 types.cpp
--- libs/python/src/types.cpp 2001/11/15 00:51:33 1.5
+++ libs/python/src/types.cpp 2001/12/09 21:48:54
@@ -455,6 +455,61 @@ static PyObject* do_instance_nb_hex(PyOb
     return call(obj, &type_object_base::instance_number_hex);
 }
 
+static PyObject* do_instance_nb_inplace_add(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_add, other);
+}
+
+static PyObject* do_instance_nb_inplace_subtract(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_subtract, other);
+}
+
+static PyObject* do_instance_nb_inplace_multiply(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_multiply, other);
+}
+
+static PyObject* do_instance_nb_inplace_divide(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_divide, other);
+}
+
+static PyObject* do_instance_nb_inplace_remainder(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_remainder, other);
+}
+
+static PyObject* do_instance_nb_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus)
+{
+ return call(obj, &type_object_base::instance_number_inplace_power, exponent, modulus);
+}
+
+static PyObject* do_instance_nb_inplace_lshift(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_lshift, other);
+}
+
+static PyObject* do_instance_nb_inplace_rshift(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_rshift, other);
+}
+
+static PyObject* do_instance_nb_inplace_and(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_and, other);
+}
+
+static PyObject* do_instance_nb_inplace_or(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_or, other);
+}
+
+static PyObject* do_instance_nb_inplace_xor(PyObject* obj, PyObject* other)
+{
+ return call(obj, &type_object_base::instance_number_inplace_xor, other);
+}
+
 } // extern "C"
 
 namespace
@@ -511,6 +566,41 @@ bool add_capability_richcompare(type_obj
     return false;
 }
 
+#if PYTHON_API_VERSION >= 1010
+# define ENABLE_INPLACE_CAPABILITY1 \
+ dest->tp_flags |= Py_TPFLAGS_HAVE_INPLACEOPS;
+#else
+# define ENABLE_INPLACE_CAPABILITY1
+#endif
+#define ENABLE_INPLACE_CAPABILITY(field) \
+ case type_object_base::number_##field: \
+ create_method_table_if_null(dest->tp_as_number); \
+ dest->tp_as_number->nb_##field = &do_instance_nb_##field; \
+ detail::shared_pod_manager::replace_if_equal(dest->tp_as_number); \
+ ENABLE_INPLACE_CAPABILITY1 \
+ return true
+
+bool add_capability_inplace(type_object_base::capability capability, PyTypeObject* dest)
+{
+ assert(dest != 0);
+ switch (capability)
+ {
+ ENABLE_INPLACE_CAPABILITY (inplace_add);
+ ENABLE_INPLACE_CAPABILITY (inplace_subtract);
+ ENABLE_INPLACE_CAPABILITY (inplace_multiply);
+ ENABLE_INPLACE_CAPABILITY (inplace_divide);
+ ENABLE_INPLACE_CAPABILITY (inplace_remainder);
+ ENABLE_INPLACE_CAPABILITY (inplace_power);
+ ENABLE_INPLACE_CAPABILITY (inplace_lshift);
+ ENABLE_INPLACE_CAPABILITY (inplace_rshift);
+ ENABLE_INPLACE_CAPABILITY (inplace_and);
+ ENABLE_INPLACE_CAPABILITY (inplace_or);
+ ENABLE_INPLACE_CAPABILITY (inplace_xor);
+ default:
+ return false;
+ }
+}
+
 #define ENABLE_MAPPING_CAPABILITY(field) \
     case type_object_base::mapping_##field: \
         create_method_table_if_null(dest); \
@@ -626,6 +716,8 @@ namespace detail {
         return;
     if(add_capability_richcompare(capability, dest_))
         return;
+ if(add_capability_inplace(capability, dest_))
+ return;
     if(add_capability_mapping(capability, dest_->tp_as_mapping))
         return;
     if(add_capability_sequence(capability, dest_->tp_as_sequence))
@@ -1051,6 +1143,61 @@ PyObject* type_object_base::instance_num
 PyObject* type_object_base::instance_number_hex(PyObject*) const
 {
     return unimplemented("instance_number_hex");
+}
+
+PyObject* type_object_base::instance_number_inplace_add(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_add");
+}
+
+PyObject* type_object_base::instance_number_inplace_subtract(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_subtract");
+}
+
+PyObject* type_object_base::instance_number_inplace_multiply(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_multiply");
+}
+
+PyObject* type_object_base::instance_number_inplace_divide(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_divide");
+}
+
+PyObject* type_object_base::instance_number_inplace_remainder(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_remainder");
+}
+
+PyObject* type_object_base::instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_power");
+}
+
+PyObject* type_object_base::instance_number_inplace_lshift(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_lshift");
+}
+
+PyObject* type_object_base::instance_number_inplace_rshift(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_rshift");
+}
+
+PyObject* type_object_base::instance_number_inplace_and(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_and");
+}
+
+PyObject* type_object_base::instance_number_inplace_or(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_or");
+}
+
+PyObject* type_object_base::instance_number_inplace_xor(PyObject*, PyObject*) const
+{
+ return unimplemented("instance_number_inplace_xor");
 }
 
 PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const
Index: libs/python/test/comprehensive.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/test/comprehensive.cpp,v
retrieving revision 1.12
diff -u -p -r1.12 comprehensive.cpp
--- libs/python/test/comprehensive.cpp 2001/11/15 05:29:22 1.12
+++ libs/python/test/comprehensive.cpp 2001/12/09 21:48:54
@@ -667,7 +667,7 @@ int total_Ints = 0;
 
 struct Int
 {
- explicit Int(int i) : i_(i) {
+ explicit Int(int i) : i_(i), j_(0) {
 #ifndef NDEBUG
         ++total_Ints;
 #endif
@@ -675,12 +675,29 @@ struct Int
     
 #ifndef NDEBUG
     ~Int() { --total_Ints; }
- Int(const Int& rhs) : i_(rhs.i_) { ++total_Ints; }
+ Int(const Int& rhs) : i_(rhs.i_), j_(rhs.j_) { ++total_Ints; }
 #endif
     
     int i() const { return i_; }
+ int j() const { return j_; }
     
     int i_;
+ int j_;
+
+ Int& operator +=(Int const& r) { ++j_; i_ += r.i_; return *this; }
+ Int& operator -=(Int const& r) { ++j_; i_ -= r.i_; return *this; }
+ Int& operator *=(Int const& r) { ++j_; i_ *= r.i_; return *this; }
+ Int& operator /=(Int const& r) { ++j_; i_ /= r.i_; return *this; }
+ Int& operator %=(Int const& r) { ++j_; i_ %= r.i_; return *this; }
+ Int& ipow (Int const& r) { ++j_;
+ int o=i_;
+ for (int k=1; k<r.i_; k++) i_ *= o;
+ return *this; }
+ Int& operator <<=(Int const& r) { ++j_; i_ <<= r.i_; return *this; }
+ Int& operator >>=(Int const& r) { ++j_; i_ >>= r.i_; return *this; }
+ Int& operator &=(Int const& r) { ++j_; i_ &= r.i_; return *this; }
+ Int& operator |=(Int const& r) { ++j_; i_ |= r.i_; return *this; }
+ Int& operator ^=(Int const& r) { ++j_; i_ ^= r.i_; return *this; }
 };
 
 Int operator+(Int const & l, Int const & r) { return Int(l.i_ + r.i_); }
@@ -868,6 +885,19 @@ namespace bpl_test {
   double freal(const std::complex<float>& c) { return c.real(); }
   double fimag(std::complex<float> c) { return c.imag(); }
 
+ // Wrappers for inplace operators.
+ Int& int_iadd(Int& self, const Int& r) { self += r; return self; }
+ Int& int_isub(Int& self, const Int& r) { self -= r; return self; }
+ Int& int_imul(Int& self, const Int& r) { self *= r; return self; }
+ Int& int_idiv(Int& self, const Int& r) { self /= r; return self; }
+ Int& int_imod(Int& self, const Int& r) { self %= r; return self; }
+ Int& int_ipow(Int& self, const Int& r) { self.ipow (r); return self; }
+ Int& int_ilshift(Int& self, const Int& r) { self <<= r; return self; }
+ Int& int_irshift(Int& self, const Int& r) { self >>= r; return self; }
+ Int& int_iand(Int& self, const Int& r) { self &= r; return self; }
+ Int& int_ior(Int& self, const Int& r) { self |= r; return self; }
+ Int& int_ixor(Int& self, const Int& r) { self ^= r; return self; }
+
 /************************************************************/
 /* */
 /* init the module */
@@ -1042,6 +1072,7 @@ void init_module(boost::python::module_b
     boost::python::class_builder<Int> int_class(m, "Int");
     int_class.def(boost::python::constructor<int>());
     int_class.def(&Int::i, "i");
+ int_class.def(&Int::j, "j");
 
     // wrap homogeneous operators
     int_class.def(boost::python::operators<(boost::python::op_add | boost::python::op_sub | boost::python::op_neg |
@@ -1061,6 +1092,19 @@ void init_module(boost::python::module_b
                   boost::python::left_operand<int const & >());
     // export non-operator function as heterogeneous reverse-argument operator
     int_class.def(&rmul, "__rmul__");
+
+ // inplace operators.
+ int_class.def(&int_iadd, "__iadd__");
+ int_class.def(&int_isub, "__isub__");
+ int_class.def(&int_imul, "__imul__");
+ int_class.def(&int_idiv, "__idiv__");
+ int_class.def(&int_imod, "__imod__");
+ int_class.def(&int_ipow, "__ipow__");
+ int_class.def(&int_ilshift, "__ilshift__");
+ int_class.def(&int_irshift, "__irshift__");
+ int_class.def(&int_iand, "__iand__");
+ int_class.def(&int_ior, "__ior__");
+ int_class.def(&int_ixor, "__ixor__");
     
 
     boost::python::class_builder<EnumOwner> enum_owner(m, "EnumOwner");
Index: libs/python/test/comprehensive.py
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/test/comprehensive.py,v
retrieving revision 1.11
diff -u -p -r1.11 comprehensive.py
--- libs/python/test/comprehensive.py 2001/11/01 23:28:54 1.11
+++ libs/python/test/comprehensive.py 2001/12/09 21:48:54
@@ -1058,6 +1058,43 @@ test inheritB2
     Traceback (innermost last):
     TypeError: bad operand type(s) for pow()
 
+ >>> ii = Int(1)
+ >>> ii += Int(2)
+ >>> ii.i()
+ 3
+ >>> ii -= Int(1)
+ >>> ii.i()
+ 2
+ >>> ii *= Int(3)
+ >>> ii.i()
+ 6
+ >>> ii /= Int(2)
+ >>> ii.i()
+ 3
+ >>> ii <<= Int(2)
+ >>> ii.i()
+ 12
+ >>> ii >>= Int(1)
+ >>> ii.i()
+ 6
+ >>> ii &= Int(5)
+ >>> ii.i()
+ 4
+ >>> ii |= Int(9)
+ >>> ii.i()
+ 13
+ >>> ii ^= Int(7)
+ >>> ii.i()
+ 10
+ >>> ii %= Int(4)
+ >>> ii.i()
+ 2
+ >>> ii **= Int(3)
+ >>> ii.i()
+ 8
+ >>> ii.j()
+ 11
+
 Test operator export to a subclass
 
     # force method table sharing


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk