diff --git a/caller.h b/caller.h index 00cf65b7..43da3d91 100644 --- a/caller.h +++ b/caller.h @@ -6,7 +6,7 @@ // The author gratefully acknowleges the support of Dragon Systems, Inc., in // producing this work. // -// This file generated for 10-argument member functions and 11-argument free +// This file generated for 5-argument member functions and 6-argument free // functions by gen_caller.python #ifndef CALLER_DWA05090_H_ @@ -17,6 +17,7 @@ # include # include "signatures.h" # include "none.h" +# include "objects.h" namespace python { @@ -103,126 +104,6 @@ struct caller from_python(a5, type()))); } - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()))); - } - template static PyObject* call(R (T::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) { @@ -303,126 +184,6 @@ struct caller from_python(a5, type()))); } - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()))); - } - - template - static PyObject* call(R (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - return to_python((target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()))); - } - // Free functions static PyObject* call(R (*f)(), PyObject* args, PyObject* /* keywords */ ) { if (!PyArg_ParseTuple(args, const_cast(""))) @@ -508,126 +269,6 @@ struct caller from_python(a6, type()))); } - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()))); - } - - template - static PyObject* call(R (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - PyObject* a11; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11)) - return 0; - return to_python(f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()), - from_python(a11, type()))); - } - }; template <> @@ -718,131 +359,6 @@ struct caller return detail::none(); } - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type())); - return detail::none(); - } - template static PyObject* call(void (T::*pmf)() const, PyObject* args, PyObject* /* keywords */ ) { @@ -929,131 +445,6 @@ struct caller return detail::none(); } - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type())); - return detail::none(); - } - - template - static PyObject* call(void (T::*pmf)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) const, PyObject* args, PyObject* /* keywords */ ) { - PyObject* self; - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &self, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - T& target = from_python(self, type()); - (target.*pmf)(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type())); - return detail::none(); - } - // Free functions static PyObject* call(void (*f)(), PyObject* args, PyObject* /* keywords */ ) { @@ -1147,133 +538,270 @@ struct caller return detail::none(); } - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type())); - return detail::none(); - } - - template - static PyObject* call(void (*f)(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11), PyObject* args, PyObject* /* keywords */ ) { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - PyObject* a11; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10, &a11)) - return 0; - f(from_python(a1, type()), - from_python(a2, type()), - from_python(a3, type()), - from_python(a4, type()), - from_python(a5, type()), - from_python(a6, type()), - from_python(a7, type()), - from_python(a8, type()), - from_python(a9, type()), - from_python(a10, type()), - from_python(a11, type())); - return detail::none(); - } - }; +namespace detail +{ + +// create signature tuples +inline +PyObject* function_signature() { + tuple result(0); + + return result.reference().release(); } -#endif +template +PyObject* function_signature(type) { + static const bool is_plain_A1 = BOOST_PYTHON_IS_PLAIN(A1); + tuple result(1); + result.set_item(0, python_type_name_selector::get(type())); + + return result.reference().release(); +} + +template +PyObject* function_signature(type, type) { + static const bool is_plain_A1 = BOOST_PYTHON_IS_PLAIN(A1); + static const bool is_plain_A2 = BOOST_PYTHON_IS_PLAIN(A2); + tuple result(2); + result.set_item(0, python_type_name_selector::get(type())); + result.set_item(1, python_type_name_selector::get(type())); + + return result.reference().release(); +} + +template +PyObject* function_signature(type, type, type) { + static const bool is_plain_A1 = BOOST_PYTHON_IS_PLAIN(A1); + static const bool is_plain_A2 = BOOST_PYTHON_IS_PLAIN(A2); + static const bool is_plain_A3 = BOOST_PYTHON_IS_PLAIN(A3); + tuple result(3); + result.set_item(0, python_type_name_selector::get(type())); + result.set_item(1, python_type_name_selector::get(type())); + result.set_item(2, python_type_name_selector::get(type())); + + return result.reference().release(); +} + +template +PyObject* function_signature(type, type, type, type) { + static const bool is_plain_A1 = BOOST_PYTHON_IS_PLAIN(A1); + static const bool is_plain_A2 = BOOST_PYTHON_IS_PLAIN(A2); + static const bool is_plain_A3 = BOOST_PYTHON_IS_PLAIN(A3); + static const bool is_plain_A4 = BOOST_PYTHON_IS_PLAIN(A4); + tuple result(4); + result.set_item(0, python_type_name_selector::get(type())); + result.set_item(1, python_type_name_selector::get(type())); + result.set_item(2, python_type_name_selector::get(type())); + result.set_item(3, python_type_name_selector::get(type())); + + return result.reference().release(); +} + +template +PyObject* function_signature(type, type, type, type, type) { + static const bool is_plain_A1 = BOOST_PYTHON_IS_PLAIN(A1); + static const bool is_plain_A2 = BOOST_PYTHON_IS_PLAIN(A2); + static const bool is_plain_A3 = BOOST_PYTHON_IS_PLAIN(A3); + static const bool is_plain_A4 = BOOST_PYTHON_IS_PLAIN(A4); + static const bool is_plain_A5 = BOOST_PYTHON_IS_PLAIN(A5); + tuple result(5); + result.set_item(0, python_type_name_selector::get(type())); + result.set_item(1, python_type_name_selector::get(type())); + result.set_item(2, python_type_name_selector::get(type())); + result.set_item(3, python_type_name_selector::get(type())); + result.set_item(4, python_type_name_selector::get(type())); + + return result.reference().release(); +} + +template +PyObject* function_signature(type, type, type, type, type, type) { + static const bool is_plain_A1 = BOOST_PYTHON_IS_PLAIN(A1); + static const bool is_plain_A2 = BOOST_PYTHON_IS_PLAIN(A2); + static const bool is_plain_A3 = BOOST_PYTHON_IS_PLAIN(A3); + static const bool is_plain_A4 = BOOST_PYTHON_IS_PLAIN(A4); + static const bool is_plain_A5 = BOOST_PYTHON_IS_PLAIN(A5); + static const bool is_plain_A6 = BOOST_PYTHON_IS_PLAIN(A6); + tuple result(6); + result.set_item(0, python_type_name_selector::get(type())); + result.set_item(1, python_type_name_selector::get(type())); + result.set_item(2, python_type_name_selector::get(type())); + result.set_item(3, python_type_name_selector::get(type())); + result.set_item(4, python_type_name_selector::get(type())); + result.set_item(5, python_type_name_selector::get(type())); + + return result.reference().release(); +} + + +// member functions +template +inline PyObject* function_signature(R (T::*pmf)()) { + return function_signature( + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1)) { + return function_signature( + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2)) { + return function_signature( + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2, A3)) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2, A3, A4)) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2, A3, A4, A5)) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); +} + + +// const member functions +template +inline PyObject* function_signature(R (T::*pmf)() const) { + return function_signature( + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1) const) { + return function_signature( + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2) const) { + return function_signature( + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2, A3) const) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2, A3, A4) const) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (T::*pmf)(A1, A2, A3, A4, A5) const) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); +} + + +// free functions +template +inline PyObject* function_signature(R (*f)()) { + return function_signature(); +} + +template +inline PyObject* function_signature(R (*f)(A1)) { + return function_signature( + python::type()); +} + +template +inline PyObject* function_signature(R (*f)(A1, A2)) { + return function_signature( + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (*f)(A1, A2, A3)) { + return function_signature( + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (*f)(A1, A2, A3, A4)) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (*f)(A1, A2, A3, A4, A5)) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); +} + +template +inline PyObject* function_signature(R (*f)(A1, A2, A3, A4, A5, A6)) { + return function_signature( + python::type(), + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); +} + +} // namespace detail + +} // namespace python + +#endif // CALLER_DWA05090_H_ + diff --git a/extclass.cpp b/extclass.cpp index 94d9bf68..68941c0e 100644 --- a/extclass.cpp +++ b/extclass.cpp @@ -329,9 +329,9 @@ PyObject* read_only_setattr_function::do_call(PyObject* /*args*/, PyObject* /*ke return 0; } -const char* read_only_setattr_function::description() const +PyObject* read_only_setattr_function::description() const { - return "uncallable"; + return BOOST_PYTHON_CONVERSION::to_python("uncallable"); } extension_class_base::extension_class_base(const char* name) @@ -469,6 +469,19 @@ operator_dispatcher::create(const ref& object, const ref& self) return result; } +namespace { + +void set_attribute_error(const char* oper, tuple args) +{ + PyErr_Clear(); + string message(oper); + message += argument_tuple_as_string(args); + message += " undefined."; + PyErr_SetObject(PyExc_TypeError, message.get()); +} + +} // anonymous namespace + extern "C" { @@ -498,7 +511,7 @@ int operator_dispatcher_coerce(PyObject** l, PyObject** r) #define PY_DEFINE_OPERATOR(id, symbol) \ - PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \ + PyObject* operator_dispatcher_call_##id(PyObject* left, PyObject* right) \ { \ /* unwrap the arguments from their OperatorDispatcher */ \ PyObject* self; \ @@ -506,17 +519,20 @@ int operator_dispatcher_coerce(PyObject** l, PyObject** r) int reverse = unwrap_args(left, right, self, other); \ if (reverse == unwrap_exception_code) \ return 0; \ + const char * oper = reverse \ + ? "__r" #id "__" \ + : "__" #id "__"; \ \ /* call the function */ \ PyObject* result = \ PyEval_CallMethod(self, \ - const_cast(reverse ? "__r" #id "__" : "__" #id "__"), \ + const_cast(oper), \ const_cast("(O)"), \ other); \ if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) \ { \ - PyErr_Clear(); \ - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for " #symbol); \ + tuple args(ref(self, ref::increment_count), ref(other, ref::increment_count)); \ + set_attribute_error(oper , args); \ } \ return result; \ } @@ -562,24 +578,34 @@ PyObject* operator_dispatcher_call_pow(PyObject* left, PyObject* right, PyObject if (reverse == unwrap_exception_code) return 0; - + + const char * oper = (reverse == 0) + ? "__pow__" + : (reverse == 1) + ? "__rpow__" + : "__rrpow__"; // call the function PyObject* result = PyEval_CallMethod(self, - const_cast((reverse == 0) - ? "__pow__" - : (reverse == 1) - ? "__rpow__" - : "__rrpow__"), + const_cast(oper), const_cast("(OO)"), first, second); - if (result == 0 && - (PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_TypeError) || - PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError))) - { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()"); - } + + if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) + { + if(m == Py_None) + { + tuple args(ref(self, ref::increment_count), ref(first, ref::increment_count)); + set_attribute_error(oper , args); + } + else + { + tuple args(ref(self, ref::increment_count), + ref(first, ref::increment_count), + ref(second, ref::increment_count)); + set_attribute_error(oper , args); + } + } return result; } @@ -592,16 +618,23 @@ int operator_dispatcher_call_cmp(PyObject* left, PyObject* right) if (reverse == unwrap_exception_code) return -1; + const char * oper = reverse + ? "__rcmp__" + : "__cmp__"; // call the function PyObject* result = PyEval_CallMethod(self, - const_cast(reverse ? "__rcmp__" : "__cmp__"), + const_cast(oper), const_cast("(O)"), other); + if (result == 0 && PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_AttributeError)) + { + tuple args(ref(self, ref::increment_count), ref(other, ref::increment_count)); + set_attribute_error(oper , args); + } + if (result == 0) { - PyErr_Clear(); - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for cmp() or <"); return -1; } else diff --git a/extclass.h b/extclass.h index 925f441b..bb59eb39 100644 --- a/extclass.h +++ b/extclass.h @@ -133,6 +133,39 @@ class class_registry static std::vector static_derived_class_info; }; +template +no_t* is_plain_aux(type >); + +template +string forward_python_type_name(python::type >) +{ + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); +} + +template +no_t* is_plain_aux(type >); + +template +string forward_python_type_name(python::type >) +{ + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); +} + +template +string python_type_name(type) +{ + if(class_registry::class_object() == 0) + { + return string("UnknownType"); + } + else + { + return class_registry::class_object()->complete_class_name(); + } +} + }} // namespace python::detail BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -314,7 +347,9 @@ class read_only_setattr_function : public function public: read_only_setattr_function(const char* name); PyObject* do_call(PyObject* args, PyObject* keywords) const; - const char* description() const; + PyObject* description() const; + string function_name() const + { return m_name; } private: string m_name; }; @@ -428,7 +463,7 @@ class extension_class template inline void def_raw(Fn fn, const char* name) { - this->add_method(new_raw_arguments_function(fn), name); + this->add_method(new_raw_arguments_function(fn, name), name); } // define member functions. In fact this works for free functions, too - @@ -438,7 +473,7 @@ class extension_class template inline void def(Fn fn, const char* name) { - this->add_method(new_wrapped_function(fn), name); + this->add_method(new_wrapped_function(fn, name), name); } // Define a virtual member function with a default implementation. @@ -447,7 +482,7 @@ class extension_class template inline void def(Fn fn, const char* name, DefaultFn default_fn) { - this->add_method(new_virtual_function(type(), fn, default_fn), name); + this->add_method(new_virtual_function(type(), fn, default_fn, name), name); } // Provide a function which implements x., reading from the given @@ -455,7 +490,7 @@ class extension_class template inline void def_getter(MemberType T::*pm, const char* name) { - this->add_getter_method(new getter_function(pm), name); + this->add_getter_method(new getter_function(pm, name), name); } // Provide a function which implements assignment to x., writing to @@ -463,7 +498,7 @@ class extension_class template inline void def_setter(MemberType T::*pm, const char* name) { - this->add_setter_method(new setter_function(pm), name); + this->add_setter_method(new setter_function(pm, name), name); } // Expose the given member (pm) of the T obj as a read-only attribute diff --git a/functions.cpp b/functions.cpp index 0cd24306..24e99502 100644 --- a/functions.cpp +++ b/functions.cpp @@ -11,13 +11,35 @@ #include "singleton.h" #include "objects.h" #include "errors.h" +#include "extclass.h" namespace python { namespace detail { -struct function::type_object : - singleton > > +string argument_tuple_as_string(tuple arguments) { - type_object() : singleton_base(&PyType_Type) {} + string result("("); + for (std::size_t i = 0; i < arguments.size(); ++i) + { + if (i != 0) + result += ", "; + if(arguments[i]->ob_type->ob_type == extension_meta_class()) + { + result += downcast(arguments[i]->ob_type).get()->complete_class_name(); + } + else + { + result += arguments[i]->ob_type->tp_name; + } + } + result += ")"; + return result; +} + +struct function::type_object : + singleton > > > +{ + type_object() : singleton_base(&PyType_Type) + {} }; @@ -56,6 +78,38 @@ function::function() { } +PyObject* function::getattr(const char * name) const +{ + if(strcmp(name, "__signatures__") == 0) + { + list signatures; + for (const function* f = this; f != 0; f = f->m_overloads.get()) + { + signatures.push_back(f->description()); + } + return signatures.reference().release(); + + } + else if(strcmp(name, "__name__") == 0) + { + return function_name().reference().release(); + + } + else if(strcmp(name, "__dict__") == 0) + { + dictionary items; + items.set_item(string("__name__"), detail::none()); + items.set_item(string("__signatures__"), detail::none()); + return items.reference().release(); + + } + else + { + PyErr_SetString(PyExc_AttributeError, name); + return 0; + } +} + PyObject* function::call(PyObject* args, PyObject* keywords) const { for (const function* f = this; f != 0; f = f->m_overloads.get()) @@ -69,6 +123,26 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const } catch(const argument_error&) { + if(m_overloads.get() == 0 && rephrase_argument_error() && + PyErr_GivenExceptionMatches(PyErr_Occurred(), PyExc_TypeError)) + { + PyErr_Clear(); + string message(""); + string name(this->function_name()); + if(name.size() != 0) + { + message += "'"; + message += name; + message += "' "; + } + message += "expected argument(s) "; + message += description_as_string(); + message += ",\nbut got "; + tuple arguments(ref(args, ref::increment_count)); + message += argument_types_as_string(arguments); + message += " instead."; + PyErr_SetObject(PyExc_TypeError, message.get()); + } } } @@ -76,27 +150,52 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const return 0; PyErr_Clear(); - string message("No overloaded functions match ("); - tuple arguments(ref(args, ref::increment_count)); - for (std::size_t i = 0; i < arguments.size(); ++i) + string message("No variant of overloaded function"); + string name(this->function_name()); + + if(name.size() != 0) { - if (i != 0) - message += ", "; - message += arguments[i]->ob_type->tp_name; + message += " '"; + message += name; + message += "'"; } + message += " matches argument(s):\n"; + + tuple arguments(ref(args, ref::increment_count)); + message += argument_types_as_string(arguments); - message += "). Candidates are:\n"; + message += "\nCandidates are:\n"; for (const function* f1 = this; f1 != 0; f1 = f1->m_overloads.get()) { if (f1 != this) message += "\n"; - message += f1->description(); + message += f1->description_as_string(); } PyErr_SetObject(PyExc_TypeError, message.get()); return 0; } +string function::description_as_string() const +{ + string result("("); + tuple arguments(ref(this->description())); + for (std::size_t i = 0; i < arguments.size(); ++i) + { + if (i != 0) + result += ", "; + result += string(arguments[i]); + } + + result += ")"; + return result; +} + +string function::argument_types_as_string(tuple arguments) const +{ + return argument_tuple_as_string(arguments); +} + bound_function* bound_function::create(const ref& target, const ref& fn) { bound_function* const result = free_list; diff --git a/functions.h b/functions.h index ec982f53..13d05550 100644 --- a/functions.h +++ b/functions.h @@ -25,6 +25,8 @@ namespace python { namespace detail { // forward declaration class extension_instance; +string argument_tuple_as_string(tuple args); + // function -- // the common base class for all overloadable function and method objects @@ -38,17 +40,36 @@ class function : public python_object virtual ~function() {} PyObject* call(PyObject* args, PyObject* keywords) const; + PyObject* getattr(const char * name) const; static void add_to_namespace(reference f, const char* name, PyObject* dict); - + + protected: + virtual PyObject* description() const = 0; private: virtual PyObject* do_call(PyObject* args, PyObject* keywords) const = 0; - virtual const char* description() const = 0; + virtual string description_as_string() const; + virtual string argument_types_as_string(tuple args) const; + virtual string function_name() const = 0; + virtual bool rephrase_argument_error() const + { return true; } private: struct type_object; private: reference m_overloads; }; +struct named_function : function +{ + named_function(const char * name) + : m_name(name) + {} + + string function_name() const + { return m_name; } + + string m_name; +}; + // wrapped_function_pointer<> -- // A single function or member function pointer wrapped and presented to // Python as a callable object. @@ -57,19 +78,19 @@ class function : public python_object // R - the return type of the function pointer // F - the complete type of the wrapped function pointer template -struct wrapped_function_pointer : function +struct wrapped_function_pointer : named_function { typedef F ptr_fun; // pointer-to--function or pointer-to-member-function - wrapped_function_pointer(ptr_fun pf) - : m_pf(pf) {} + wrapped_function_pointer(ptr_fun pf, const char * name) + : named_function(name), m_pf(pf) {} private: PyObject* do_call(PyObject* args, PyObject* keywords) const { return caller::call(m_pf, args, keywords); } - const char* description() const - { return typeid(F).name(); } + PyObject* description() const + { return function_signature(m_pf); } private: const ptr_fun m_pf; @@ -80,15 +101,15 @@ struct wrapped_function_pointer : function // verbatim to C++ (useful for customized argument parsing and variable // argument lists) template -struct raw_arguments_function : function +struct raw_arguments_function : named_function { typedef Ret (*ptr_fun)(Args, Keywords); - raw_arguments_function(ptr_fun pf) - : m_pf(pf) {} + raw_arguments_function(ptr_fun pf, const char * name) + : named_function(name), m_pf(pf) {} private: - PyObject* do_call(PyObject* args, PyObject* keywords) const + PyObject* do_call(PyObject* args, PyObject* keywords) const { ref dict(keywords ? ref(keywords, ref::increment_count) : @@ -99,9 +120,17 @@ struct raw_arguments_function : function from_python(dict.get(), python::type()))); } - const char* description() const - { return typeid(ptr_fun).name(); } + PyObject* description() const + { + tuple result(1); + result.set_item(0, string("...")); + + return result.reference().release(); + } + virtual bool rephrase_argument_error() const + { return false; } + private: const ptr_fun m_pf; }; @@ -119,19 +148,20 @@ struct raw_arguments_function : function // parameter and calls T::f on it /non-virtually/, where V // approximates &T::f. template -class virtual_function : public function +class virtual_function : public named_function { public: - virtual_function(V virtual_function_ptr, D default_implementation) - : m_virtual_function_ptr(virtual_function_ptr), + virtual_function(V virtual_function_ptr, D default_implementation, const char * name) + : named_function(name), + m_virtual_function_ptr(virtual_function_ptr), m_default_implementation(default_implementation) {} private: PyObject* do_call(PyObject* args, PyObject* keywords) const; - const char* description() const - { return typeid(V).name(); } + PyObject* description() const + { return function_signature(m_virtual_function_ptr); } private: const V m_virtual_function_ptr; @@ -142,26 +172,26 @@ class virtual_function : public function // functionality once the return type has already been deduced. R is expected to // be type, where X is the actual return type of pmf. template -function* new_wrapped_function_aux(R, F pmf) +function* new_wrapped_function_aux(R, F pmf, const char * name) { // We can't just use "typename R::Type" below because MSVC (incorrectly) pukes. typedef typename R::type return_type; - return new wrapped_function_pointer(pmf); + return new wrapped_function_pointer(pmf, name); } // Create and return a new member function object wrapping the given // pointer-to-member function template -inline function* new_wrapped_function(F pmf) +inline function* new_wrapped_function(F pmf, const char * name) { // Deduce the return type and pass it off to the helper function above - return new_wrapped_function_aux(return_value(pmf), pmf); + return new_wrapped_function_aux(return_value(pmf), pmf, name); } template -function* new_raw_arguments_function(R (*pmf)(Args, keywords)) +function* new_raw_arguments_function(R (*pmf)(Args, keywords), const char * name) { - return new raw_arguments_function(pmf); + return new raw_arguments_function(pmf, name); } @@ -170,26 +200,26 @@ function* new_raw_arguments_function(R (*pmf)(Args, keywords)) // be type, where X is the actual return type of V. template inline function* new_virtual_function_aux( - type, R, V virtual_function_ptr, D default_implementation - ) + type, R, V virtual_function_ptr, D default_implementation, + const char * name) { // We can't just use "typename R::Type" below because MSVC (incorrectly) pukes. typedef typename R::type return_type; return new virtual_function( - virtual_function_ptr, default_implementation); + virtual_function_ptr, default_implementation, name); } // Create and return a new virtual_function object wrapping the given // virtual_function_ptr and default_implementation template inline function* new_virtual_function( - type, V virtual_function_ptr, D default_implementation - ) + type, V virtual_function_ptr, D default_implementation, + const char * name) { // Deduce the return type and pass it off to the helper function above return new_virtual_function_aux( type(), return_value(virtual_function_ptr), - virtual_function_ptr, default_implementation); + virtual_function_ptr, default_implementation, name); } // A function with a bundled "bound target" object. This is what is produced by @@ -220,37 +250,37 @@ class bound_function : public python_object // Special functions designed to access data members of a wrapped C++ object. template -class getter_function : public function +class getter_function : public named_function { public: typedef MemberType ClassType::* pointer_to_member; - getter_function(pointer_to_member pm) - : m_pm(pm) {} + getter_function(pointer_to_member pm, const char * name) + : named_function(name), m_pm(pm) {} private: PyObject* do_call(PyObject* args, PyObject* keywords) const; - const char* description() const - { return typeid(MemberType (*)(const ClassType&)).name(); } + PyObject* description() const + { return function_signature((MemberType (*)(const ClassType&))0); } private: pointer_to_member m_pm; }; template -class setter_function : public function +class setter_function : public named_function { public: typedef MemberType ClassType::* pointer_to_member; - setter_function(pointer_to_member pm) - : m_pm(pm) {} + setter_function(pointer_to_member pm, const char * name) + : named_function(name), m_pm(pm) {} private: PyObject* do_call(PyObject* args, PyObject* keywords) const; - const char* description() const - { return typeid(void (*)(const ClassType&, const MemberType&)).name(); } + PyObject* description() const + { return function_signature((void (*)(const ClassType&, const MemberType&))0); } private: pointer_to_member m_pm; }; diff --git a/gen_caller.py b/gen_caller.py index f0e65d49..7aaac5cf 100644 --- a/gen_caller.py +++ b/gen_caller.py @@ -31,6 +31,7 @@ body_sections = ( # include # include "signatures.h" # include "none.h" +# include "objects.h" namespace python { @@ -56,9 +57,25 @@ struct caller ''', '''}; -} +namespace detail +{ + +// create signature tuples +inline''', +''' +// member functions +''', +''' +// const member functions +''', +''' +// free functions +''', +'''} // namespace detail -#endif +} // namespace python + +#endif // CALLER_DWA05090_H_ ''') #' @@ -87,6 +104,34 @@ free_function = '''%{ template <%(class A%n%:, %)> ''' +function_signature = '''%{template <%}%(class A%n%:, %)%{>%} +PyObject* function_signature(%(type%:, %)) { +%( static const bool is_plain_A%n = BOOST_PYTHON_IS_PLAIN(A%n); +%) tuple result(%x); +%( result.set_item(%N, python_type_name_selector::get(type())); +%) + return result.reference().release(); +} + +''' + +member_function_signature = '''template +inline PyObject* function_signature(R (T::*pmf)(%(A%n%:, %))%1) { + return function_signature( + python::type()%(, + python::type()%)); +} + +''' + +free_function_signature = '''template +inline PyObject* function_signature(R (*f)(%(A%n%:, %))) { + return function_signature(%( + python::type()%:,%)); +} + +''' + def gen_caller(member_function_args, free_function_args = None): if free_function_args is None: free_function_args = member_function_args + 1 @@ -118,6 +163,16 @@ def gen_caller(member_function_args, free_function_args = None): + gen_functions(free_function, free_function_args, 'void', '', return_none) + body_sections[6] + + # create lists describing the function signatures + + gen_functions(function_signature, free_function_args) + + body_sections[7] + + gen_functions(member_function_signature, member_function_args, '') + + body_sections[8] + + gen_functions(member_function_signature, member_function_args, ' const') + + body_sections[9] + + gen_functions(free_function_signature, free_function_args) + + body_sections[10] ) if __name__ == '__main__': diff --git a/gen_extclass.py b/gen_extclass.py index 81ea4942..380d7d91 100644 --- a/gen_extclass.py +++ b/gen_extclass.py @@ -138,6 +138,39 @@ class class_registry static std::vector static_derived_class_info; }; +template +no_t* is_plain_aux(type >); + +template +string forward_python_type_name(python::type >) +{ + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); +} + +template +no_t* is_plain_aux(type >); + +template +string forward_python_type_name(python::type >) +{ + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); +} + +template +string python_type_name(type) +{ + if(class_registry::class_object() == 0) + { + return string("UnknownType"); + } + else + { + return class_registry::class_object()->complete_class_name(); + } +} + }} // namespace python::detail BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE @@ -319,7 +352,9 @@ class read_only_setattr_function : public function public: read_only_setattr_function(const char* name); PyObject* do_call(PyObject* args, PyObject* keywords) const; - const char* description() const; + PyObject* description() const; + string function_name() const + { return m_name; } private: string m_name; }; @@ -433,7 +468,7 @@ class extension_class template inline void def_raw(Fn fn, const char* name) { - this->add_method(new_raw_arguments_function(fn), name); + this->add_method(new_raw_arguments_function(fn, name), name); } // define member functions. In fact this works for free functions, too - @@ -443,7 +478,7 @@ class extension_class template inline void def(Fn fn, const char* name) { - this->add_method(new_wrapped_function(fn), name); + this->add_method(new_wrapped_function(fn, name), name); } // Define a virtual member function with a default implementation. @@ -452,7 +487,7 @@ class extension_class template inline void def(Fn fn, const char* name, DefaultFn default_fn) { - this->add_method(new_virtual_function(type(), fn, default_fn), name); + this->add_method(new_virtual_function(type(), fn, default_fn, name), name); } // Provide a function which implements x., reading from the given @@ -460,7 +495,7 @@ class extension_class template inline void def_getter(MemberType T::*pm, const char* name) { - this->add_getter_method(new getter_function(pm), name); + this->add_getter_method(new getter_function(pm, name), name); } // Provide a function which implements assignment to x., writing to @@ -468,7 +503,7 @@ class extension_class template inline void def_setter(MemberType T::*pm, const char* name) { - this->add_setter_method(new setter_function(pm), name); + this->add_setter_method(new setter_function(pm, name), name); } // Expose the given member (pm) of the T obj as a read-only attribute diff --git a/gen_function.py b/gen_function.py index bebbc818..5137d44b 100644 --- a/gen_function.py +++ b/gen_function.py @@ -35,6 +35,8 @@ def _gen_arg(template, n, args, delimiter = '%'): if key == 'n': result = result + `n` + elif key == 'N': + result = result + `n-1` else: result = result + _gen_common_key(key, n, args) @@ -55,8 +57,13 @@ def gen_function(template, n, *args, **keywords): %n is transformed into the string representation of 1..n for each repetition of n. - %x, where x is a digit, is transformed into the corresponding additional + %N is transformed into the string representation of 0..(n-1) for each repetition + of n. + + %i, where i is a digit, is transformed into the corresponding additional argument. + + %x is transformed into the number of the current repetition for example, diff --git a/gen_init_function.py b/gen_init_function.py index 9fedec2c..ab6e3422 100644 --- a/gen_init_function.py +++ b/gen_init_function.py @@ -130,6 +130,8 @@ private: // override function hook PyObject* do_call(PyObject* args, PyObject* keywords) const; private: virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0; + string description_as_string() const; + string argument_types_as_string(tuple args) const; }; """ + gen_functions(""" @@ -145,8 +147,20 @@ struct init%x : init python::detail::reference_parameter(from_python(a%n, type()))%) ); } - const char* description() const - { return typeid(void (*)(T&%(, A%n%%))).name(); } + + PyObject* description() const + { + return function_signature(python::type()%(, + python::type()%)); + } + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; + } };""", args) + """ }} // namespace python::detail diff --git a/init_function.cpp b/init_function.cpp index f29e914a..de6c3c99 100644 --- a/init_function.cpp +++ b/init_function.cpp @@ -33,4 +33,24 @@ namespace python { namespace detail { return none(); } +string init::description_as_string() const +{ + tuple arguments(ref(this->description())); + string result("("); + for (std::size_t i = 1; i < arguments.size(); ++i) + { + if (i != 1) + result += ", "; + result += string(arguments[i]); + } + + result += ")"; + return result; +} + +string init::argument_types_as_string(tuple arguments) const +{ + return argument_tuple_as_string(arguments.slice(1,arguments.size())); +} + }} // namespace python::detail diff --git a/init_function.h b/init_function.h index 14da7842..dfc2fea0 100644 --- a/init_function.h +++ b/init_function.h @@ -110,11 +110,6 @@ template struct init2; template struct init3; template struct init4; template struct init5; -template struct Init6; -template struct Init7; -template struct Init8; -template struct Init9; -template struct Init10; template struct init_function @@ -162,71 +157,6 @@ struct init_function detail::parameter_traits::const_reference, detail::parameter_traits::const_reference>; } - - template - static init* create(signature6) { - return new Init6::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature7) { - return new Init7::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature8) { - return new Init8::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature9) { - return new Init9::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } - - template - static init* create(signature10) { - return new Init10::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference, - detail::parameter_traits::const_reference>; - } }; class init : public function @@ -235,6 +165,8 @@ private: // override function hook PyObject* do_call(PyObject* args, PyObject* keywords) const; private: virtual instance_holder_base* create_holder(extension_instance* self, PyObject* tail_args, PyObject* keywords) const = 0; + string description_as_string() const; + string argument_types_as_string(tuple args) const; }; @@ -248,8 +180,19 @@ struct init0 : init return new T(self ); } - const char* description() const - { return typeid(void (*)(T&)).name(); } + + PyObject* description() const + { + return function_signature(python::type()); + } + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; + } }; template @@ -264,8 +207,20 @@ struct init1 : init python::detail::reference_parameter(from_python(a1, type())) ); } - const char* description() const - { return typeid(void (*)(T&, A1)).name(); } + + PyObject* description() const + { + return function_signature(python::type(), + python::type()); + } + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; + } }; template @@ -282,8 +237,21 @@ struct init2 : init python::detail::reference_parameter(from_python(a2, type())) ); } - const char* description() const - { return typeid(void (*)(T&, A1, A2)).name(); } + + PyObject* description() const + { + return function_signature(python::type(), + python::type(), + python::type()); + } + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; + } }; template @@ -302,8 +270,22 @@ struct init3 : init python::detail::reference_parameter(from_python(a3, type())) ); } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3)).name(); } + + PyObject* description() const + { + return function_signature(python::type(), + python::type(), + python::type(), + python::type()); + } + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; + } }; template @@ -324,8 +306,23 @@ struct init4 : init python::detail::reference_parameter(from_python(a4, type())) ); } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4)).name(); } + + PyObject* description() const + { + return function_signature(python::type(), + python::type(), + python::type(), + python::type(), + python::type()); + } + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; + } }; template @@ -348,160 +345,27 @@ struct init5 : init python::detail::reference_parameter(from_python(a5, type())) ); } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5)).name(); } -}; - -template -struct Init6 : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - if (!PyArg_ParseTuple(args, const_cast("OOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6)) - throw argument_error(); - return new T(self, - python::detail::reference_parameter(from_python(a1, type())), - python::detail::reference_parameter(from_python(a2, type())), - python::detail::reference_parameter(from_python(a3, type())), - python::detail::reference_parameter(from_python(a4, type())), - python::detail::reference_parameter(from_python(a5, type())), - python::detail::reference_parameter(from_python(a6, type())) - ); + + PyObject* description() const + { + return function_signature(python::type(), + python::type(), + python::type(), + python::type(), + python::type(), + python::type()); } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6)).name(); } -}; - -template -struct Init7 : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7)) - throw argument_error(); - return new T(self, - python::detail::reference_parameter(from_python(a1, type())), - python::detail::reference_parameter(from_python(a2, type())), - python::detail::reference_parameter(from_python(a3, type())), - python::detail::reference_parameter(from_python(a4, type())), - python::detail::reference_parameter(from_python(a5, type())), - python::detail::reference_parameter(from_python(a6, type())), - python::detail::reference_parameter(from_python(a7, type())) - ); + + string function_name() const + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + string result(python_type_name_selector::get(python::type())); + result += ".__init__"; + return result; } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7)).name(); } -}; - -template -struct Init8 : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8)) - throw argument_error(); - return new T(self, - python::detail::reference_parameter(from_python(a1, type())), - python::detail::reference_parameter(from_python(a2, type())), - python::detail::reference_parameter(from_python(a3, type())), - python::detail::reference_parameter(from_python(a4, type())), - python::detail::reference_parameter(from_python(a5, type())), - python::detail::reference_parameter(from_python(a6, type())), - python::detail::reference_parameter(from_python(a7, type())), - python::detail::reference_parameter(from_python(a8, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8)).name(); } -}; - -template -struct Init9 : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9)) - throw argument_error(); - return new T(self, - python::detail::reference_parameter(from_python(a1, type())), - python::detail::reference_parameter(from_python(a2, type())), - python::detail::reference_parameter(from_python(a3, type())), - python::detail::reference_parameter(from_python(a4, type())), - python::detail::reference_parameter(from_python(a5, type())), - python::detail::reference_parameter(from_python(a6, type())), - python::detail::reference_parameter(from_python(a7, type())), - python::detail::reference_parameter(from_python(a8, type())), - python::detail::reference_parameter(from_python(a9, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9)).name(); } -}; - -template -struct Init10 : init -{ - virtual instance_holder_base* create_holder(extension_instance* self, PyObject* args, PyObject* /*keywords*/) const - { - PyObject* a1; - PyObject* a2; - PyObject* a3; - PyObject* a4; - PyObject* a5; - PyObject* a6; - PyObject* a7; - PyObject* a8; - PyObject* a9; - PyObject* a10; - if (!PyArg_ParseTuple(args, const_cast("OOOOOOOOOO"), &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9, &a10)) - throw argument_error(); - return new T(self, - python::detail::reference_parameter(from_python(a1, type())), - python::detail::reference_parameter(from_python(a2, type())), - python::detail::reference_parameter(from_python(a3, type())), - python::detail::reference_parameter(from_python(a4, type())), - python::detail::reference_parameter(from_python(a5, type())), - python::detail::reference_parameter(from_python(a6, type())), - python::detail::reference_parameter(from_python(a7, type())), - python::detail::reference_parameter(from_python(a8, type())), - python::detail::reference_parameter(from_python(a9, type())), - python::detail::reference_parameter(from_python(a10, type())) - ); - } - const char* description() const - { return typeid(void (*)(T&, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)).name(); } }; }} // namespace python::detail #endif // INIT_FUNCTION_DWA052000_H_ + diff --git a/module.h b/module.h index 601ef17d..fd92f5a6 100644 --- a/module.h +++ b/module.h @@ -18,8 +18,6 @@ namespace python { class module_builder { - typedef PyObject * (*raw_function_ptr)(python::tuple const &, python::dictionary const &); - public: // Create a module. REQUIRES: only one module_builder is created per module. module_builder(const char* name); @@ -32,13 +30,13 @@ class module_builder template void def_raw(Fn fn, const char* name) { - add(detail::new_raw_arguments_function(fn), name); + add(detail::new_raw_arguments_function(fn, name), name); } template void def(Fn fn, const char* name) { - add(detail::new_wrapped_function(fn), name); + add(detail::new_wrapped_function(fn, name), name); } static string name(); diff --git a/objects.h b/objects.h index 31ac3284..e9d8a240 100644 --- a/objects.h +++ b/objects.h @@ -293,6 +293,152 @@ struct list::slice_proxy int m_low, m_high; }; +namespace detail +{ +#define BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(T, name) \ + inline string python_type_name(python::type) \ + { return string(#name); } + +#if 0 + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(long, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned long, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(int, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned int, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(short, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned short, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(signed char, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned char, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(bool, types.IntType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(float, types.FloatType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(double, types.FloatType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(void, types.NoneType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(const char *, types.StringType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(std::string, types.StringType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(PyObject, AnyType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(reference, AnyType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(list, types.ListType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(tuple, types.TupleType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(dictionary, types.DictionaryType); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(string, types.StringType); +#endif /* #if 0 */ + + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(long, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned long, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(int, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned int, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(short, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned short, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(signed char, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(unsigned char, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(bool, int); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(float, float); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(double, float); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(void, None); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(const char *, string); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(std::string, string); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(PyObject, any); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(reference, any); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(list, list); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(tuple, tuple); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(dictionary, dictionary); + BOOST_PYTHON_OVERLOAD_TYPENAME_FUNCTION(string, string); + + typedef char no_t[1]; + typedef char yes_t[2]; + + yes_t* is_plain_aux(...); + + template + no_t* is_plain_aux(type); + + template + no_t* is_plain_aux(type); + + template + no_t* is_plain_aux(type); + + template + no_t* is_plain_aux(type); + + template + no_t* is_plain_aux(type >); + + template + no_t* is_plain_aux(type >); + + template + no_t* is_plain_aux(type >); + +#define BOOST_PYTHON_IS_PLAIN(T) \ + (sizeof(*python::detail::is_plain_aux(python::type())) == \ + sizeof(python::detail::yes_t)) + + template + struct python_type_name_selector + { + template + static string get(python::type t) + { return python_type_name(t); } + }; + + template + string forward_python_type_name(python::type) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template + string forward_python_type_name(python::type) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template + string forward_python_type_name(python::type) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template + string forward_python_type_name(python::type) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template + string forward_python_type_name(python::type >) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template + string forward_python_type_name(python::type >) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template + string forward_python_type_name(python::type >) + { + static const bool is_plain = BOOST_PYTHON_IS_PLAIN(T); + return python_type_name_selector::get(python::type()); + } + + template <> + struct python_type_name_selector + { + template + static string get(python::type t) + { return forward_python_type_name(t); } + }; +} // namespace detail + } // namespace python BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE diff --git a/operators.h b/operators.h index 95528bc8..1c07f346 100644 --- a/operators.h +++ b/operators.h @@ -197,8 +197,7 @@ namespace detail }; }; - - + // Fully specialize define_operator for all operators defined in operator_id above. // Every specialization defines one function object for normal operator calls and one // for operator calls with operands reversed ("__r*__" function variants). @@ -214,15 +213,20 @@ namespace detail { \ PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ { \ - tuple args(ref(arguments, ref::increment_count)); \ + tuple args(ref(arguments, ref::increment_count)); \ \ return BOOST_PYTHON_CONVERSION::to_python( \ BOOST_PYTHON_CONVERSION::from_python(args[0].get(), python::type()) oper \ BOOST_PYTHON_CONVERSION::from_python(args[1].get(), python::type())); \ } \ \ - const char* description() const \ - { return "__" #id "__"; } \ + string function_name() const \ + { return string(name()); } \ + \ + PyObject* description() const \ + { \ + return function_signature(python::type(), python::type()); \ + } \ }; \ \ template \ @@ -230,15 +234,20 @@ namespace detail { \ PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ { \ - tuple args(ref(arguments, ref::increment_count)); \ + tuple args(ref(arguments, ref::increment_count)); \ \ - return BOOST_PYTHON_CONVERSION::to_python( \ + return BOOST_PYTHON_CONVERSION::to_python( \ BOOST_PYTHON_CONVERSION::from_python(args[1].get(), python::type()) oper \ BOOST_PYTHON_CONVERSION::from_python(args[0].get(), python::type())); \ } \ \ - const char* description() const \ - { return "__r" #id "__"; } \ + string function_name() const \ + { return string(rname()); } \ + \ + PyObject* description() const \ + { \ + return function_signature(python::type(), python::type()); \ + } \ \ }; \ \ @@ -255,14 +264,19 @@ namespace detail { \ PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ { \ - tuple args(ref(arguments, ref::increment_count)); \ + tuple args(ref(arguments, ref::increment_count)); \ \ - return BOOST_PYTHON_CONVERSION::to_python( \ + return BOOST_PYTHON_CONVERSION::to_python( \ oper(BOOST_PYTHON_CONVERSION::from_python(args[0].get(), python::type()))); \ } \ \ - const char* description() const \ - { return "__" #id "__"; } \ + string function_name() const \ + { return string(name()); } \ + \ + PyObject* description() const \ + { \ + return function_signature(python::type()); \ + } \ }; \ \ static const char * name() { return "__" #id "__"; } \ @@ -317,8 +331,13 @@ namespace detail BOOST_PYTHON_CONVERSION::from_python(args[1].get(), python::type()))); } - const char* description() const - { return "__pow__"; } + string function_name() const + { return string(name()); } + + PyObject* description() const + { + return function_signature(python::type(), python::type()); + } }; @@ -331,7 +350,7 @@ namespace detail if (args.size() == 3 && args[2]->ob_type != Py_None->ob_type) { - PyErr_SetString(PyExc_TypeError, "bad operand type(s) for pow()"); + PyErr_SetString(PyExc_TypeError, "'__pow__' expected 2 arguments, got 3."); throw argument_error(); } @@ -340,8 +359,13 @@ namespace detail BOOST_PYTHON_CONVERSION::from_python(args[0].get(), python::type()))); } - const char* description() const - { return "__rpow__"; } + string function_name() const + { return string(rname()); } + + PyObject* description() const + { + return function_signature(python::type(), python::type()); + } }; @@ -374,8 +398,13 @@ namespace detail return res; } - const char* description() const - { return "__divmod__"; } + string function_name() const + { return string(name()); } + + PyObject* description() const + { + return function_signature(python::type(), python::type()); + } }; @@ -399,9 +428,13 @@ namespace detail return res; } - const char* description() const - { return "__rdivmod__"; } + string function_name() const + { return string(rname()); } + PyObject* description() const + { + return function_signature(python::type(), python::type()); + } }; static const char * name() { return "__divmod__"; } @@ -430,8 +463,13 @@ namespace detail 0) ; } - const char* description() const - { return "__cmp__"; } + string function_name() const + { return string(name()); } + + PyObject* description() const + { + return function_signature(python::type(), python::type()); + } }; @@ -452,8 +490,13 @@ namespace detail 0) ; } - const char* description() const - { return "__rcmp__"; } + string function_name() const + { return string(rname()); } + + PyObject* description() const + { + return function_signature(python::type(), python::type()); + } }; @@ -488,8 +531,13 @@ namespace detail #endif } - const char* description() const - { return "__str__"; } + string function_name() const + { return string(name()); } + + PyObject* description() const + { + return function_signature(python::type()); + } }; diff --git a/signatures.h b/signatures.h index 39dd94c2..ec345dfe 100644 --- a/signatures.h +++ b/signatures.h @@ -18,7 +18,7 @@ namespace detail { // A stand-in for the built-in void. This one can be passed to functions and // (under MSVC, which has a bug, be used as a default template type parameter). struct void_t {}; -} +} // namespace detail // An envelope in which type information can be delivered for the purposes // of selecting an overloaded from_python() function. This is needed to work diff --git a/subclass.cpp b/subclass.cpp index ee28fd72..3598cb61 100644 --- a/subclass.cpp +++ b/subclass.cpp @@ -67,7 +67,7 @@ namespace { ref global_class_reduce() { - static ref result(detail::new_wrapped_function(class_reduce)); + static ref result(detail::new_wrapped_function(class_reduce, "__reduce__")); return result; } @@ -111,7 +111,7 @@ namespace { ref global_instance_reduce() { - static ref result(detail::new_wrapped_function(instance_reduce)); + static ref result(detail::new_wrapped_function(instance_reduce, "__reduce__")); return result; } } @@ -225,14 +225,21 @@ namespace detail { // Mostly copied wholesale from Python's classobject.c PyObject* class_base::repr() const + { + unsigned long address = reinterpret_cast(this); + string result = string("") % tuple(complete_class_name(), address); + return result.reference().release(); + } + + + // Mostly copied wholesale from Python's classobject.c + string class_base::complete_class_name() const { PyObject *mod = PyDict_GetItemString( m_name_space.get(), const_cast("__module__")); - unsigned long address = reinterpret_cast(this); - string result = (mod == NULL || !PyString_Check(mod)) - ? string("") % tuple(m_name, address) - : string("") % tuple(ref(mod, ref::increment_count), m_name, address); - return result.reference().release(); + return (mod == NULL || !PyString_Check(mod)) + ? m_name + : string("%s.%s") % tuple(ref(mod, ref::increment_count), m_name); } diff --git a/subclass.h b/subclass.h index a7679a95..714f0c5a 100644 --- a/subclass.h +++ b/subclass.h @@ -97,6 +97,9 @@ namespace detail { int setattr(const char* name, PyObject* value); PyObject* repr() const; void add_base(ref base); + + // get the complete class name (i.e. "module.class") + virtual string complete_class_name() const; protected: bool initialize_instance(instance* obj, PyObject* args, PyObject* keywords); diff --git a/test_extclass.py b/test_extclass.py index 578197f1..c321ac36 100644 --- a/test_extclass.py +++ b/test_extclass.py @@ -10,15 +10,18 @@ r''' Automatic checking of the number and type of arguments. Foo's constructor takes a single long parameter. - >>> ext = Foo() - Traceback (innermost last): - File "", line 1, in ? - TypeError: function requires exactly 1 argument; 0 given + >>> try: ext = Foo() + ... except TypeError, err: + ... assert re.match( + ... "'demo.Foo.__init__' expected argument\(s\) \(int\),\n" + ... "but got \(\) instead.", str(err)) + ... else: print 'no exception' >>> try: ext = Foo('foo') ... except TypeError, err: ... assert re.match( - ... '(illegal argument type for built-in operation)|(an integer is required)', str(err)) + ... "'demo.Foo.__init__' expected argument\(s\) \(int\),\n" + ... "but got \(string\) instead.", str(err)) ... else: print 'no exception' >>> ext = Foo(1) @@ -160,10 +163,16 @@ a Bar parameter: But objects not derived from Bar cannot: - >>> baz.pass_bar(baz) - Traceback (innermost last): - ... - TypeError: extension class 'Baz' is not convertible into 'Bar'. + >>> try: baz.pass_bar(baz) + ... except TypeError, err: + ... assert re.match( + ... "'pass_bar' expected argument\(s\) \(demo.Baz, demo.Bar\),\n" + ... "but got \(demo.Baz, demo.Baz\) instead.", str(err)) + ... else: print 'no exception' + +(this error was: +TypeError: extension class 'Baz' is not convertible into 'Bar'. +) The clone function on Baz returns a smart pointer; we wrap it into an extension_instance and make it look just like any other Baz obj. @@ -354,7 +363,11 @@ Some simple overloading tests: >>> try: r = Range('yikes') ... except TypeError, e: ... assert re.match( - ... 'No overloaded functions match [(]Range, string[)]\. Candidates are:\n.*\n.*', + ... "No variant of overloaded function 'demo.Range.__init__' matches argument\(s\):\n" + ... "\(string\)\n" + ... "Candidates are:\n" + ... "\(int\)\n" + ... "\(int, int\)", ... str(e)) ... else: print 'no exception' @@ -564,7 +577,17 @@ Testing overloaded free functions 15 >>> try: overloaded(1, 'foo') ... except TypeError, err: - ... assert re.match("No overloaded functions match \(int, string\)\. Candidates are:", + ... assert re.match( + ... "No variant of overloaded function 'overloaded' matches argument\(s\):\n" + ... "\(int, string\)\n" + ... "Candidates are:\n" + ... "\(\)\n" + ... "\(int\)\n" + ... "\(string\)\n" + ... "\(int, int\)\n" + ... "\(int, int, int\)\n" + ... "\(int, int, int, int\)\n" + ... "\(int, int, int, int, int\)", ... str(err)) ... else: ... print 'no exception' @@ -594,7 +617,17 @@ Testing overloaded constructors 5 >>> try: over = OverloadTest(1, 'foo') ... except TypeError, err: - ... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:", + ... assert re.match( + ... "No variant of overloaded function 'demo.OverloadTest.__init__' matches argument\(s\):\n" + ... "\(int, string\)\n" + ... "Candidates are:\n" + ... "\(\)\n" + ... "\(demo.OverloadTest\)\n" + ... "\(int\)\n" + ... "\(int, int\)\n" + ... "\(int, int, int\)\n" + ... "\(int, int, int, int\)\n" + ... "\(int, int, int, int, int\)", ... str(err)) ... else: ... print 'no exception' @@ -616,16 +649,35 @@ Testing overloaded methods 5 >>> try: over.overloaded(1,'foo') ... except TypeError, err: - ... assert re.match("No overloaded functions match \(OverloadTest, int, string\)\. Candidates are:", + ... assert re.match( + ... "No variant of overloaded function 'overloaded' matches argument\(s\):\n" + ... "\(demo.OverloadTest, int, string\)\n" + ... "Candidates are:\n" + ... "\(demo.OverloadTest\)\n" + ... "\(demo.OverloadTest, int\)\n" + ... "\(demo.OverloadTest, int, int\)\n" + ... "\(demo.OverloadTest, int, int, int\)\n" + ... "\(demo.OverloadTest, int, int, int, int\)\n" + ... "\(demo.OverloadTest, int, int, int, int, int\)", ... str(err)) ... else: ... print 'no exception' Testing base class conversions - >>> testUpcast(over) - Traceback (innermost last): - TypeError: extension class 'OverloadTest' is not convertible into 'Base'. + >>> try: testUpcast(over) + ... except TypeError, err: + ... assert re.match( + ... "'testUpcast' expected argument\(s\) \(demo.Base\),\n" + ... "but got \(demo.OverloadTest\) instead.", + ... str(err)) + ... else: + ... print 'no exception' + +(this error was: +TypeError: extension class 'OverloadTest' is not convertible into 'Base'. +) + >>> der1 = Derived1(333) >>> der1.x() 333 @@ -634,18 +686,37 @@ Testing base class conversions >>> der1 = derived1Factory(1000) >>> testDowncast1(der1) 1000 - >>> testDowncast2(der1) - Traceback (innermost last): + >>> try: testDowncast2(der1) + ... except TypeError, err: + ... assert re.match( + ... "'testDowncast2' expected argument\(s\) \(demo.Derived2\),\n" + ... "but got \(demo.Base\) instead.", + ... str(err)) + ... else: + ... print 'no exception' + +(this error was: TypeError: extension class 'Base' is not convertible into 'Derived2'. +) + >>> der2 = Derived2(444) >>> der2.x() 444 >>> testUpcast(der2) 444 >>> der2 = derived2Factory(1111) - >>> testDowncast2(der2) - Traceback (innermost last): + >>> try: testDowncast2(der2) + ... except TypeError, err: + ... assert re.match( + ... "'testDowncast2' expected argument\(s\) \(demo.Derived2\),\n" + ... "but got \(demo.Base\) instead.", + ... str(err)) + ... else: + ... print 'no exception' + +(this error was: TypeError: extension class 'Base' is not convertible into 'Derived2'. +) Testing interaction between callbacks, base declarations, and overloading - testCallback() calls callback() (within C++) @@ -656,10 +727,14 @@ Testing interaction between callbacks, base declarations, and overloading >>> c = CallbackTest() >>> c.testCallback(1) 2 - >>> c.testCallback('foo') - Traceback (innermost last): - File "", line 1, in ? - TypeError: illegal argument type for built-in operation + >>> try: c.testCallback('foo') + ... except TypeError, err: + ... assert re.match( + ... "'testCallback' expected argument\(s\) \(demo.CallbackTestBase, int\),\n" + ... "but got \(demo.CallbackTest, string\) instead.", + ... str(err)) + ... else: + ... print 'no exception' >>> c.callback(1) 2 >>> c.callback('foo') @@ -678,10 +753,14 @@ Testing interaction between callbacks, base declarations, and overloading -1 >>> r.callback('foo') 'foo 1' - >>> r.testCallback('foo') - Traceback (innermost last): - File "", line 1, in ? - TypeError: illegal argument type for built-in operation + >>> try: r.testCallback('foo') + ... except TypeError, err: + ... assert re.match( + ... "'testCallback' expected argument\(s\) \(demo.CallbackTestBase, int\),\n" + ... "but got \(demo.RedefineCallback, string\) instead.", + ... str(err)) + ... else: + ... print 'no exception' >>> r.testCallback(1) -1 >>> testCallback(r, 1) @@ -969,15 +1048,33 @@ test inheritB2 >>> j = pow(i, 5) >>> j.i() 32 - >>> j = pow(i, 5, k) - Traceback (innermost last): - TypeError: bad operand type(s) for pow() - >>> j = pow(i, 5, 5) - Traceback (innermost last): - TypeError: bad operand type(s) for pow() + >>> try: j = pow(i, 5, k) + ... except TypeError, err: + ... assert re.match( + ... "No variant of overloaded function '__pow__' matches argument\(s\):\n" + ... "\(demo.Int, int, demo.Int\)\n" + ... "Candidates are:\n" + ... "\(demo.Int, demo.Int\)\n" + ... "\(demo.Int, demo.Int, demo.Int\)\n" + ... "\(demo.Int, int\)", + ... str(err)) + ... else: + ... print 'no exception' + >>> try: j = pow(i, 5, 5) + ... except TypeError, err: + ... assert re.match( + ... "No variant of overloaded function '__pow__' matches argument\(s\):\n" + ... "\(demo.Int, int, int\)\n" + ... "Candidates are:\n" + ... "\(demo.Int, demo.Int\)\n" + ... "\(demo.Int, demo.Int, demo.Int\)\n" + ... "\(demo.Int, int\)", + ... str(err)) + ... else: + ... print 'no exception' >>> j = i/1 Traceback (innermost last): - TypeError: bad operand type(s) for / + TypeError: __div__(demo.Int, int) undefined. >>> j = 1+i >>> j.i() 3 @@ -993,10 +1090,10 @@ test inheritB2 -1 >>> j = 1/i Traceback (innermost last): - TypeError: bad operand type(s) for / + TypeError: __rdiv__(demo.Int, int) undefined. >>> pow(1,i) Traceback (innermost last): - TypeError: bad operand type(s) for pow() + TypeError: __rpow__(demo.Int, int) undefined. Test operator export to a subclass