2
0
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:
Dave Abrahams
2003-07-23 01:31:34 +00:00
parent 8f76b8880e
commit af53ae8329
6 changed files with 104 additions and 49 deletions

View File

@@ -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:

View File

@@ -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>

View File

@@ -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;
};

View File

@@ -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_)

View File

@@ -73,3 +73,5 @@ BOOST_PYTHON_MODULE(opaque_ext)
bpl::def ("use2", &::use2);
bpl::def ("failuse2", &::failuse2);
}
# include "module_tail.cpp"

View File

@@ -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