From 0ed5af25a7e9450003e2282734ad07453898977a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 15 Jul 2001 09:41:09 +0000 Subject: [PATCH] Tested: all compilers & python 1.5.2, all unix & python 2.1 [SVN r10623] --- build/filemgr.py | 3 + build/irix_CC.mak | 14 +- build/linux_gcc.mak | 14 +- build/mingw32.mak | 9 +- build/tru64_cxx.mak | 14 +- build/vc60.mak | 6 +- example/richcmp.cpp | 239 ++++++++++++++++++ example/test_richcmp.py | 63 +++++ include/boost/python/classes.hpp | 52 ++++ .../boost/python/detail/extension_class.hpp | 12 + include/boost/python/detail/types.hpp | 10 +- include/boost/python/operators.hpp | 14 +- src/classes.cpp | 36 +++ src/types.cpp | 75 +++++- 14 files changed, 544 insertions(+), 17 deletions(-) create mode 100755 example/richcmp.cpp create mode 100644 example/test_richcmp.py diff --git a/build/filemgr.py b/build/filemgr.py index d8310f6d..33e43519 100644 --- a/build/filemgr.py +++ b/build/filemgr.py @@ -52,6 +52,8 @@ bpl_exa + "/tst_dvect2.py", bpl_exa + "/tst_ivect1.py", bpl_exa + "/tst_ivect2.py", bpl_exa + "/test_cross_module.py", +bpl_exa + "/richcmp.cpp", +bpl_exa + "/test_richcmp.py", ) defs = ( @@ -68,6 +70,7 @@ defs = ( "noncopyable_import", "ivect", "dvect", +"richcmp", ) if (__name__ == "__main__"): diff --git a/build/irix_CC.mak b/build/irix_CC.mak index 5894ff51..18a97cc7 100644 --- a/build/irix_CC.mak +++ b/build/irix_CC.mak @@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost PYEXE=/usr/local/Python-1.5.2/bin/python PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.0/bin/python -#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#PYEXE=/usr/local/Python-2.1/bin/python +#PYINC=-I/usr/local/Python-2.1/include/python2.1 STLPORTINC=-I$(BOOST)/boost/compatibility/cpp_c_headers STDOPTS= @@ -46,7 +46,8 @@ DEPOBJ=$(OBJ) \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o + ivect.o dvect.o \ + richcmp.o .SUFFIXES: .o .cpp @@ -58,7 +59,8 @@ all: libboost_python.a \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so + ivect.so dvect.so \ + richcmp.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -105,6 +107,9 @@ ivect.so: $(OBJ) ivect.o dvect.so: $(OBJ) dvect.o $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so +richcmp.so: $(OBJ) richcmp.o + $(LD) $(LDOPTS) $(OBJ) richcmp.o -o richcmp.so + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -135,6 +140,7 @@ clean: rm -f noncopyable_import.o noncopyable_import.so rm -f ivect.o ivect.so rm -f dvect.o dvect.so + rm -f richcmp.o richcmp.so rm -f so_locations *.pyc rm -rf ii_files diff --git a/build/linux_gcc.mak b/build/linux_gcc.mak index 5971ca61..071fa062 100644 --- a/build/linux_gcc.mak +++ b/build/linux_gcc.mak @@ -21,8 +21,8 @@ PYEXE=PYTHONPATH=. /usr/bin/python PYINC=-I/usr/include/python1.5 #PYEXE=/usr/local/Python-1.5.2/bin/python #PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.0/bin/python -#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#PYEXE=/usr/local/Python-2.1/bin/python +#PYINC=-I/usr/local/Python-2.1/include/python2.1 STDOPTS=-fPIC -ftemplate-depth-21 WARNOPTS= @@ -47,7 +47,8 @@ DEPOBJ=$(OBJ) \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o + ivect.o dvect.o \ + richcmp.o .SUFFIXES: .o .cpp @@ -59,7 +60,8 @@ all: libboost_python.a \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so + ivect.so dvect.so \ + richcmp.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -106,6 +108,9 @@ ivect.so: $(OBJ) ivect.o dvect.so: $(OBJ) dvect.o $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so +richcmp.so: $(OBJ) richcmp.o + $(LD) $(LDOPTS) $(OBJ) richcmp.o -o richcmp.so + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -136,6 +141,7 @@ clean: rm -f noncopyable_import.o noncopyable_import.so rm -f ivect.o ivect.so rm -f dvect.o dvect.so + rm -f richcmp.o richcmp.so rm -f so_locations *.pyc softlinks: diff --git a/build/mingw32.mak b/build/mingw32.mak index 0a16f332..a553930a 100644 --- a/build/mingw32.mak +++ b/build/mingw32.mak @@ -62,7 +62,8 @@ all: libboost_python.a \ do_it_yourself_converters.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd + ivect.pyd dvect.pyd \ + richcmp.pyd libboost_python.a: $(OBJ) del libboost_python.a @@ -149,6 +150,12 @@ dvect.pyd: $(OBJ) dvect.o --def dvect.def \ $(OBJ) dvect.o $(PYLIB) +richcmp.pyd: $(OBJ) richcmp.o + dllwrap $(DLLWRAPOPTS) \ + --dllname richcmp.pyd \ + --def richcmp.def \ + $(OBJ) richcmp.o $(PYLIB) + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp diff --git a/build/tru64_cxx.mak b/build/tru64_cxx.mak index 21a8126e..88601e64 100644 --- a/build/tru64_cxx.mak +++ b/build/tru64_cxx.mak @@ -19,8 +19,8 @@ BOOST=$(ROOT)/boost PYEXE=/usr/local/Python-1.5.2/bin/python PYINC=-I/usr/local/Python-1.5.2/include/python1.5 -#PYEXE=/usr/local/Python-2.0/bin/python -#PYINC=-I/usr/local/Python-2.0/include/python2.0 +#PYEXE=/usr/local/Python-2.1/bin/python +#PYINC=-I/usr/local/Python-2.1/include/python2.1 #STLPORTINC=-I/usr/local/STLport-4.1b3/stlport #STLPORTINC=-I/usr/local/STLport-4.1b4/stlport #STLPORTOPTS= \ @@ -57,7 +57,8 @@ DEPOBJ=$(OBJ) \ do_it_yourself_converters.o \ pickle1.o pickle2.o pickle3.o \ noncopyable_export.o noncopyable_import.o \ - ivect.o dvect.o + ivect.o dvect.o \ + richcmp.o .SUFFIXES: .o .cpp @@ -69,7 +70,8 @@ all: libboost_python.a \ do_it_yourself_converters.so \ pickle1.so pickle2.so pickle3.so \ noncopyable_export.so noncopyable_import.so \ - ivect.so dvect.so + ivect.so dvect.so \ + richcmp.so libboost_python.a: $(OBJ) rm -f libboost_python.a @@ -120,6 +122,9 @@ ivect.so: $(OBJ) ivect.o dvect.so: $(OBJ) dvect.o $(LD) $(LDOPTS) $(OBJ) $(HIDDEN) dvect.o -o dvect.so +richcmp.so: $(OBJ) richcmp.o + $(LD) $(LDOPTS) $(OBJ) richcmp.o -o richcmp.so + .cpp.o: $(CPP) $(CPPOPTS) -c $*.cpp @@ -150,6 +155,7 @@ clean: rm -f noncopyable_import.o noncopyable_import.so rm -f ivect.o ivect.so rm -f dvect.o dvect.so + rm -f richcmp.o richcmp.so rm -f so_locations *.pyc rm -rf cxx_repository diff --git a/build/vc60.mak b/build/vc60.mak index f0016075..cdbe8c66 100644 --- a/build/vc60.mak +++ b/build/vc60.mak @@ -43,7 +43,8 @@ all: boost_python.lib \ do_it_yourself_converters.pyd \ pickle1.pyd pickle2.pyd pickle3.pyd \ noncopyable_export.pyd noncopyable_import.pyd \ - ivect.pyd dvect.pyd + ivect.pyd dvect.pyd \ + richcmp.pyd boost_python.lib: $(OBJ) $(LD) -lib /nologo /out:boost_python.lib $(OBJ) @@ -87,6 +88,9 @@ ivect.pyd: $(OBJ) ivect.obj dvect.pyd: $(OBJ) dvect.obj $(LD) $(LDOPTS) $(OBJ) dvect.obj $(PYLIB) /export:initdvect /out:"dvect.pyd" +richcmp.pyd: $(OBJ) richcmp.obj + $(LD) $(LDOPTS) $(OBJ) richcmp.obj $(PYLIB) /export:initrichcmp /out:"richcmp.pyd" + .cpp.obj: $(CPP) $(CPPOPTS) /c $*.cpp diff --git a/example/richcmp.cpp b/example/richcmp.cpp new file mode 100755 index 00000000..1fe130c3 --- /dev/null +++ b/example/richcmp.cpp @@ -0,0 +1,239 @@ +#include "dvect.h" +#include "ivect.h" +#include + +//------------------ Overload DVECT -------------------------------- + +#define DVECT_BINARY_OPERATORS( oper ) \ +namespace vects { \ + dvect operator##oper (const dvect& a, const dvect& b) { \ + if (a.size()!=b.size()){throw boost::python::argument_error();} \ + dvect result(a.size()); \ + dvect::const_iterator a_it = a.begin(); \ + dvect::const_iterator b_it = b.begin(); \ + dvect::iterator r_it = result.begin(); \ + for (int i=0; i ) +DVECT_BINARY_OPERATORS( >= ) +DVECT_BINARY_OPERATORS( < ) +DVECT_BINARY_OPERATORS( <= ) +DVECT_BINARY_OPERATORS( == ) +DVECT_BINARY_OPERATORS( != ) +#undef DVECT_BINARY_OPERATORS + +#define DVECT_SCALAR_BINARY_OPERATORS( scalar_type, oper ) \ +namespace vects { \ + dvect operator##oper (const dvect& a, const scalar_type& b) { \ + dvect result(a.size()); \ + dvect::const_iterator a_it = a.begin(); \ + dvect::iterator r_it = result.begin(); \ + for (int i=0; i ) +DVECT_SCALAR_BINARY_OPERATORS( double, >= ) +DVECT_SCALAR_BINARY_OPERATORS( double, < ) +DVECT_SCALAR_BINARY_OPERATORS( double, <= ) +DVECT_SCALAR_BINARY_OPERATORS( double, == ) +DVECT_SCALAR_BINARY_OPERATORS( double, != ) +#undef DVECT_SCALAR_BINARY_OPERATORS + +#define SCALAR_DVECT_BINARY_OPERATORS( scalar_type, oper ) \ +namespace vects { \ + dvect operator##oper (const scalar_type& a, const dvect& b) { \ + dvect result(b.size()); \ + dvect::const_iterator b_it = b.begin(); \ + dvect::iterator r_it = result.begin(); \ + for (int i=0; i ) +IVECT_BINARY_OPERATORS( >= ) +IVECT_BINARY_OPERATORS( < ) +IVECT_BINARY_OPERATORS( <= ) +IVECT_BINARY_OPERATORS( == ) +IVECT_BINARY_OPERATORS( != ) +#undef IVECT_BINARY_OPERATORS + +#define IVECT_SCALAR_BINARY_OPERATORS( scalar_type, oper ) \ +namespace vects { \ + ivect operator##oper (const ivect& a, const scalar_type& b) { \ + ivect result(a.size()); \ + ivect::const_iterator a_it = a.begin(); \ + ivect::iterator r_it = result.begin(); \ + for (int i=0; i ) +IVECT_SCALAR_BINARY_OPERATORS( int, >= ) +IVECT_SCALAR_BINARY_OPERATORS( int, < ) +IVECT_SCALAR_BINARY_OPERATORS( int, <= ) +IVECT_SCALAR_BINARY_OPERATORS( int, == ) +IVECT_SCALAR_BINARY_OPERATORS( int, != ) +#undef IVECT_SCALAR_BINARY_OPERATORS + +#define SCALAR_IVECT_BINARY_OPERATORS( scalar_type, oper ) \ +namespace vects { \ + ivect operator##oper (const scalar_type& a, const ivect& b) { \ + ivect result(b.size()); \ + ivect::const_iterator b_it = b.begin(); \ + ivect::iterator r_it = result.begin(); \ + for (int i=0; i ) +DI_BINARY_OPERATORS( >= ) +DI_BINARY_OPERATORS( < ) +DI_BINARY_OPERATORS( <= ) +DI_BINARY_OPERATORS( == ) +DI_BINARY_OPERATORS( != ) +#undef DI_BINARY_OPERATORS + +#define ID_BINARY_OPERATORS( oper ) \ +namespace vects { \ + dvect operator##oper (const ivect& a, const dvect& b) { \ + if (a.size()!=b.size()){throw boost::python::argument_error();} \ + dvect result(a.size()); \ + ivect::const_iterator a_it = a.begin(); \ + dvect::const_iterator b_it = b.begin(); \ + dvect::iterator r_it = result.begin(); \ + for (int i=0; i ) +ID_BINARY_OPERATORS( >= ) +ID_BINARY_OPERATORS( < ) +ID_BINARY_OPERATORS( <= ) +ID_BINARY_OPERATORS( == ) +ID_BINARY_OPERATORS( != ) +#undef ID_BINARY_OPERATORS + +//-------------------- Module --------------------------------------- +#define all_operators (boost::python::op_mul | boost::python::op_add |\ + boost::python::op_div | boost::python::op_sub ) + +#define comp_operators (boost::python::op_gt | boost::python::op_ge |\ + boost::python::op_lt | boost::python::op_le |\ + boost::python::op_eq | boost::python::op_ne) + +BOOST_PYTHON_MODULE_INIT(richcmp) +{ + try + { + boost::python::module_builder richcmp_module("richcmp"); + + boost::python::class_builder + dvect_class(richcmp_module, "dvect"); + boost::python::class_builder + ivect_class(richcmp_module, "ivect"); + + dvect_class.def(boost::python::constructor()); + dvect_class.def(&vects::dvect::as_tuple,"as_tuple"); + + dvect_class.def(boost::python::operators()); + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + dvect_class.def(boost::python::operators(), + boost::python::left_operand() ); + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + + dvect_class.def(boost::python::operators()); + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + // left_operand not needed since Python uses reflection + dvect_class.def(boost::python::operators(), + boost::python::right_operand() ); + + ivect_class.def(boost::python::constructor()); + ivect_class.def(&vects::ivect::as_tuple,"as_tuple"); + + ivect_class.def(boost::python::operators()); + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + ivect_class.def(boost::python::operators(), + boost::python::left_operand() ); + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + + ivect_class.def(boost::python::operators()); + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + // left_operand not needed since Python uses reflection + ivect_class.def(boost::python::operators(), + boost::python::right_operand() ); + } + catch(...){boost::python::handle_exception();} +} diff --git a/example/test_richcmp.py b/example/test_richcmp.py new file mode 100644 index 00000000..afea2a76 --- /dev/null +++ b/example/test_richcmp.py @@ -0,0 +1,63 @@ +import richcmp,sys +global dv,dv2 +dv = richcmp.ivect((1,2,3,4,5)) +print dv.as_tuple() +dv2 = richcmp.dvect((2,-2,3,8,-5)) +print dv2.as_tuple() + +print (dv+dv2).as_tuple() +print (dv+3).as_tuple() +print (3+dv).as_tuple() + +def python_2_1(): + print "\nvect vs. vect Comparisons:" + print (dv < dv2).as_tuple() + print (dv <= dv2).as_tuple() + print (dv == dv2).as_tuple() + print (dv != dv2).as_tuple() + print (dv > dv2).as_tuple() + print (dv >= dv2).as_tuple() + + print "\nvect vs. scalar Comparisons:" + print (dv < 3).as_tuple() + print (dv <= 3).as_tuple() + print (dv == 3).as_tuple() + print (dv != 3).as_tuple() + print (dv > 3).as_tuple() + print (dv >= 3).as_tuple() + + print "\nscalar vs. vect Comparisons:" + print (3 < dv).as_tuple() + print (3 <= dv).as_tuple() + print (3 == dv).as_tuple() + print (3 != dv).as_tuple() + print (3 > dv).as_tuple() + print (3 >= dv).as_tuple() + +def python_pre_2_1(): + print "\nvect vs. vect Comparisons:" + print (dv.__lt__(dv2)).as_tuple() + print (dv.__le__(dv2)).as_tuple() + print (dv.__eq__(dv2)).as_tuple() + print (dv.__ne__(dv2)).as_tuple() + print (dv.__gt__(dv2)).as_tuple() + print (dv.__ge__(dv2)).as_tuple() + + print "\nvect vs. scalar Comparisons:" + print (dv.__lt__(3)).as_tuple() + print (dv.__le__(3)).as_tuple() + print (dv.__eq__(3)).as_tuple() + print (dv.__ne__(3)).as_tuple() + print (dv.__gt__(3)).as_tuple() + print (dv.__ge__(3)).as_tuple() + + print "\nscalar vs. vect Comparisons:" + +if __name__=='__main__': + try: + if sys.version_info[0]>=2 and sys.version_info[1]>=1: + python_2_1() + else: + python_pre_2_1() + except: + python_pre_2_1() diff --git a/include/boost/python/classes.hpp b/include/boost/python/classes.hpp index d38fbba5..2d69e81e 100644 --- a/include/boost/python/classes.hpp +++ b/include/boost/python/classes.hpp @@ -70,6 +70,14 @@ class instance PyObject* oct(); PyObject* hex(); + // Rich comparisons + PyObject* lt(PyObject* other); + PyObject* le(PyObject* other); + PyObject* eq(PyObject* other); + PyObject* ne(PyObject* other); + PyObject* gt(PyObject* other); + PyObject* ge(PyObject* other); + private: // noncopyable, without the size bloat instance(const instance&); void operator=(const instance&); @@ -169,6 +177,14 @@ class class_t PyObject* instance_number_float(PyObject*) const; PyObject* instance_number_oct(PyObject*) const; PyObject* instance_number_hex(PyObject*) const; + + private: // Implement rich comparisons + PyObject* instance_lt(PyObject*, PyObject*) const; + PyObject* instance_le(PyObject*, PyObject*) const; + PyObject* instance_eq(PyObject*, PyObject*) const; + PyObject* instance_ne(PyObject*, PyObject*) const; + PyObject* instance_gt(PyObject*, PyObject*) const; + PyObject* instance_ge(PyObject*, PyObject*) const; private: // Miscellaneous "special" methods PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const; @@ -477,6 +493,42 @@ PyObject* class_t::instance_number_hex(PyObject* obj) const return downcast(obj)->hex(); } +template +PyObject* class_t::instance_lt(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->lt(other); +} + +template +PyObject* class_t::instance_le(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->le(other); +} + +template +PyObject* class_t::instance_eq(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->eq(other); +} + +template +PyObject* class_t::instance_ne(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->ne(other); +} + +template +PyObject* class_t::instance_gt(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->gt(other); +} + +template +PyObject* class_t::instance_ge(PyObject* obj, PyObject* other) const +{ + return downcast(obj)->ge(other); +} + namespace detail { inline dictionary& class_base::dict() { diff --git a/include/boost/python/detail/extension_class.hpp b/include/boost/python/detail/extension_class.hpp index 5c8e720a..d871ad6e 100644 --- a/include/boost/python/detail/extension_class.hpp +++ b/include/boost/python/detail/extension_class.hpp @@ -616,6 +616,12 @@ class extension_class choose_op<(which & op_and)>::template args::add(this); choose_op<(which & op_xor)>::template args::add(this); choose_op<(which & op_or)>::template args::add(this); + choose_op<(which & op_gt)>::template args::add(this); + choose_op<(which & op_ge)>::template args::add(this); + choose_op<(which & op_lt)>::template args::add(this); + choose_op<(which & op_le)>::template args::add(this); + choose_op<(which & op_eq)>::template args::add(this); + choose_op<(which & op_ne)>::template args::add(this); choose_unary_op<(which & op_neg)>::template args::add(this); choose_unary_op<(which & op_pos)>::template args::add(this); choose_unary_op<(which & op_abs)>::template args::add(this); @@ -645,6 +651,12 @@ class extension_class choose_op<(which & op_xor)>::template args::add(this); choose_op<(which & op_or)>::template args::add(this); choose_op<(which & op_cmp)>::template args::add(this); + choose_op<(which & op_gt)>::template args::add(this); + choose_op<(which & op_ge)>::template args::add(this); + choose_op<(which & op_lt)>::template args::add(this); + choose_op<(which & op_le)>::template args::add(this); + choose_op<(which & op_eq)>::template args::add(this); + choose_op<(which & op_ne)>::template args::add(this); } template diff --git a/include/boost/python/detail/types.hpp b/include/boost/python/detail/types.hpp index 5f0c8f97..2d0d0f6b 100644 --- a/include/boost/python/detail/types.hpp +++ b/include/boost/python/detail/types.hpp @@ -45,7 +45,7 @@ class type_object_base : public python_type public: enum capability { - hash, call, str, getattr, setattr, compare, repr, + hash, call, str, getattr, setattr, compare, repr, richcompare, mapping_length, mapping_subscript, mapping_ass_subscript, @@ -115,6 +115,14 @@ class type_object_base : public python_type virtual PyObject* instance_number_float(PyObject*) const; virtual PyObject* instance_number_oct(PyObject*) const; virtual PyObject* instance_number_hex(PyObject*) const; + + public: // Callbacks for rich comparisons + virtual PyObject* instance_lt(PyObject*, PyObject*) const; + virtual PyObject* instance_le(PyObject*, PyObject*) const; + virtual PyObject* instance_eq(PyObject*, PyObject*) const; + virtual PyObject* instance_ne(PyObject*, PyObject*) const; + virtual PyObject* instance_gt(PyObject*, PyObject*) const; + virtual PyObject* instance_ge(PyObject*, PyObject*) const; }; template diff --git a/include/boost/python/operators.hpp b/include/boost/python/operators.hpp index da88ec6c..52e52eee 100644 --- a/include/boost/python/operators.hpp +++ b/include/boost/python/operators.hpp @@ -65,7 +65,13 @@ enum operator_id op_long = 0x20000, op_float = 0x40000, op_str = 0x80000, - op_cmp = 0x100000 + op_cmp = 0x100000, + op_gt = 0x200000, + op_ge = 0x400000, + op_lt = 0x800000, + op_le = 0x1000000, + op_eq = 0x2000000, + op_ne = 0x4000000 }; // Wrap the operators given by "which". Usage: @@ -301,6 +307,12 @@ namespace detail PY_DEFINE_BINARY_OPERATORS(and, &); PY_DEFINE_BINARY_OPERATORS(xor, ^); PY_DEFINE_BINARY_OPERATORS(or, |); + PY_DEFINE_BINARY_OPERATORS(gt, >); + PY_DEFINE_BINARY_OPERATORS(ge, >=); + PY_DEFINE_BINARY_OPERATORS(lt, <); + PY_DEFINE_BINARY_OPERATORS(le, <=); + PY_DEFINE_BINARY_OPERATORS(eq, ==); + PY_DEFINE_BINARY_OPERATORS(ne, !=); PY_DEFINE_UNARY_OPERATORS(neg, -); PY_DEFINE_UNARY_OPERATORS(pos, +); diff --git a/src/classes.cpp b/src/classes.cpp index 8755bb34..a44c3c0a 100644 --- a/src/classes.cpp +++ b/src/classes.cpp @@ -736,6 +736,36 @@ PyObject* instance::hex() return callback::call_method(this, "__hex__"); } +PyObject* instance::lt(PyObject* other) +{ + return callback::call_method(this, "__lt__", other); +} + +PyObject* instance::le(PyObject* other) +{ + return callback::call_method(this, "__le__", other); +} + +PyObject* instance::eq(PyObject* other) +{ + return callback::call_method(this, "__eq__", other); +} + +PyObject* instance::ne(PyObject* other) +{ + return callback::call_method(this, "__ne__", other); +} + +PyObject* instance::gt(PyObject* other) +{ + return callback::call_method(this, "__gt__", other); +} + +PyObject* instance::ge(PyObject* other) +{ + return callback::call_method(this, "__ge__", other); +} + namespace { struct named_capability { @@ -747,6 +777,12 @@ namespace { { { "__hash__", detail::type_object_base::hash }, { "__cmp__", detail::type_object_base::compare }, + { "__gt__", detail::type_object_base::richcompare }, + { "__ge__", detail::type_object_base::richcompare }, + { "__lt__", detail::type_object_base::richcompare }, + { "__le__", detail::type_object_base::richcompare }, + { "__eq__", detail::type_object_base::richcompare }, + { "__ne__", detail::type_object_base::richcompare }, { "__repr__", detail::type_object_base::repr }, { "__str__", detail::type_object_base::str }, { "__call__", detail::type_object_base::call }, diff --git a/src/types.cpp b/src/types.cpp index 7ba5840b..88c37b89 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -159,6 +159,28 @@ static PyObject* do_instance_repr(PyObject* obj) return call(obj, &type_object_base::instance_repr); } +static PyObject* do_instance_richcompare(PyObject* obj, PyObject* other, int d) +{ +#if PYTHON_API_VERSION >= 1010 + switch(d) + { + case Py_LT: + return call(obj, &type_object_base::instance_lt, other); + case Py_LE: + return call(obj, &type_object_base::instance_le, other); + case Py_EQ: + return call(obj, &type_object_base::instance_eq, other); + case Py_NE: + return call(obj, &type_object_base::instance_ne, other); + case Py_GT: + return call(obj, &type_object_base::instance_gt, other); + case Py_GE: + return call(obj, &type_object_base::instance_ge, other); + } +#endif + return 0; +} + static int do_instance_compare(PyObject* obj, PyObject* other) { return call(obj, &type_object_base::instance_compare, other); @@ -406,7 +428,7 @@ namespace bool add_capability_general(type_object_base::capability capability, PyTypeObject* dest) { assert(dest != 0); - + switch(capability) { ENABLE_GENERAL_CAPABILITY(hash); @@ -435,6 +457,25 @@ void create_method_table_if_null(T*& table) } } +#define ENABLE_RICHCOMPARE_CAPABILITY \ + dest->tp_richcompare = &do_instance_richcompare; \ + dest->tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE; \ + return true + +bool add_capability_richcompare(type_object_base::capability capability, PyTypeObject* dest) +{ + assert(dest != 0); + if (capability == type_object_base::richcompare) { +#if PYTHON_API_VERSION >= 1010 + ENABLE_RICHCOMPARE_CAPABILITY; +#else + return true; +#endif + } + + return false; +} + #define ENABLE_MAPPING_CAPABILITY(field) \ case type_object_base::mapping_##field: \ create_method_table_if_null(dest); \ @@ -548,6 +589,8 @@ namespace detail { { if(add_capability_general(capability, dest_)) return; + if(add_capability_richcompare(capability, dest_)) + return; if(add_capability_mapping(capability, dest_->tp_as_mapping)) return; if(add_capability_sequence(capability, dest_->tp_as_sequence)) @@ -975,6 +1018,36 @@ PyObject* type_object_base::instance_number_hex(PyObject*) const return unimplemented("instance_number_hex"); } +PyObject* type_object_base::instance_lt(PyObject*, PyObject*) const +{ + return unimplemented("instance_lt"); +} + +PyObject* type_object_base::instance_le(PyObject*, PyObject*) const +{ + return unimplemented("instance_le"); +} + +PyObject* type_object_base::instance_eq(PyObject*, PyObject*) const +{ + return unimplemented("instance_eq"); +} + +PyObject* type_object_base::instance_ne(PyObject*, PyObject*) const +{ + return unimplemented("instance_ne"); +} + +PyObject* type_object_base::instance_gt(PyObject*, PyObject*) const +{ + return unimplemented("instance_gt"); +} + +PyObject* type_object_base::instance_ge(PyObject*, PyObject*) const +{ + return unimplemented("instance_ge"); +} + }} // namespace boost::python #ifdef TYPE_OBJECT_BASE_STANDALONE_TEST