Bug 1368538: Support translating C++ exception into Python's standard exceptions
This commit is contained in:
committed by
Gustavo Carneiro
parent
878dd743f8
commit
c9a9de3371
@@ -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
@@ -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('__'):
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__")
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user