trap exceptions comprehensively in Jython -


this attempt far trap exceptions in jython code. difficult thing, find, trapping exceptions when override method java class: "vigil" decorator below (which tests whether edt/event despatch thread status correct) can find out first line code thrown... can identify method itself. not line.

furthermore, tracing stack frames through python , java stacks beyond me. there seem these layers , layers of "proxy" classes, no doubt inevitable part of jython mechanics. it'd great if cleverer me take interest in question!

nb example of how use "vigil" decorator:

    class columncellrenderer( javax.swing.table.defaulttablecellrenderer ):         @vigil( true ) # means check done thread edt, intercepting python exceptions , java throwables...         def gettablecellrenderercomponent( self, table, value, isselected, hasfocus, row, column):             super_comp = self.super__gettablecellrenderercomponent( table, value, isselected, hasfocus, row, column)             super_comp.foreground = java.awt.color.black             super_comp.font = main_frame_self.m_plain_font             ... 

... , these 3 functions use in attempt trap stuff...

def custom_hook(type_of_e, e, tb ):     """ method catch python-style baseexceptions, using command sys.excepthook = custom_hook. first thing method needs in jython determine whether java  java.lang.throwable or not.  if jthrowable must handled code caters b{uncaught java throwables}.             """     try:          if 'tb' not in locals():             tb = none         logger.error("python custom_hook called...\ntype of e: %s\ne: %s\ntb: %s" % ( unicode( type_of_e ), unicode( e ),                                                                                      unicode( tb ) ))         msg = ''.join( traceback.format_exception(type_of_e, e, tb ))         logger.error( "traceback:\n" + msg )     except baseexception, e:         logger.error( "exception in python custom_hook!:\n%s" % e )         raise e sys.excepthook = custom_hook  class javauncaughtexcepthandler( java.lang.thread.uncaughtexceptionhandler ):     """ java.lang.class catch java throwables thrown app.             """     def uncaughtexception( self, thread, throwable ):         try:             ''' nb getting java stack trace seems produce different trace  throwable.printstacktrace()... why?                          '''             # want single log message             exception_msg = "\n*** uncaught java exception being logged in %s:\n" % __file__             baos = java.io.bytearrayoutputstream()             ps = java.io.printstream(baos)             throwable.printstacktrace( ps )             # remove multiple lines java stack trace message             java_stack_trace_lines = unicode( baos.tostring( "iso-8859-1" )).splitlines()             java_stack_trace_lines = filter( none, java_stack_trace_lines  )             normalised_java_stack_trace = '\n'.join( java_stack_trace_lines )             exception_msg += normalised_java_stack_trace + '\n'             python_traceback_string = traceback.format_exc()             exception_msg += "python traceback:\n%s" % python_traceback_string             logger.error( exception_msg )         except (baseexception, java.lang.throwable ), e:             logger.error( "*** exception in java exception handler:\ntype %s\n%s" % ( type( e ), unicode( e ) ) )             raise e         # nb printstacktrace causes custom_hook invoked... (but doesn't print anything) java.lang.thread.setdefaultuncaughtexceptionhandler( javauncaughtexcepthandler()  )   def vigil( *args ):     """ decorator 2 functions.   1. check method being run in edt or non-edt thread;  2. catch java throwables otherwise not caught , documented: in particular,  normal java error-trapping in jython seems impossible determine line number @  exception thrown.  @ least records line @ java java.lang.throwable thrown.     """     if len( args ) != 1:         raise exception( "vigil: wrong number of args (should 1, value: none/true/false): %s" % str( args ))     req_edt = args[ 0 ]     if req_edt , type( req_edt ) not bool:         raise exception( "vigil: edt_status wrong type: %s, type %s" % ( req_edt, type( req_edt )) )     def real_decorator( function ):         if not hasattr( function, '__call__' ):             raise exception( "vigil: function %s not have __call__ attr, type %s"                  % ( function, type( function )) )          # nb info decorator location can't got when wrapper called, record @ point         penultimate_frame = traceback.extract_stack()[ -2 ]          decorator_file = penultimate_frame[ 0 ]             decorator_line_no = penultimate_frame[ 1 ]             def wrapper( *args, **kvargs ):             try:                 # todo possible python and/or java stack trace @ point?                 if req_edt , javax.swing.swingutilities.iseventdispatchthread() != req_edt:                     logger.error( "*** vigil: wrong edt value, should %s\nfile %s, line no %s, function: %s\n" %          ( "edt" if req_edt else "non-edt", decorator_file, decorator_line_no, function ))                 return function( *args, **kvargs )             except ( baseexception, java.lang.throwable ), e:                 ''' nb sorts of problems if vigil-protected function throws exception: 1) raising e means short stack trace... 2) if list stack trace elements here line (seemingly inside function  exception occurred) wrong line! 3) python/java stack frames: how hell work??? 4) want single error message logged                                 '''                  msg = "*** exception %s caught vigil in file %s\nin function starting line %d" % ( e, decorator_file, decorator_line_no )                 logger.error( msg )                 frame = inspect.currentframe()                 # following doesn't seem work... why not?                 python_stack_trace = traceback.format_stack(frame)                 python_stack_string = "python stack trace:\n"                 el in python_stack_trace[ : -1 ]:                     python_stack_string += el                 logger.error( python_stack_string )                 if isinstance( e, java.lang.throwable ):                     # nb problems stack trace: although appears show                      # correct java calling pathway, seems line number of every file , method                      # shown being last line, wherever exception raised.                     # possibly try , hold of actual pyxxx objects ... (?)                     java_stack_trace = e.stacktrace                     java_stack_string = "java stack trace:\n"                     el in java_stack_trace:                         java_stack_string += "  %s\n" % unicode( el )                     logger.error( java_stack_string )                     raise e         return wrapper     return real_decorator 

ps of course possible top-and-tail every overridden java method try ... except... where's fun in that? seriously, doing i'm unable find line @ exception thrown...

here's example of decorator used in socket module in jython map java exceptions python exceptions. didn't read vigil decorator closely since it's doing lot of work, i'm putting here in case might help:

def raises_java_exception(method_or_function):     """maps java socket exceptions equivalent python exception.     sets _last_error on socket objects support so_error.     """      @wraps(method_or_function)     def handle_exception(*args, **kwargs):         is_socket = len(args) > 0 , isinstance(args[0], _realsocket)         try:             try:                 return method_or_function(*args, **kwargs)             except java.lang.exception, jlx:                 raise _map_exception(jlx)         except error, e:             if is_socket:                 args[0]._last_error = e[0]             raise         else:             if is_socket:                 args[0]._last_error = 0     return handle_exception 

mostly seeing here dispatching on whether java exception (java.lang.exception) or not. suppose generalized java.lang.throwable, although it's unclear can done in case of java.lang.error in event. nothing corresponding socket errors!

the above decorator in turn uses _map_exception function unwrap java exception. it's quite application specific here can see:

def _map_exception(java_exception):     if isinstance(java_exception, nettychannelexception):         java_exception = java_exception.cause  # unwrap     if isinstance(java_exception, sslexception) or isinstance(java_exception, certificateexception):         cause = java_exception.cause         if cause:             msg = "%s (%s)" % (java_exception.message, cause)         else:             msg = java_exception.message         py_exception = sslerror(ssl_error_ssl, msg)     else:         mapped_exception = _exception_map.get(java_exception.__class__)         if mapped_exception:             py_exception = mapped_exception(java_exception)         else:             py_exception = error(-1, 'unmapped exception: %s' % java_exception)     py_exception.java_exception = java_exception     return _add_exception_attrs(py_exception) 

there clunkiness in code, , i'm sure room improvement, overall makes decorated code easier follow. example:

@raises_java_exception def gethostname():     return str(inetaddress.getlocalhost().gethostname()) 

Comments

Popular posts from this blog

Java 3D LWJGL collision -

methods - python can't use function in submodule -

c# - ErrorThe type or namespace name 'AxWMPLib' could not be found (are you missing a using directive or an assembly reference?) -