Revision: 963
http://svn.sourceforge.net/pygccxml/?rev=963&view=rev
Author: roman_yakovenko
Date: 2007-03-30 13:43:14 -0700 (Fri, 30 Mar 2007)
Log Message:
-----------
implementing better exception handling
Modified Paths:
--------------
pyplusplus_dev/docs/troubleshooting_guide/exceptions/exceptions.cpp
pyplusplus_dev/docs/troubleshooting_guide/exceptions/test.py
Modified: pyplusplus_dev/docs/troubleshooting_guide/exceptions/exceptions.cpp
===================================================================
--- pyplusplus_dev/docs/troubleshooting_guide/exceptions/exceptions.cpp 2007-03-30 16:59:57 UTC (rev 962)
+++ pyplusplus_dev/docs/troubleshooting_guide/exceptions/exceptions.cpp 2007-03-30 20:43:14 UTC (rev 963)
@@ -7,59 +7,113 @@
* from Python built-in exceptions
*
**/
-
-class zero_division_error : public std::exception{
+class application_error : public std::exception{
public:
- zero_division_error()
+ application_error()
: std::exception(), m_msg()
{}
- zero_division_error( const std::string& msg )
+ application_error( const std::string& msg )
: std::exception(), m_msg( msg )
{}
- zero_division_error( const zero_division_error& other )
+ application_error( const application_error& other )
: std::exception(other), m_msg( other.m_msg )
{}
const std::string& message() const
{ return m_msg; }
- virtual ~zero_division_error() throw(){}
+ virtual ~application_error() throw(){}
+
+ std::string application_name() const
+ { return "my_exceptions module"; }
private:
const std::string m_msg;
};
-double devide( double x, int y ){
- if( !y ){
- throw zero_division_error( "unable to devide by 0( zero )" );
+void check_preconditions( bool raise_error ){
+ if( raise_error ){
+ throw application_error( "xyz" );
}
- return x/y;
}
+std::string get_application_name( const application_error& err ){
+ return err.application_name();
+}
+
namespace bpl = boost::python;
-void translate( const zero_division_error& err ){
- bpl::object this_module( bpl::handle<>( bpl::borrowed(PyImport_AddModule("my_exceptions"))));
- bpl::object zde_class = this_module.attr("zero_division_error");
- bpl::object pyerr = zde_class( err );
- PyErr_SetObject( zde_class.ptr(), bpl::incref( pyerr.ptr() ) );
-}
+struct exception_translator{
+
+ exception_translator(){
+ bpl::converter::registry::push_back( &exception_translator::convertible
+ , &exception_translator::construct
+ , bpl::type_id<application_error>() );
+
+ bpl::register_exception_translator<application_error>(&exception_translator::translate);
+ }
+
+ static void
+ translate( const application_error& err ){
+ bpl::object this_module( bpl::handle<>( bpl::borrowed(PyImport_AddModule("my_exceptions"))));
+ bpl::object app_exc_class = this_module.attr("application_error");
+ bpl::object pyerr = app_exc_class( err );
+ PyErr_SetObject( app_exc_class.ptr(), bpl::incref( pyerr.ptr() ) );
+ }
+ //Sometimes, exceptions should be passed back to the library.
+ static void*
+ convertible(PyObject* py_obj){
+ if( 1 != PyObject_IsInstance( py_obj, PyExc_Exception ) ){
+ return 0;
+ }
+
+ if( !PyObject_HasAttrString( py_obj, "_pimpl" ) ){
+ return 0;
+ }
+
+ bpl::object pyerr( bpl::handle<>( bpl::borrowed( py_obj ) ) );
+ bpl::object pimpl = bpl::getattr( pyerr, "_pimpl" );
+ bpl::extract<application_error> type_checker( pimpl );
+ if( !type_checker.check() ){
+ return 0;
+ }
+ return py_obj;
+ }
+
+ static void
+ construct( PyObject* py_obj, bpl::converter::rvalue_from_python_stage1_data* data){
+ typedef bpl::converter::rvalue_from_python_storage<application_error> storage_t;
+
+ bpl::object pyerr( bpl::handle<>( bpl::borrowed( py_obj ) ) );
+ bpl::object pimpl = bpl::getattr( pyerr, "_pimpl" );
+
+ storage_t* the_storage = reinterpret_cast<storage_t*>( data );
+ void* memory_chunk = the_storage->storage.bytes;
+ application_error* cpp_err
+ = new (memory_chunk) application_error( bpl::extract<application_error>(pimpl) );
+
+ data->convertible = memory_chunk;
+ }
+
+};
+
BOOST_PYTHON_MODULE( my_exceptions ){
typedef bpl::return_value_policy< bpl::copy_const_reference > return_copy_const_ref;
- bpl::class_< zero_division_error >( "_zero_division_error_" )
+ bpl::class_< application_error >( "_application_error_" )
.def( bpl::init<const std::string&>() )
- .def( bpl::init<const zero_division_error&>() )
- .def( "message", &zero_division_error::message, return_copy_const_ref() )
- .def( "__str__", &zero_division_error::message, return_copy_const_ref() );
+ .def( bpl::init<const application_error&>() )
+ .def( "message", &application_error::message, return_copy_const_ref() )
+ .def( "__str__", &application_error::message, return_copy_const_ref() );
- bpl::register_exception_translator<zero_division_error>(&translate);
+ exception_translator();
- bpl::def( "devide", &::devide );
+ bpl::def( "check_preconditions", &::check_preconditions );
+ bpl::def( "get_application_name", &::get_application_name );
}
Modified: pyplusplus_dev/docs/troubleshooting_guide/exceptions/test.py
===================================================================
--- pyplusplus_dev/docs/troubleshooting_guide/exceptions/test.py 2007-03-30 16:59:57 UTC (rev 962)
+++ pyplusplus_dev/docs/troubleshooting_guide/exceptions/test.py 2007-03-30 20:43:14 UTC (rev 963)
@@ -1,27 +1,43 @@
import unittest
import my_exceptions
-print dir( my_exceptions._zero_division_error_.__class__ )
-
-class zero_division_error(my_exceptions._zero_division_error_, ZeroDivisionError ):
+class application_error(Exception):
+ def __init__( self, app_error ):
+ Exception.__init__( self )
+ self._pimpl = app_error
+
+ def __str__( self ):
+ return self._pimpl.message()
- def __init__( self, msg ):
- my_exceptions._zero_division_error_.__init__( self, msg )
-
-my_exceptions.zero_division_error = zero_division_error
+my_exceptions.application_error = application_error
class tester_t( unittest.TestCase ):
def __init__( self, *args ):
unittest.TestCase.__init__( self, *args )
- def test( self ):
- print my_exceptions.devide( 1, 1 )
- self.failUnless( 1 == my_exceptions.devide( 1, 1 ) )
+ def test_function_call( self ):
+ my_exceptions.check_preconditions( False )
+
+ def test_concrete_error( self ):
try:
- my_exceptions.devide( 1, 0 )
- except zero_division_error, err:
- print err.__class__.__name__, str(err)
-
+ my_exceptions.check_preconditions( True )
+ except my_exceptions.application_error, err:
+ self.failUnless( str( err ) == "xyz" )
+
+ def test_base_error( self ):
+ try:
+ my_exceptions.check_preconditions( True )
+ except Exception, err:
+ self.failUnless( str( err ) == "xyz" )
+
+ def test_converter( self ):
+ try:
+ my_exceptions.check_preconditions( True )
+ except my_exceptions.application_error, err:
+ app_name = my_exceptions.get_application_name( err )
+ self.failUnless( "my_exceptions module" == app_name )
+
+
def create_suite():
suite = unittest.TestSuite()
suite.addTest( unittest.makeSuite(tester_t))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|