diff --git a/src/Base/VectorPyImp.cpp b/src/Base/VectorPyImp.cpp index 28e5bbed59..ed131617d1 100644 --- a/src/Base/VectorPyImp.cpp +++ b/src/Base/VectorPyImp.cpp @@ -665,50 +665,102 @@ PyObject *VectorPy::getCustomAttributes(const char* /*attr*/) const int VectorPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { - return 0; + return 0; } +// TODO for v0.18: +// In generation script allow to more precisely define which slots +// of the number protocol should be supported instead of setting all. + #if PY_MAJOR_VERSION < 3 -PyObject * VectorPy::number_divide_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_divide_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + if (PyObject_TypeCheck(self, &(VectorPy::Type)) && + PyNumber_Check(other)) { + // Vector passes PyNumber_Check because it sets nb_int and nb_float + // slots of the PyNumberMethods structure. So, it must be explicitly + // filered out here. + if (PyObject_TypeCheck(other, &(VectorPy::Type))) { + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); + return 0; + } + + Base::Vector3d vec = static_cast(self) ->value(); + double div = PyFloat_AsDouble(other); + if (div == 0) { + PyErr_Format(PyExc_ZeroDivisionError, "'%s' division by zero", + Py_TYPE(self)->tp_name); + return 0; + } + + vec /= div; + return new VectorPy(vec); + } + + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for /: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } #endif -PyObject * VectorPy::number_remainder_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_remainder_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_divmod_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_divmod_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_power_handler (PyObject* /*self*/, PyObject* /*other*/, PyObject* /*arg*/) +PyObject * VectorPy::number_power_handler (PyObject* self, PyObject* other, PyObject* /*arg*/) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_negative_handler (PyObject* /*self*/) +PyObject * VectorPy::number_negative_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + if (PyObject_TypeCheck(self, &(VectorPy::Type))) { + Base::Vector3d vec = static_cast(self) ->value(); + return new VectorPy(-vec); + } + + PyErr_Format(PyExc_TypeError, "bad operand type for unary -: '%s'", + Py_TYPE(self)->tp_name); return 0; } -PyObject * VectorPy::number_positive_handler (PyObject* /*self*/) +PyObject * VectorPy::number_positive_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + if (PyObject_TypeCheck(self, &(VectorPy::Type))) { + Base::Vector3d vec = static_cast(self) ->value(); + return new VectorPy(vec); + } + + PyErr_Format(PyExc_TypeError, "bad operand type for unary +: '%s'", + Py_TYPE(self)->tp_name); return 0; } -PyObject * VectorPy::number_absolute_handler (PyObject* /*self*/) +PyObject * VectorPy::number_absolute_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + if (PyObject_TypeCheck(self, &(VectorPy::Type))) { + Base::Vector3d vec = static_cast(self) ->value(); + vec.x = fabs(vec.x); + vec.y = fabs(vec.y); + vec.z = fabs(vec.z); + return new VectorPy(vec); + } + + PyErr_Format(PyExc_TypeError, "bad operand type for abs(): '%s'", + Py_TYPE(self)->tp_name); return 0; } @@ -717,39 +769,45 @@ int VectorPy::number_nonzero_handler (PyObject* /*self*/) return 1; } -PyObject * VectorPy::number_invert_handler (PyObject* /*self*/) +PyObject * VectorPy::number_invert_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "bad operand type for unary ~: '%s'", + Py_TYPE(self)->tp_name); return 0; } -PyObject * VectorPy::number_lshift_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_lshift_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for <<: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_rshift_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_rshift_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for >>: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_and_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_and_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for &: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_xor_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_xor_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ^: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } -PyObject * VectorPy::number_or_handler (PyObject* /*self*/, PyObject* /*other*/) +PyObject * VectorPy::number_or_handler (PyObject* self, PyObject* other) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for |: '%s' and '%s'", + Py_TYPE(self)->tp_name, Py_TYPE(other)->tp_name); return 0; } @@ -760,36 +818,39 @@ int VectorPy::number_coerce_handler (PyObject ** /*self*/, PyObject ** /*other*/ } #endif -PyObject * VectorPy::number_int_handler (PyObject* /*self*/) +PyObject * VectorPy::number_int_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "int() argument must be a string or a number, not '%s'", + Py_TYPE(self)->tp_name); return 0; } #if PY_MAJOR_VERSION < 3 -PyObject * VectorPy::number_long_handler (PyObject* /*self*/) +PyObject * VectorPy::number_long_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "long() argument must be a string or a number, not '%s'", + Py_TYPE(self)->tp_name); return 0; } #endif -PyObject * VectorPy::number_float_handler (PyObject* /*self*/) +PyObject * VectorPy::number_float_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_Format(PyExc_TypeError, "float() argument must be a string or a number, not '%s'", + Py_TYPE(self)->tp_name); return 0; } #if PY_MAJOR_VERSION < 3 -PyObject * VectorPy::number_oct_handler (PyObject* /*self*/) +PyObject * VectorPy::number_oct_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_SetString(PyExc_TypeError, "oct() argument can't be converted to oct"); return 0; } -PyObject * VectorPy::number_hex_handler (PyObject* /*self*/) +PyObject * VectorPy::number_hex_handler (PyObject* self) { - PyErr_SetString(PyExc_NotImplementedError, "Not implemented"); + PyErr_SetString(PyExc_TypeError, "hex() argument can't be converted to hex"); return 0; } #endif