Merge branch 'ejulien-python_operator_overload_test_suite'

* ejulien-python_operator_overload_test_suite:
  Add __str__ to operator_overload testcase for python builtin
  Python operator_overload runtime testcase cleanup
  Work around a limitation of the Python binding generator related to the += family of operators.
  Fix Python 3 division member operator when -builtin is not used.
  Fix class member division operator.
  Remove the PY3BUILTIN switch as its behavior can be achieved with the existing SWIG_FEATURES=-builtin switch.
  Implement the operator overload test suite for Python.

Conflicts:
	Examples/test-suite/operator_overload.i
This commit is contained in:
William S Fulton 2016-05-05 23:01:35 +01:00
commit 5e6ab1d61d
4 changed files with 98 additions and 10 deletions

View file

@ -73,6 +73,10 @@ see bottom for a set of possible tests
%rename(OrOperator) operator ||;
#endif
#if defined(SWIGPYTHON)
%feature("python:slot", "tp_str", functype="reprfunc") Op::__str__;
#endif
#ifdef SWIGD
// Due to the way operator overloading is implemented in D1 and D2, the prefix
// increment/decrement operators (D1) resp. the postfix ones (D2) are ignored.
@ -109,11 +113,11 @@ public:
return *this;
}
// +=,-=... are member fns
void operator+=(const Op& o){ i+=o.i;}
void operator-=(const Op& o){ i-=o.i;}
void operator*=(const Op& o){ i*=o.i;}
void operator/=(const Op& o){ i/=o.i;}
void operator%=(const Op& o){ i%=o.i;}
Op &operator+=(const Op& o){ i+=o.i; return *this; }
Op &operator-=(const Op& o){ i-=o.i; return *this; }
Op &operator*=(const Op& o){ i*=o.i; return *this; }
Op &operator/=(const Op& o){ i/=o.i; return *this; }
Op &operator%=(const Op& o){ i%=o.i; return *this; }
// the +,-,*,... are friends
// (just to make life harder)
friend Op operator+(const Op& a,const Op& b){return Op(a.i+b.i);}

View file

@ -0,0 +1,77 @@
from operator_overload import *
# first check all the operators are implemented correctly from pure C++ code
Op_sanity_check()
pop = Op(6)/Op(3)
# test routine:
a=Op()
b=Op(5)
c=Op(b) # copy construct
d=Op(2)
dd=d # assignment operator
# test equality
if not a!=b:
raise RuntimeError("a!=b")
if not b==c:
raise RuntimeError("b==c")
if not a!=d:
raise RuntimeError("a!=d")
if not d==dd:
raise RuntimeError("d==dd")
# test <
if not a<b:
raise RuntimeError("a<b")
if not a<=b:
raise RuntimeError("a<=b")
if not b<=c:
raise RuntimeError("b<=c")
if not b>=c:
raise RuntimeError("b>=c")
if not b>d:
raise RuntimeError("b>d")
if not b>=d:
raise RuntimeError("b>=d")
# test +=
e=Op(3)
e+=d
if not e==b:
raise RuntimeError("e==b (%s==%s)" % (e.i, b.i))
e-=c
if not e==a:
raise RuntimeError("e==a")
e=Op(1)
e*=b
if not e==c:
raise RuntimeError("e==c")
e/=d
if not e==d:
raise RuntimeError("e==d")
e%=c;
if not e==d:
raise RuntimeError("e==d")
# test +
f=Op(1)
g=Op(1)
if not f+g==Op(2):
raise RuntimeError("f+g==Op(2)")
if not f-g==Op(0):
raise RuntimeError("f-g==Op(0)")
if not f*g==Op(1):
raise RuntimeError("f*g==Op(1)")
if not f/g==Op(1):
raise RuntimeError("f/g==Op(1)")
if not f%g==Op(0):
raise RuntimeError("f%g==Op(0)")
# test unary operators
if not -a==a:
raise RuntimeError("-a==a")
if not -b==Op(-5):
raise RuntimeError("-b==Op(-5)")

View file

@ -103,7 +103,11 @@
%pybinoperator(__neg__, *::operator-(), unaryfunc, nb_negative);
%pybinoperator(__neg__, *::operator-() const, unaryfunc, nb_negative);
%pybinoperator(__mul__, *::operator*, binaryfunc, nb_multiply);
%pybinoperator(__div__, *::operator/, binaryfunc, nb_div);
#if defined(SWIGPYTHON_PY3)
%pybinoperator(__truediv__, *::operator/, binaryfunc, nb_divide);
#else
%pybinoperator(__div__, *::operator/, binaryfunc, nb_divide);
#endif
%pybinoperator(__mod__, *::operator%, binaryfunc, nb_remainder);
%pybinoperator(__lshift__, *::operator<<, binaryfunc, nb_lshift);
%pybinoperator(__rshift__, *::operator>>, binaryfunc, nb_rshift);
@ -117,8 +121,6 @@
%pycompare(__eq__, *::operator==, Py_EQ);
%pycompare(__ne__, *::operator!=, Py_NE);
%feature("python:slot", "nb_truediv", functype="binaryfunc") *::operator/;
/* Special cases */
%rename(__invert__) *::operator~;
%feature("python:slot", "nb_invert", functype="unaryfunc") *::operator~;
@ -200,7 +202,11 @@ __bool__ = __nonzero__
%pyinplaceoper(__iadd__ , *::operator +=, binaryfunc, nb_inplace_add);
%pyinplaceoper(__isub__ , *::operator -=, binaryfunc, nb_inplace_subtract);
%pyinplaceoper(__imul__ , *::operator *=, binaryfunc, nb_inplace_multiply);
#if defined(SWIGPYTHON_PY3)
%pyinplaceoper(__itruediv__ , *::operator /=, binaryfunc, nb_inplace_divide);
#else
%pyinplaceoper(__idiv__ , *::operator /=, binaryfunc, nb_inplace_divide);
#endif
%pyinplaceoper(__imod__ , *::operator %=, binaryfunc, nb_inplace_remainder);
%pyinplaceoper(__iand__ , *::operator &=, binaryfunc, nb_inplace_and);
%pyinplaceoper(__ior__ , *::operator |=, binaryfunc, nb_inplace_or);

View file

@ -517,6 +517,7 @@ public:
fputs(usage3, stdout);
} else if (strcmp(argv[i], "-py3") == 0) {
py3 = 1;
Preprocessor_define("SWIGPYTHON_PY3", 0);
Swig_mark_arg(i);
} else if (strcmp(argv[i], "-builtin") == 0) {
builtin = 1;
@ -4153,9 +4154,9 @@ public:
printSlot(f, getSlot(n, "feature:python:nb_inplace_xor"), "nb_inplace_xor", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_inplace_or"), "nb_inplace_or", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_floor_divide"), "nb_floor_divide", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_true_divide"), "nb_true_divide", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_divide"), "nb_true_divide", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_inplace_floor_divide"), "nb_inplace_floor_divide", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_inplace_true_divide"), "nb_inplace_true_divide", "binaryfunc");
printSlot(f, getSlot(n, "feature:python:nb_inplace_divide"), "nb_inplace_true_divide", "binaryfunc");
Printv(f, "#if PY_VERSION_HEX >= 0x02050000\n", NIL);
printSlot(f, getSlot(n, "feature:python:nb_index"), "nb_index", "unaryfunc");
Printv(f, "#endif\n", NIL);