@c The Python X Library -- error handling
@c
@c Copyright 2000 Peter Liljenberg
@c

@node Error Handling
@chapter Error Handling

If an X object method generates an error, it will be handled in one of two
different ways depending on the kind of method.  Errors are represented
by X error objects in the Xlib.

If the method @emph{does not} return data, the error will most likely be
detected after the method has returned.  All methods which does not
return data has a parameter called @code{onerror}, which can be used to
provide a error handler for any error generated by this method.

The error handler is called with to arguments: the error object and the
low-level request object.  The error @emph{must not} do call any X
object methods.  If that is necessary, the error handler must store the
error away for later retrieval.  The class @code{error.CatchError} is
provided for this purpose.

If no error handler is given when calling a method which generates an
error, the error will be passed to the default error handler.  If no
default error handler is specified, the error is simply printed on
@code{sys.stderr}.

If the method @emph{does} return data, the error will make it impossible
for it to return any valid data.  An exception is raised with the error
object as the exception value.  It is not passed to any error handlers.

@menu
* X Error Classes::  X error class hierarchy.
* CatchError::       Error handler class.
@end menu


@node X Error Classes
@section X Error Classes

X errors are structured in the following class hierarchy:

@example
@group
Exception
 \_ error.XError
     \_ error.BadRequest
     \_ error.BadValue
     \_ error.BadAtom
     \_ error.BadMatch
     \_ error.BadAccess
     \_ error.BadAlloc
     \_ error.BadName
     \_ error.BadLength
     \_ error.BadImplementation
     \_ error.XResourceError
         \_ error.BadWindow
         \_ error.BadPixmap
         \_ error.BadCursor
         \_ error.BadFont
         \_ error.BadDrawable
         \_ error.BadColor
         \_ error.BadGC
         \_ error.BadIDChoice
@end group
@end example

All error objects has the following attributes:

@table @code

@item code

The numeric error code

@item sequence_number

The sequence number of the failed request

@item resource_id

The bad resource id.  For all the @code{error.XResourceError} this is a
X resource object.  For the other errors it is an integer, which for
some errors might have no meaning

@item major_opcode

The major opcode for the failed request

@item minor_opcode

The minor opcode for the failed request.  This will be zero for all base
X11R6 request, but will be interesting for extension requests

@end table


@node CatchError
@section CatchError

@code{error.CatchError} is an object which can be used as an error
handler.  It collects an error matching any of the specified types,
which can be retrieved later.  If several errors occur, only the last
one is remembered.


@deffn Class CatchError ( *errors )

Create a new error handler object.  Initialize by providing all error
classes you are interested in as arguments.  If no error classes are
provided at all, this means that all errors will be considered.

@end deffn


Pass the @code{error.CatchError} object as the @code{onerror} parameter
to X object methods.  If these methods generated any errors matching the
ones specified, it can be retrieved with the following functions:

@defmethod CatchError get_error ( )

Return the last error object caught, or None if no matching errors has
occured.

@end defmethod

@defmethod CatchError get_request ( )

Return the request object for the last error caught, or None if no
matching errors has occured.

@end defmethod

@code{error.CatchError} objects can be reused:

@defmethod CatchError reset ( )

Forget any caught error.

@end defmethod


Since the X protocol is mostly asynchronous any error we're watching for
might not have been recieved when we call @code{get_error}.  To make
sure that the request has been processed by the server and any error
generated has been received by the Xlib, we must synchronize with the
server.

An example of using @code{error.CatchError}:

@example
@group
# Resize and the foo window
# If it has been destroyed since we looked at it the last time,
# reset variable foo to None

# Create a error handler for BadWindow errors
ec = error.CatchError(error.BadWindow)

# Perform the operation
foo.configure(width = 100, height = 200, onerror = ec)

# Sync communication with server
display.sync()

# And check if there was any error
if ec.get_error():
    foo = None
@end group
@end example

               
