catch exceptions in method calls too

This commit is contained in:
Gustavo J. A. M. Carneiro committed 2009-08-23 19:16:42 +01:00
1 parent f14f0a8f20
commit 262c88f846
5 files changed
+56 -2

No files matched your search

+27 -1
View File
@@ -13,6 +13,8 @@ from typehandlers import codesink
import overloading
import settings
import utils
from cppexception import CppException
class CppMethod(ForwardWrapperBase):
"""
@@ -23,7 +25,7 @@ class CppMethod(ForwardWrapperBase):
template_parameters=(), is_virtual=None, is_const=False,
unblock_threads=None, is_pure_virtual=False,
custom_template_method_name=None, visibility='public',
custom_name=None, deprecated=False, docstring=None):
custom_name=None, deprecated=False, docstring=None, throw=()):
"""
Create an object the generates code to wrap a C++ class method.
@@ -66,6 +68,9 @@ class CppMethod(ForwardWrapperBase):
- False: Not deprecated
- True: Deprecated
- "message": Deprecated, and deprecation warning contains the given message
@param throw: list of C++ exceptions that the function may throw
@type throw: list of L{CppException}
"""
self.stack_where_defined = traceback.extract_stack()
@@ -114,6 +119,10 @@ class CppMethod(ForwardWrapperBase):
unblock_threads=unblock_threads)
self.deprecated = deprecated
for t in throw:
assert isinstance(t, CppException)
self.throw = list(throw)
def set_helper_class(self, helper_class):
"Set the C++ helper class, which is used for overriding virtual methods"
self._helper_class = helper_class
@@ -189,6 +198,12 @@ class CppMethod(ForwardWrapperBase):
method = '%s::%s%s' % (class_.full_name, self.method_name, template_params)
else:
method = 'self->obj->%s%s' % (self.method_name, template_params)
if self.throw:
self.before_call.write_code('try\n{')
self.before_call.indent()
if self.return_value.ctype == 'void':
self.before_call.write_code(
'%s(%s);' %
@@ -203,6 +218,17 @@ class CppMethod(ForwardWrapperBase):
'retval = %s(%s);' %
(method, ", ".join(self.call_params)))
if self.throw:
for exc in self.throw:
self.before_call.unindent()
self.before_call.write_code('} catch (%s const &exc) {' % exc.full_name)
self.before_call.indent()
self.before_call.write_cleanup()
self.before_call.write_code('PyErr_SetNone((PyObject *) %s);\nreturn NULL;' % exc.pytypestruct)
self.before_call.unindent()
self.before_call.write_code('}')
def _before_return_hook(self):
"""hook that post-processes parameters and check for custodian=<n>
CppClass parameters"""
+14 -1
View File
@@ -434,7 +434,20 @@ namespace xpto
}
}
double my_inverse_func (double x) throw (DomainError)
double
my_inverse_func (double x) throw (DomainError)
{
if (x == 0)
{
DomainError ex;
ex.message = "value must be != 0";
throw ex;
}
return 1/x;
}
double
ClassThatThrows::my_inverse_method (double x) throw (DomainError)
{
if (x == 0)
{
+5
View File
@@ -1046,6 +1046,11 @@ struct DomainError : public Error
// returns 1/x, raises DomainError if x == 0
double my_inverse_func (double x) throw (DomainError);
struct ClassThatThrows
{
// returns 1/x, raises DomainError if x == 0
double my_inverse_method (double x) throw (DomainError);
};
#endif /* !FOO_H_ */
+4
View File
@@ -500,6 +500,10 @@ int %s::custom_method_added_by_a_hook(int x)
mod.add_function('my_inverse_func', 'double', [Parameter.new('double', 'x')],
throw=[DomainError])
ClassThatThrows = mod.add_struct('ClassThatThrows')
ClassThatThrows.add_method('my_inverse_method', 'double', [Parameter.new('double', 'x')],
throw=[DomainError])
#### --- error handler ---
class MyErrorHandler(pybindgen.settings.ErrorHandler):
+6
View File
@@ -1166,5 +1166,11 @@ class TestFoo(unittest.TestCase):
self.assertEqual(y, 0.5)
self.assertRaises(foo.DomainError, foo.my_inverse_func, 0)
def test_method_exception(self):
c = foo.ClassThatThrows()
y = c.my_inverse_method(2)
self.assertEqual(y, 0.5)
self.assertRaises(foo.DomainError, c.my_inverse_method, 0)
if __name__ == '__main__':
unittest.main()