Bug 1368538: Support translating C++ exception into Python's standard exceptions

This commit is contained in:
Kevin Stenerson
2014-09-14 20:00:55 +01:00
committed by Gustavo Carneiro
parent 878dd743f8
commit c9a9de3371
11 changed files with 124 additions and 84 deletions
+19 -2
View File
@@ -6,7 +6,7 @@ from pybindgen import utils
class CppException(object):
def __init__(self, name, parent=None, outer_class=None, custom_name=None,
foreign_cpp_namespace=None, message_rvalue=None):
foreign_cpp_namespace=None, message_rvalue=None, is_standard_error=False):
"""
:param name: exception class name
:param parent: optional parent class wrapper
@@ -16,6 +16,11 @@ class CppException(object):
the class in the python module will be the same name as
the class in C++ (minus namespace).
:param is_standard_error: if True (default false), throws a
standard Python Exception with the same name instead
of creating anew exception. If custom_name is set,
it uses the standard exception with that name instead.
:param foreign_cpp_namespace: if set, the class is assumed to
belong to the given C++ namespace, regardless of the
C++ namespace of the python module it will be added to.
@@ -42,6 +47,7 @@ class CppException(object):
self.pytypestruct = None
self.foreign_cpp_namespace = foreign_cpp_namespace
self.message_rvalue = message_rvalue
self.is_standard_error = is_standard_error
def __repr__(self):
@@ -97,7 +103,10 @@ class CppException(object):
self.mangled_name = flatten(self.name)
self.mangled_full_name = utils.mangle_name(self.full_name)
self.pytypestruct = "Py%s%s_Type" % (prefix, self.mangled_full_name)
if self.is_standard_error:
self.pytypestruct = "PyExc_%s" % self.python_name
else:
self.pytypestruct = "Py%s%s_Type" % (prefix, self.mangled_full_name)
def _get_python_name(self):
if self.custom_name is None:
@@ -119,6 +128,9 @@ class CppException(object):
def generate_forward_declarations(self, code_sink, dummy_module):
if self.is_standard_error:
return
code_sink.writeln()
code_sink.writeln('extern PyTypeObject *%s;' % (self.pytypestruct,))
code_sink.writeln()
@@ -126,6 +138,11 @@ class CppException(object):
def generate(self, code_sink, module, docstring=None):
"""Generates the class to a code sink"""
# skip generation if translating to a standard Exception
if self.is_standard_error:
return
code_sink.writeln('PyTypeObject *%s;' % (self.pytypestruct,))
## --- register the class type in the module ---
module.after_init.write_code("/* Register the '%s' exception */" % self.full_name)
+30 -32
View File
@@ -207,7 +207,7 @@ class GccXmlTypeRegistry(object):
self.root_module = root_module
self.ordered_classes = [] # registered classes list, by registration order
self._root_ns_rx = re.compile(r"(^|\s)(::)")
def class_registered(self, cpp_class):
assert isinstance(cpp_class, (CppClass, CppException))
self.ordered_classes.append(cpp_class)
@@ -265,7 +265,7 @@ class GccXmlTypeRegistry(object):
type_name = utils.ascii(type_name)
decl = self._root_ns_rx.sub('', type_name)
return decl
def lookup_return(self, type_info, annotations={}):
kwargs = {}
for name, value in annotations.items():
@@ -347,7 +347,7 @@ class AnnotationsScanner(object):
file_name = decl.location.file_name
line_number = decl.location.line
try:
lines = self.files[file_name]
except KeyError:
@@ -532,7 +532,7 @@ class ModuleParser(object):
pre_scan_hook(module_parser, pygccxml_definition, global_annotations,
parameter_annotations)
where:
- module_parser -- the ModuleParser (this class) instance
@@ -561,7 +561,7 @@ class ModuleParser(object):
every scanned type, function, or method. It will be called like this::
post_scan_hook(module_parser, pygccxml_definition, pybindgen_wrapper)
where:
- module_parser -- the ModuleParser (this class) instance
@@ -929,7 +929,7 @@ pybindgen.settings.error_handler = ErrorHandler()
kwargs.setdefault('destructor_visibility', des)
return is_exception
def _get_destructor_visibility(self, cls):
for member in cls.get_members():
if isinstance(member, calldef.destructor_t):
@@ -1105,7 +1105,7 @@ pybindgen.settings.error_handler = ErrorHandler()
self._anonymous_structs.append((cls, outer_class))
continue
if '<' in cls.name:
@@ -1116,7 +1116,7 @@ pybindgen.settings.error_handler = ErrorHandler()
break
else:
typedef = None
base_class_wrappers = []
bases_ok = True
for cls_bases_item in cls.bases:
@@ -1333,7 +1333,7 @@ pybindgen.settings.error_handler = ErrorHandler()
pygen_function_closed = True
if outer_class is None:
## --- look for typedefs ----
for alias in module_namespace.typedefs(function=self.location_filter,
recursive=False, allow_empty=True):
@@ -1502,7 +1502,7 @@ pybindgen.settings.error_handler = ErrorHandler()
else:
assert False, "container type %s unaccounted for." % name
if outer_class is not None:
kwargs['outer_class'] = outer_class
outer_class_key = outer_class.partial_decl_string
@@ -1521,11 +1521,11 @@ pybindgen.settings.error_handler = ErrorHandler()
# key_type = traits.key_type(definition)
#print >> sys.stderr, "************* register_container %s; element_type=%s, key_type=%s" % \
# (name, element_type, key_type.partial_decl_string)
element_decl = type_traits.remove_declarated(element_type)
kwargs['container_type'] = container_type
pygen_sink = self._get_pygen_sink_for_definition(element_decl)
elem_type_spec = self.type_registry.lookup_return(element_type)
@@ -1559,7 +1559,7 @@ pybindgen.settings.error_handler = ErrorHandler()
module.add_container(name, (return_type_key, return_type_elem), **kwargs)
else:
module.add_container(name, return_type_elem, **kwargs)
def _class_has_virtual_methods(self, cls):
"""return True if cls has at least one virtual method, else False"""
@@ -1575,7 +1575,7 @@ pybindgen.settings.error_handler = ErrorHandler()
and str(cpp_type.base) == 'std::ostream')
def _scan_class_operators(self, cls, class_wrapper, pygen_sink):
def _handle_operator(op, argument_types):
#print >> sys.stderr, "<<<<<OP>>>>> (OP %s in class %s) : %s --> %s" % \
# (op.symbol, cls, [str(x) for x in argument_types], op.return_type)
@@ -1669,7 +1669,7 @@ pybindgen.settings.error_handler = ErrorHandler()
% len(argument_types),
WrapperWarning, op.location.file_name, op.location.line)
return
for op in self.module_namespace.free_operators(function=self.location_filter,
@@ -1678,7 +1678,7 @@ pybindgen.settings.error_handler = ErrorHandler()
_handle_operator(op, [arg.type for arg in op.arguments])
for op in cls.member_operators(function=self.location_filter,
allow_empty=True,
allow_empty=True,
recursive=True):
if op.access_type != 'public':
continue
@@ -1720,7 +1720,7 @@ pybindgen.settings.error_handler = ErrorHandler()
class_wrapper.memory_policy.decref_method,
class_wrapper.memory_policy.peekref_method,
])
for member in cls.get_members():
if member.name in methods_to_ignore:
continue
@@ -1773,8 +1773,8 @@ pybindgen.settings.error_handler = ErrorHandler()
argument_specs.append(self.type_registry.lookup_parameter(arg.type, arg.name,
parameter_annotations.get(arg.name, {}),
arg.default_value))
if pure_virtual and not class_wrapper.allow_subclassing:
class_wrapper.set_cannot_be_constructed("pure virtual method and subclassing disabled")
@@ -1889,7 +1889,7 @@ pybindgen.settings.error_handler = ErrorHandler()
else: # no exception, add method succeeded
for hook in self._post_scan_hooks:
hook(self, member, method_wrapper)
## ------------ constructor --------------------
elif isinstance(member, calldef.constructor_t):
@@ -1985,7 +1985,7 @@ pybindgen.settings.error_handler = ErrorHandler()
pygen_sink.writeln("cls.add_instance_attribute(%r, %s, is_const=%r)" %
(member.name, _pygen_retval(*return_type_spec),
type_traits.is_const(member.type)))
## convert the return value
try:
return_type = ReturnValue.new(*return_type_spec[0], **return_type_spec[1])
@@ -2011,7 +2011,7 @@ pybindgen.settings.error_handler = ErrorHandler()
if type_traits.has_trivial_constructor(cls):
class_wrapper.add_constructor([])
pygen_sink.writeln("cls.add_constructor([])")
if not have_copy_constructor:
try: # pygccxml > 0.9
has_copy_constructor = type_traits.has_copy_constructor(cls)
@@ -2020,7 +2020,7 @@ pybindgen.settings.error_handler = ErrorHandler()
if has_copy_constructor:
class_wrapper.add_copy_constructor()
pygen_sink.writeln("cls.add_copy_constructor()")
def _get_calldef_exceptions(self, calldef):
retval = []
@@ -2052,10 +2052,8 @@ pybindgen.settings.error_handler = ErrorHandler()
if isinstance(exc, CppException):
retval.append(exc)
else:
warnings.warn_explicit("Thrown exception '%s' was not previously detected as an exception class."
" PyBindGen bug?"
% (normalize_name(decl.partial_decl_string)),
WrapperWarning, calldef.location.file_name, calldef.location.line)
raise ValueError("Thrown exception '%s' is not a CppException object: %r"
% (normalize_name(name), exc))
return retval
def scan_functions(self):
@@ -2081,7 +2079,7 @@ pybindgen.settings.error_handler = ErrorHandler()
% (section.local_customizations_module, section.local_customizations_module))
pygen_sink.writeln("root_module.end_section(%r)" % section.name)
self._scan_namespace_functions(self.module, self.module_namespace)
def _scan_namespace_functions(self, module, module_namespace):
root_module = module.get_root()
@@ -2164,7 +2162,7 @@ pybindgen.settings.error_handler = ErrorHandler()
if argnum == 0 and as_method is not None \
and isinstance(arg.type, cpptypes.pointer_t):
annotations.setdefault("transfer_ownership", "false")
spec = self.type_registry.lookup_parameter(arg.type, arg.name,
annotations,
default_value=arg.default_value)
@@ -2237,7 +2235,7 @@ pybindgen.settings.error_handler = ErrorHandler()
if instance_types == template_parameters:
kwargs['custom_name'] = name
break
if alt_name:
kwargs['custom_name'] = alt_name
@@ -2275,7 +2273,7 @@ pybindgen.settings.error_handler = ErrorHandler()
def decl_cmp(a, b):
return cmp(a.decl_string, b.decl_string)
nested_namespaces.sort(decl_cmp)
for nested_namespace in nested_namespaces:
nested_module = module.get_submodule(nested_namespace.name)
nested_module_pygen_func = "register_functions_" + "_".join(nested_module.get_namespace_path())
@@ -2287,7 +2285,7 @@ pybindgen.settings.error_handler = ErrorHandler()
pygen_sink.writeln("return")
pygen_sink.unindent()
pygen_sink.writeln()
nested_namespaces = []
for nested_namespace in module_namespace.namespaces(allow_empty=True, recursive=False):
if nested_namespace.name.startswith('__'):
+6
View File
@@ -490,6 +490,12 @@ ClassThatThrows::ClassThatThrows (double x) throw (DomainError)
}
}
int
ClassThatThrows::throw_out_of_range() throw (std::out_of_range)
{
throw std::out_of_range("imaginary index out of range");
}
int
ClassThatThrows::throw_error () const throw (std::exception)
{
+36 -33
View File
@@ -168,7 +168,7 @@ public:
virtual int get_int (int x) {
return x;
}
static int instance_count;
virtual ~Zbr () {
@@ -190,7 +190,7 @@ class Foobar
{
Foobar (const Foobar &);
Foobar& operator= (const Foobar &);
public:
static int instance_count;
@@ -205,7 +205,7 @@ class SomeObject
{
public:
std::string m_prefix;
enum {
TYPE_FOO,
TYPE_BAR,
@@ -372,7 +372,7 @@ public:
const Foo * get_foo_shared_ptr () {
return m_foo_shared_ptr;
}
// -#- @return(caller_owns_return=true) -#-
Foo * get_foo_ptr () {
Foo *foo = m_foo_ptr;
@@ -520,7 +520,7 @@ namespace xpto
std::string get_foo_datum(FooXpto const &foo);
struct XptoClass
struct XptoClass
{
SomeClass* GetSomeClass()
// -#- @return(caller_owns_return=true) -#-
@@ -764,7 +764,7 @@ namespace TopNs
};
namespace PrefixBottomNs {
class PrefixInner : public OuterBase
class PrefixInner : public OuterBase
{
public:
PrefixInner () {}
@@ -814,7 +814,7 @@ int set_simple_list (SimpleStructList list);
class TestContainer
{
public:
std::set<float> m_floatSet;
TestContainer () : m_vec (NULL) {
@@ -852,7 +852,7 @@ private:
SimpleStructMap m_simpleMap;
std::vector<std::string> *m_vec;
};
std::map<std::string, int> get_map ();
@@ -981,7 +981,7 @@ private:
// disable the copy constructor
ManipulatedObject (const ManipulatedObject &ctor_arg);
public:
ManipulatedObject () : m_value (0) {}
void SetValue (int value) { m_value = value; }
@@ -992,7 +992,7 @@ public:
class ReferenceManipulator
{
ManipulatedObject m_obj;
public:
ReferenceManipulator () {}
virtual ~ReferenceManipulator () {}
@@ -1011,13 +1011,13 @@ public:
class VectorLike
{
std::vector<double> m_vec;
public:
VectorLike ()
VectorLike ()
{
}
// -#- name=__len__ -#-
std::vector<double>::size_type get_len () const
std::vector<double>::size_type get_len () const
{
return m_vec.size ();
}
@@ -1059,8 +1059,8 @@ public:
{
std::copy(m_vec.begin(), m_vec.begin() + n0, std::back_inserter(m_vec));
}
}
else
}
else
{
*this = VectorLike();
}
@@ -1080,7 +1080,7 @@ public:
{
const int n = this->get_len();
index = (index < 0 ? (n + 1 + index) : index);
try
try
{
return m_vec.at(index);
}
@@ -1097,7 +1097,7 @@ public:
index1 = (index1 < 0 ? (n + 1 + index1) : index1);
index2 = (index2 < 0 ? (n + 1 + index2) : index2);
if (index1 >= n or index2 > n) return -1;
for (int i = index1; i < index2; ++i)
for (int i = index1; i < index2; ++i)
{
if (this->set_item(i, values.get_item(i - index1)) != 0) return -1;
}
@@ -1110,7 +1110,7 @@ public:
const int n = this->get_len();
index1 = (index1 < 0 ? (n + 1 + index1) : index1);
index2 = (index2 < 0 ? (n + 1 + index2) : index2);
for (int i = index1; i < index2; ++i)
for (int i = index1; i < index2; ++i)
{
result.m_vec.push_back(this->get_item(i));
}
@@ -1139,9 +1139,9 @@ public:
class VectorLike2
{
std::vector<double> m_vec;
public:
VectorLike2 ()
VectorLike2 ()
{
}
@@ -1159,7 +1159,7 @@ public:
class MapLike
{
std::map<int, double> m_map;
public:
MapLike () {}
@@ -1180,7 +1180,7 @@ struct Error
struct DomainError : public Error
// -#- exception -#-
{
};
};
// returns 1/x, raises DomainError if x == 0
@@ -1188,22 +1188,25 @@ double my_inverse_func (double x) throw (DomainError);
double my_inverse_func2 (double x) throw (std::exception);
// the following function throws an exception but forgets to declare it
// -#- throw=std::exception -#-
// -#- throw=std::exception -#-
double my_inverse_func3 (double x);
class ClassThatThrows
{
public:
ClassThatThrows (double x) throw (DomainError);
// returns 1/x, raises DomainError if x == 0
double my_inverse_method (double x) throw (DomainError);
double my_inverse_method2 (double x) throw (std::exception);
// the following method throws an exception but forgets to declare it
// -#- throw=std::exception -#-
// -#- throw=std::exception -#-
double my_inverse_method3 (double x);
// -#- throw=std::out_of_range -#-
int throw_out_of_range() throw (std::out_of_range);
virtual int throw_error () const throw (std::exception);
virtual ~ClassThatThrows () {}
@@ -1228,7 +1231,7 @@ class property
{
private:
ValueType m_value;
public:
property<ValueType> ()
{
@@ -1271,13 +1274,13 @@ public:
// -#- @return(reference_existing_object=true) -#-
const Foobar* getFoobarInternalPtr () { return &m_foobar; }
// -#- @return(reference_existing_object=true) -#-
Foobar& getFoobarInternalRef () { return m_foobar; }
// -#- @return(return_internal_reference=true) -#-
Foobar* getFoobarInternalPtr2 () { return &m_foobar; }
// -#- @return(return_internal_reference=true) -#-
Foobar& getFoobarInternalRef2 () { return m_foobar; }
@@ -1289,7 +1292,7 @@ class MIRoot
{
public:
MIRoot () {}
int root_method () const { return -1; }
int root_method () const { return -1; }
};
@@ -1298,7 +1301,7 @@ class MIBase1 : public virtual MIRoot
int m_value;
public:
MIBase1 () : m_value (1) {}
int base1_method () const { return m_value; }
int base1_method () const { return m_value; }
};
class MIBase2 : public virtual MIRoot
@@ -1306,16 +1309,16 @@ class MIBase2 : public virtual MIRoot
int m_value;
public:
MIBase2 () : m_value (2) {}
int base2_method () const { return m_value; }
int base2_method () const { return m_value; }
};
class MIMixed : public MIBase1, public MIBase2
{
public:
MIMixed () {}
int mixed_method () const { return 3; }
int mixed_method () const { return 3; }
};
Tupl my_throwing_func () throw (std::exception);
+1
View File
@@ -41,6 +41,7 @@ def my_module_gen():
module_parser.parse_init([sys.argv[1]], includes=['"foo.h"'], pygen_sink=pygen, pygen_classifier=MyPygenClassifier(),
gccxml_options=gccxml_options)
module = module_parser.module
foomodulegen_common.customize_module_pre(module)
module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
module_parser.scan_types()
module_parser.scan_methods()
+3 -1
View File
@@ -28,6 +28,8 @@ def my_module_gen():
module_parser.parse_init([sys.argv[1]], includes=['"foo.h"'], pygen_sink=FileCodeSink(pygen_file),
gccxml_options=gccxml_options)
module = module_parser.module
foomodulegen_common.customize_module_pre(module)
module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
module_parser.scan_types()
module_parser.scan_methods()
@@ -58,7 +60,7 @@ def main():
print("** running under profiler", file=sys.stderr)
profile.run('my_module_gen()', 'foomodulegen-auto.pstat')
else:
my_module_gen()
my_module_gen()
if __name__ == '__main__':
main()
+19 -16
View File
@@ -22,12 +22,13 @@ import foomodulegen_common
def my_module_gen(out_file):
mod = Module('foo')
foomodulegen_common.customize_module_pre(mod)
mod.add_include ('"foo.h"')
mod.add_function('TypeNameGet',
'std::string',
[],
mod.add_function('TypeNameGet',
'std::string',
[],
custom_name='IntegerTypeNameGet', template_parameters=['int'])
Foo = mod.add_class('Foo', automatic_type_narrowing=True)
@@ -91,7 +92,7 @@ int %s::custom_method_added_by_a_hook(int x)
is_virtual=True)
Zbr.add_static_attribute('instance_count', ReturnValue.new('int'))
Zbr.add_method('get_value', ReturnValue.new('int'), [Parameter.new('int*', 'x', direction=Parameter.DIRECTION_OUT)])
mod.add_function('store_zbr', None,
[Parameter.new('Zbr*', 'zbr', transfer_ownership=True)])
mod.add_function('invoke_zbr', ReturnValue.new('int'), [Parameter.new('int', 'x')])
@@ -124,7 +125,7 @@ int %s::custom_method_added_by_a_hook(int x)
SomeObject.add_static_attribute('staticData', ReturnValue.new('std::string'))
SomeObject.add_static_attribute('instance_count', ReturnValue.new('int'))
SomeObject.add_method('add_prefix', ReturnValue.new('int'),
[Parameter.new('std::string&', 'message',
direction=Parameter.DIRECTION_INOUT)])
@@ -299,19 +300,19 @@ int %s::custom_method_added_by_a_hook(int x)
xpto.add_typedef(Foo, 'FooXpto')
xpto.add_function('get_foo_datum', 'std::string', [Parameter.new('const xpto::FooXpto&', 'foo')])
typehandlers.add_type_alias('uint32_t', 'xpto::FlowId')
typehandlers.add_type_alias('uint32_t', 'xpto::FlowId')
xpto.add_function('get_flow_id', 'xpto::FlowId', [Parameter.new('xpto::FlowId', 'flowId')])
# bug #798383
XptoClass = xpto.add_struct('XptoClass')
XptoClass.add_method("GetSomeClass", retval("xpto::SomeClass*", caller_owns_return=True), [])
## ---- some implicity conversion APIs
mod.add_function('function_that_takes_foo', ReturnValue.new('void'),
[Parameter.new('Foo', 'foo')])
mod.add_function('function_that_returns_foo', ReturnValue.new('Foo'), [])
cls = mod.add_class('ClassThatTakesFoo')
cls.add_constructor([Parameter.new('Foo', 'foo')])
cls.add_method('get_foo', ReturnValue.new('Foo'), [])
@@ -376,7 +377,7 @@ int %s::custom_method_added_by_a_hook(int x)
ReturnValue.new('int'),
[Parameter.new('int', 'x')],
is_virtual=True, is_pure_virtual=True, visibility='protected', is_const=True)
AbstractBaseClass2.add_method('private_virtual',
ReturnValue.new('int'), [Parameter.new('int', 'x')],
is_virtual=True, is_pure_virtual=True, visibility='private', is_const=True)
@@ -417,7 +418,7 @@ int %s::custom_method_added_by_a_hook(int x)
inner = bottom_ns.add_class('PrefixInner',parent=outer_base)
inner.add_constructor([])
inner.add_method('Do', 'void', [])
Socket = mod.add_class('Socket', allow_subclassing=True)
Socket.add_constructor([])
@@ -438,7 +439,7 @@ int %s::custom_method_added_by_a_hook(int x)
mod.add_function('set_simple_list', 'int', [Parameter.new('SimpleStructList', 'list')])
mod.add_container('std::set<float>', 'float', 'set')
TestContainer = mod.add_class('TestContainer', allow_subclassing=True)
TestContainer.add_constructor([])
TestContainer.add_instance_attribute('m_floatSet', 'std::set<float>')
@@ -518,8 +519,8 @@ int %s::custom_method_added_by_a_hook(int x)
VectorLike.add_method('set_item', 'int', [Parameter.new('int', 'index'), Parameter.new('double', 'value')],
custom_name='__setitem__')
VectorLike.add_method('get_item', 'double', [Parameter.new('int', 'index')], custom_name='__getitem__')
VectorLike.add_method('set_slice', 'int', [Parameter.new('int', 'index1'),
Parameter.new('int', 'index2'),
VectorLike.add_method('set_slice', 'int', [Parameter.new('int', 'index1'),
Parameter.new('int', 'index2'),
Parameter.new('VectorLike', 'values')], custom_name='__setslice__')
VectorLike.add_method('get_slice', 'VectorLike', [Parameter.new('int', 'index1'),
Parameter.new('int', 'index2')], custom_name='__getslice__')
@@ -556,7 +557,9 @@ int %s::custom_method_added_by_a_hook(int x)
ClassThatThrows.add_method('my_inverse_method3', 'double', [Parameter.new('double', 'x')],
throw=[std_exception])
ClassThatThrows.add_method('throw_error', 'int', [], throw=[std_exception], is_const=True, is_virtual=True)
ClassThatThrows.add_method('throw_error', 'int', [], throw=[mod["out_of_range"]], is_const=True, is_virtual=True)
ClassThatThrows.add_method('throw_out_of_range', 'int', [], throw=[mod["out_of_range"]])
# https://bugs.launchpad.net/pybindgen/+bug/450255
ProtectedConstructor = mod.add_class('ProtectedConstructor')
@@ -582,7 +585,7 @@ int %s::custom_method_added_by_a_hook(int x)
MIRoot = mod.add_class('MIRoot')
MIRoot.add_constructor([])
MIRoot.add_method('root_method', 'int', [], is_const=True)
MIBase1 = mod.add_class('MIBase1', parent=MIRoot)
MIBase1.add_constructor([])
MIBase1.add_method('base1_method', 'int', [], is_const=True)
@@ -609,7 +612,7 @@ int %s::custom_method_added_by_a_hook(int x)
mod.add_function("test_args_kwargs", "int", [param("const char *", "args"), param("const char *", "kwargs")])
#### --- error handler ---
class MyErrorHandler(pybindgen.settings.ErrorHandler):
def __init__(self):
+1
View File
@@ -24,6 +24,7 @@ def my_module_gen():
out = FileCodeSink(sys.stdout)
root_module = foomodulegen_generated.module_init()
root_module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
foomodulegen_common.customize_module_pre(root_module)
## this is a very special case when we want to change the name of
## the python module to allow parallel testing of the same basic
+1
View File
@@ -52,6 +52,7 @@ def my_module_gen():
out = MyMultiSectionFactory(sys.argv[1])
root_module = foomodulegen_split.module_init()
root_module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
foomodulegen_common.customize_module_pre(root_module)
foomodulegen_split.register_types(root_module)
foomodulegen_split.register_methods(root_module)
+4
View File
@@ -52,6 +52,9 @@ typehandlers.return_type_matcher.register_transformation(transf)
typehandlers.param_type_matcher.register_transformation(transf)
del transf
def customize_module_pre(module):
standard_error = module.add_exception('out_of_range', foreign_cpp_namespace='std',
custom_name='IndexError', is_standard_error=True)
def customize_module(module):
@@ -138,3 +141,4 @@ _wrap_PyBar_Hooray_lenx(PyBar *PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject
#module.add_include('<stdio.h>')
#module.add_class(name="FILE", foreign_cpp_namespace="", import_from_module="__builtin__ named file")
#module.add_enum("reg_errcode_t", ["REG_NOERROR", "REG_NOMATCH"], import_from_module="__builtin__")
+4
View File
@@ -1272,6 +1272,10 @@ class TestFoo(unittest.TestCase):
self.assertEqual(y, 0.5)
self.assertRaises(foo.DomainError, c.my_inverse_method, 0)
def test_python_exception(self):
c = foo.ClassThatThrows(6)
self.assertRaises(IndexError, c.throw_out_of_range)
def test_constructor_exceptions(self):
c = foo.ClassThatThrows(1)
self.assertRaises(foo.DomainError, foo.ClassThatThrows, 0)