how to add_exception with inheritance

Asked by Owen Kelly

Hello all,

I'm trying to understand the correct syntax for exceptions that inherit from other exceptions.
Do you think that this pybindgen code

    std_exception=module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
    module.add_exception('general', foreign_cpp_namespace='gdf::exception', message_rvalue='%(EXC)s.what()', parent=std_exception)

is a proper description for this header?

------------Exceptions.h----------------
#include <exception>
#include <stdexcept>
namespace gdf {
    namespace exception
    {
        class general : public std::exception
        {
------------ ... ---------------

With this code, I am getting errors as follows:

>>> looking at class gdf::exception::general [class]
C:\libgdf\include\GDF\Exceptions.h:34: ModuleParserWarning: Class ::gdf::exception::general ignored because it uses a base class (::std::exception) which is not declared.
  {

Any thoughts on whether that is related or unrelated to add_exception statements?

Thanks and regards,

Owen

Question information

Language:
English Edit question
Status:
Solved
For:
PyBindGen Edit question
Assignee:
No assignee Edit question
Solved by:
Owen Kelly
Solved:
Last query:
Last reply:
Revision history for this message
Gustavo Carneiro (gjc) said :
#1

Sorry, the problem is that gccxmlparser is like a layer on top of pybindgen, and has its own separate type registry.

If parser is the ModuleParser object, you should register any manually defined classes with it, thus:

            parser.type_registry.class_registered(class_wrapper)

where class_wrapper is the object returned by module.add_exception(...)

Revision history for this message
Owen Kelly (oekelly) said :
#2

Thank you for that suggestion.

Changing my code to

    std_exception=module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
    general_exception=module.add_exception('general', foreign_cpp_namespace='gdf::exception', message_rvalue='%(EXC)s.what()', parent=std_exception)
    module_parser.type_registry.class_registered(std_exception)
    module_parser.type_registry.class_registered(general_exception)

The error (on the first pass of workflow 3) becomes

Traceback (most recent call last):
  File "..\exc_module-gen.py", line 73, in <module>
    my_module_gen()
  File "..\exc_module-gen.py", line 66, in my_module_gen
    module_parser.scan_methods()
  File "C:\Python26\lib\site-packages\pybindgen\gccxmlparser.py", line 791, in scan_methods
    if isinstance(class_wrapper.gccxml_definition, class_declaration_t):
AttributeError: 'CppException' object has no attribute 'gccxml_definition'

Which class do you think gccxml has not seen, the base, or the derived? Hmm...
The error is similar regardless of which of the two class_registered calls are used above (or both, as shown).

Owen

-------- full traceback -------------------------
C:\Python26\lib\site-packages\pygccxml\parser\declarations_cache.py:8: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
INFO Parsing source file "C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h" ...
INFO gccxml cmd: ""C:\Program Files (x86)\gccxml 0.9\bin\gccxml.exe" -I"." -I"C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include" -I"C:\Users\Owen\Documents\biopeak\sand2\libgdf\boost_1_50_0" -I"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include" -I"C:\Python26\include" -D"_HAS_TR1=0" "C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h" -fxml="c:\users\owen\appdata\local\temp\tmpssdcwg.xml""
INFO GCCXML version - 0.9
C:\Python26\lib\site-packages\pygccxml\parser\scanner.py:337: UserWarning: unable to find out array size from expression ""
  warnings.warn( msg )
>>> looking at class gdf::exception::bad_type_assigned_to_channel [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:66: ModuleParserWarning: Class ::gdf::exception::bad_type_assigned_to_channel ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::corrupt_recordbuffer [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:115: ModuleParserWarning: Class ::gdf::exception::corrupt_recordbuffer ignored because it uses a base class (::std::runtime_error) which is not declared.
  {
>>> looking at class gdf::exception::empty_container [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:59: ModuleParserWarning: Class ::gdf::exception::empty_container ignored because it uses a base class (::std::runtime_error) which is not declared.
  {
>>> looking at class gdf::exception::feature_not_implemented [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:122: ModuleParserWarning: Class ::gdf::exception::feature_not_implemented ignored because it uses a base class (::std::logic_error) which is not declared.
  {
>>> looking at class gdf::exception::file_exists [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:143: ModuleParserWarning: Class ::gdf::exception::file_exists ignored because it uses a base class (::std::invalid_argument) which is not declared.
  {
>>> looking at class gdf::exception::file_exists_not [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:150: ModuleParserWarning: Class ::gdf::exception::file_exists_not ignored because it uses a base class (::std::invalid_argument) which is not declared.
  {
>>> looking at class gdf::exception::file_not_open [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:129: ModuleParserWarning: Class ::gdf::exception::file_not_open ignored because it uses a base class (::std::invalid_argument) which is not declared.
  {
>>> looking at class gdf::exception::file_open [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:136: ModuleParserWarning: Class ::gdf::exception::file_open ignored because it uses a base class (::std::invalid_argument) which is not declared.
  {
>>> looking at class gdf::exception::general [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:34: ModuleParserWarning: Class ::gdf::exception::general ignored because it uses a base class (::std::exception) which is not declared.
  {
>>> looking at class gdf::exception::header_issues [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:200: ModuleParserWarning: Class ::gdf::exception::header_issues ignored because it uses a base class (::std::exception) which is not declared.
  {
>>> looking at class gdf::exception::illegal_eventmode_change [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:164: ModuleParserWarning: Class ::gdf::exception::illegal_eventmode_change ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::incompatible_gdf_version [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:185: ModuleParserWarning: Class ::gdf::exception::incompatible_gdf_version ignored because it uses a base class (::gdf::exception::general) which is not declared.
  {
>>> looking at class gdf::exception::index_out_of_range [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:45: ModuleParserWarning: Class ::gdf::exception::index_out_of_range ignored because it uses a base class (::std::range_error) which is not declared.
  {
>>> looking at class gdf::exception::invalid_eventmode [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:171: ModuleParserWarning: Class ::gdf::exception::invalid_eventmode ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::invalid_operation [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:52: ModuleParserWarning: Class ::gdf::exception::invalid_operation ignored because it uses a base class (::std::runtime_error) which is not declared.
  {
>>> looking at class gdf::exception::invalid_type_id [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:73: ModuleParserWarning: Class ::gdf::exception::invalid_type_id ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::mismatch_channel_number [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:108: ModuleParserWarning: Class ::gdf::exception::mismatch_channel_number ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::mixed_types_not_allowed [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:80: ModuleParserWarning: Class ::gdf::exception::mixed_types_not_allowed ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::nonexistent_channel_access [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:101: ModuleParserWarning: Class ::gdf::exception::nonexistent_channel_access ignored because it uses a base class (::std::out_of_range) which is not declared.
  {
>>> looking at class gdf::exception::serialization_error [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:157: ModuleParserWarning: Class ::gdf::exception::serialization_error ignored because it uses a base class (::std::logic_error) which is not declared.
  {
>>> looking at class gdf::exception::signal_exists [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:94: ModuleParserWarning: Class ::gdf::exception::signal_exists ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::signal_exists_not [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:87: ModuleParserWarning: Class ::gdf::exception::signal_exists_not ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class gdf::exception::wrong_eventmode [class]
C:\Users\Owen\Documents\biopeak\sand2\BP09_DFC\trunk\SC0009\libgdf\libgdf\include\GDF\Exceptions.h:178: ModuleParserWarning: Class ::gdf::exception::wrong_eventmode ignored because it uses a base class (::std::domain_error) which is not declared.
  {
>>> looking at class std::bad_alloc [class]
>>> class std::bad_alloc [class] is being postponed (waiting for base class std::exception [class] to be registered first)
>>> looking at class std::bad_exception [class]
>>> class std::bad_exception [class] is being postponed (waiting for base class std::exception [class] to be registered first)
>>> looking at class std::domain_error [class]
>>> class std::domain_error [class] is being postponed (waiting for base class std::logic_error [class] to be registered first)
>>> looking at class std::exception [class]
>>> looking at class std::invalid_argument [class]
>>> class std::invalid_argument [class] is being postponed (waiting for base class std::logic_error [class] to be registered first)
>>> looking at class std::length_error [class]
>>> class std::length_error [class] is being postponed (waiting for base class std::logic_error [class] to be registered first)
>>> looking at class std::logic_error [class]
>>> looking at class std::out_of_range [class]
>>> looking at class std::overflow_error [class]
>>> class std::overflow_error [class] is being postponed (waiting for base class std::runtime_error [class] to be registered first)
>>> looking at class std::range_error [class]
>>> class std::range_error [class] is being postponed (waiting for base class std::runtime_error [class] to be registered first)
>>> looking at class std::runtime_error [class]
>>> looking at class std::underflow_error [class]
>>> looking at class std::bad_alloc [class]
>>> looking at class std::bad_exception [class]
>>> looking at class std::domain_error [class]
>>> looking at class std::invalid_argument [class]
>>> looking at class std::length_error [class]
>>> looking at class std::overflow_error [class]
>>> looking at class std::range_error [class]
Traceback (most recent call last):
  File "..\exc_module-gen.py", line 73, in <module>
    my_module_gen()
  File "..\exc_module-gen.py", line 66, in my_module_gen
    module_parser.scan_methods()
  File "C:\Python26\lib\site-packages\pybindgen\gccxmlparser.py", line 791, in scan_methods
    if isinstance(class_wrapper.gccxml_definition, class_declaration_t):
AttributeError: 'CppException' object has no attribute 'gccxml_definition'

Revision history for this message
Gustavo Carneiro (gjc) said :
#3

*sigh* sorry, I tried to help, but I didn't fully check it. I guess pybindgen would need a bit of hacking to allow manually registered classes to be used as base classes for automatically scanned ones. My advice is to manually register the whole hierarchy of C++ exception classes, and forget about the parser.type_registry.class_registered. Sorry I can't help much at this point.

Revision history for this message
Owen Kelly (oekelly) said :
#4

Hi Gustavo,

Your information is a big help. Please help me understand your advice:

By the "whole hierarchy of C++ exceptions", do you mean
<include/stdexcept> + <include/exception> OR
<include/stdexcept> + <include/exception> + <libgdf/Exception.h>?
(Exception.h is all my exceptions that inherit from the standard exception.)

By "manually registered", do you mean using statements like this (and using Workflow 3)? :
    std_exception=module.add_exception('exception', foreign_cpp_namespace='std', message_rvalue='%(EXC)s.what()')
    module.add_exception('general', foreign_cpp_namespace='gdf::exception', message_rvalue='%(EXC)s.what()', parent=std_exception)
Or by "manually", do you mean Workflow 1?

Thanks,

Owen

Revision history for this message
Gustavo Carneiro (gjc) said :
#5

I mean the module.add_exception calls. I thin it should work, though I am not 100% sure, you just have to try...

Revision history for this message
Owen Kelly (oekelly) said :
#6

Hi Gustavo,

I tried a few variations, and the solution seems beyond my current understanding.
So I have reduced the problem to the minimum setup and captured that information in a bug (1044185) that is linked to this Answer.

The problem is not solved, but further discussion should be in bug 1044185, so I will mark this questions as "Problem Solved".

Many thanks for the time you have spent on this issue.

Regards,

Owen