mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 06:02:14 +00:00
Implemented better error reporting for argument match errors.
[SVN r19271]
This commit is contained in:
@@ -172,9 +172,9 @@ struct caller_arity<N>
|
||||
|
||||
static unsigned min_arity() { return N; }
|
||||
|
||||
static char const*const* type_names()
|
||||
static signature_element const* signature()
|
||||
{
|
||||
return signature<Sig>::type_names();
|
||||
return detail::signature<Sig>::elements();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/python/instance_holder.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
@@ -24,7 +24,7 @@ struct BOOST_PYTHON_DECL py_function_impl_base
|
||||
virtual PyObject* operator()(PyObject*, PyObject*) = 0;
|
||||
virtual unsigned min_arity() const = 0;
|
||||
virtual unsigned max_arity() const;
|
||||
virtual char const* const* type_names() const = 0;
|
||||
virtual python::detail::signature_element const* signature() const = 0;
|
||||
};
|
||||
|
||||
template <class Caller>
|
||||
@@ -44,9 +44,9 @@ struct caller_py_function_impl : py_function_impl_base
|
||||
return m_caller.min_arity();
|
||||
}
|
||||
|
||||
virtual char const* const* type_names() const
|
||||
virtual python::detail::signature_element const* signature() const
|
||||
{
|
||||
return m_caller.type_names();
|
||||
return m_caller.signature();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -70,9 +70,9 @@ struct signature_py_function_impl : py_function_impl_base
|
||||
return mpl::size<Sig>::value - 1;
|
||||
}
|
||||
|
||||
virtual char const* const* type_names() const
|
||||
virtual python::detail::signature_element const* signature() const
|
||||
{
|
||||
return python::detail::signature<Sig>::type_names();
|
||||
return python::detail::signature<Sig>::elements();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -103,9 +103,9 @@ struct full_py_function_impl : py_function_impl_base
|
||||
return m_max_arity;
|
||||
}
|
||||
|
||||
virtual char const* const* type_names() const
|
||||
virtual python::detail::signature_element const* signature() const
|
||||
{
|
||||
return python::detail::signature<Sig>::type_names();
|
||||
return python::detail::signature<Sig>::elements();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -150,6 +150,11 @@ struct py_function
|
||||
return m_impl->max_arity();
|
||||
}
|
||||
|
||||
python::detail::signature_element const* signature() const
|
||||
{
|
||||
return m_impl->signature();
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::auto_ptr<py_function_impl_base> m_impl;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <boost/python/args.hpp>
|
||||
#include <boost/python/refcount.hpp>
|
||||
#include <boost/python/extract.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/list.hpp>
|
||||
|
||||
#include <boost/python/detail/signature.hpp>
|
||||
#include <boost/mpl/vector/vector10.hpp>
|
||||
@@ -173,8 +175,53 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
|
||||
|
||||
void function::argument_error(PyObject* args, PyObject* keywords) const
|
||||
{
|
||||
// This function needs to be improved to do better error reporting.
|
||||
PyErr_BadArgument();
|
||||
static handle<> exception(
|
||||
PyErr_NewException("Boost.Python.ArgumentError", PyExc_TypeError, 0));
|
||||
|
||||
str message("Python argument types\n (");
|
||||
list actual;
|
||||
for (int i = 0; i < PyTuple_Size(args); ++i)
|
||||
{
|
||||
char const* name = PyTuple_GetItem(args, i)->ob_type->tp_name;
|
||||
actual.append(str(name));
|
||||
}
|
||||
message += str(", ").join(actual);
|
||||
message += ")\ndid not match C++ signature:\n ";
|
||||
|
||||
list signatures;
|
||||
for (function const* f = this; f; f = f->m_overloads.get())
|
||||
{
|
||||
py_function const& impl = f->m_fn;
|
||||
|
||||
python::detail::signature_element const* s
|
||||
= impl.signature();
|
||||
|
||||
list formal;
|
||||
if (impl.max_arity() == 0)
|
||||
formal.append("void");
|
||||
|
||||
for (unsigned n = 1; n <= impl.max_arity(); ++n)
|
||||
{
|
||||
if (s[n].basename == 0)
|
||||
{
|
||||
formal.append("...");
|
||||
break;
|
||||
}
|
||||
|
||||
formal.append(
|
||||
str(s[n].basename) + (s[n].lvalue ? " {lvalue}" : "")
|
||||
);
|
||||
}
|
||||
|
||||
signatures.append(
|
||||
"(%s) -> %s" % make_tuple(str(", ").join(formal), s[0].basename)
|
||||
);
|
||||
}
|
||||
|
||||
message += str("\n ").join(signatures);
|
||||
|
||||
PyErr_SetObject(exception.get(), message.ptr());
|
||||
throw_error_already_set();
|
||||
}
|
||||
|
||||
void function::add_overload(handle<function> const& overload_)
|
||||
|
||||
@@ -73,3 +73,5 @@ BOOST_PYTHON_MODULE(opaque_ext)
|
||||
bpl::def ("use2", &::use2);
|
||||
bpl::def ("failuse2", &::failuse2);
|
||||
}
|
||||
|
||||
# include "module_tail.cpp"
|
||||
|
||||
@@ -7,18 +7,22 @@
|
||||
|
||||
"""
|
||||
>>> from opaque_ext import *
|
||||
>>> #
|
||||
>>> # Check for correct conversion
|
||||
|
||||
|
||||
Check for correct conversion
|
||||
|
||||
>>> use(get())
|
||||
|
||||
# Check that None is converted to a NULL opaque pointer
|
||||
Check that None is converted to a NULL opaque pointer
|
||||
|
||||
>>> useany(get())
|
||||
1
|
||||
>>> useany(None)
|
||||
0
|
||||
|
||||
# check that we don't lose type information by converting NULL opaque
|
||||
# pointers to None
|
||||
Check that we don't lose type information by converting NULL
|
||||
opaque pointers to None
|
||||
|
||||
>>> assert getnull() is None
|
||||
>>> useany(getnull())
|
||||
0
|
||||
@@ -27,43 +31,41 @@
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RuntimeError: success
|
||||
>>> #
|
||||
>>> # Check that there is no conversion from integers ...
|
||||
>>> use(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # ... and from strings to opaque objects
|
||||
>>> use("")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # Now check the same for another opaque pointer type
|
||||
|
||||
Check that there is no conversion from integers ...
|
||||
|
||||
>>> try: use(0)
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
|
||||
... and from strings to opaque objects
|
||||
|
||||
>>> try: use("")
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
|
||||
Now check the same for another opaque pointer type
|
||||
|
||||
>>> use2(get2())
|
||||
>>> failuse2(get2())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RuntimeError: success
|
||||
>>> use2(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> use2("")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # Check that opaque types are distinct
|
||||
>>> use(get2())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> use2(get())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> try: use2(0)
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
>>> try: use2("")
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
|
||||
Check that opaque types are distinct
|
||||
|
||||
>>> try: use(get2())
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
>>> try: use2(get())
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError'
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
|
||||
Reference in New Issue
Block a user