Hello
everybody:
I'm making some kind of development related to invoke externally from a Java
Applet some ZOPE product methods via XML-RPC.
I
use ZOPE as the XMLRPC server, as it can 'listen' for XMLRPC requests, find the
method requested using URL and traversal, invoke the method and receive the
return value of it and then encapsulate the result in a XMLRPC
response.
Anyways, I want to report some exceptions from my ZOPE product python methods
through XML-RPC to the applet. As my methods don't work directly with XMLRPC,
all is embedded inside ZOPE, all the XMLRPC works are transparent for my python
methods, so I didn't realize how I could do it.
After looking for the ZOPE code responsible of the XMLRPC request process and
XMLRPC response generation I found that some of the work was being done in
ZPublisher xmlrpc.py code (Response stuff).
Then when I started to read the comments of the code I found this in the
Response class of the code:
""" It's probably possible to improve the 'exception' method quite a bit. The
current implementation, however, should suffice for now. """
But as you will see is not enough, at least for my needs.
I
want to define my own exceptions in my product, this exceptions could be defined
as follows:
class
MyOwnException:
__init__(self, faultCode, faultString):
self.faultCode = faultCode
self.faultString = faultString
Obviously I
want to map XMLRPC-like fault format.
Then, I
could raise this exception from my method, and I will want that the class
responsible of making the XMLRPC Response for my XMLRPC client will use it for
composing the XML for XMLRPC using my fault code and fault
string.
But I found
that xmlrpc.py doesn't take into account that (i'm talking of ZOPE 2.6.0) so i
had to make some changes in the code of
ZPublisher/xmlrpc.py:
def exception(self, fatal=0,
info=None,
absuri_match=None, tag_search=None):
# Fetch our exception info. t is type, v is value and tb is the
# traceback object.
if type(info) is type(()) and len(info)==3: t,v,tb = info
else:
t,v,tb = sys.exc_info()
# Don't mask 404 respnses, as some XML-RPC libraries rely on the HTTP
# mechanisms for detecting when authentication is required. Fixes Zope
# Collector issue 525.
if t == 'Unauthorized' or (isinstance(t, types.ClassType)
and issubclass(t, Unauthorized)):
return self._real.exception(fatal=fatal, info=info)
absuri_match=None, tag_search=None):
# Fetch our exception info. t is type, v is value and tb is the
# traceback object.
if type(info) is type(()) and len(info)==3: t,v,tb = info
else:
t,v,tb = sys.exc_info()
# Don't mask 404 respnses, as some XML-RPC libraries rely on the HTTP
# mechanisms for detecting when authentication is required. Fixes Zope
# Collector issue 525.
if t == 'Unauthorized' or (isinstance(t, types.ClassType)
and issubclass(t, Unauthorized)):
return self._real.exception(fatal=fatal, info=info)
#
Create an appropriate Fault object. Containing error
information
Fault=xmlrpclib.Fault
f=None
try:
# Strip HTML tags from the error value
v = str(v)
remove = [r"<[^<>]*>", r"&[A-Za-z]+;"]
for pat in remove:
v = re.sub(pat, " ", v)
from Globals import DevelopmentMode
if DevelopmentMode:
from traceback import format_exception
value = '\n' + ''.join(format_exception(t, v, tb))
else:
value = '%s - %s' % (t, v)
###### my own extension for catching user exceptions START #####
try:
faultCode = getattr(sys.exc_info()[1],'faultCode')
faultString = getattr(sys.exc_info()[1],'faultString')
except:
print "no according exception type"
###### my own extension for catching user exceptions FINISH #####
Fault=xmlrpclib.Fault
f=None
try:
# Strip HTML tags from the error value
v = str(v)
remove = [r"<[^<>]*>", r"&[A-Za-z]+;"]
for pat in remove:
v = re.sub(pat, " ", v)
from Globals import DevelopmentMode
if DevelopmentMode:
from traceback import format_exception
value = '\n' + ''.join(format_exception(t, v, tb))
else:
value = '%s - %s' % (t, v)
###### my own extension for catching user exceptions START #####
try:
faultCode = getattr(sys.exc_info()[1],'faultCode')
faultString = getattr(sys.exc_info()[1],'faultString')
except:
print "no according exception type"
###### my own extension for catching user exceptions FINISH #####
if
isinstance(v,
Fault):
f=v
###### my own extension for catching user exceptions START #####
elif (faultCode and faultString) :
f = xmlrpclib.Fault(faultCode,faultString)
###### my own extension for catching user exceptions FINISH ######
elif isinstance(v, Exception):
f=Fault(-1, 'Unexpected Zope exception: %s' % value)
else:
f=Fault(-2, 'Unexpected Zope error value: %s' % value)
except:
f=Fault(-3, "Unknown Zope fault type")
f=v
###### my own extension for catching user exceptions START #####
elif (faultCode and faultString) :
f = xmlrpclib.Fault(faultCode,faultString)
###### my own extension for catching user exceptions FINISH ######
elif isinstance(v, Exception):
f=Fault(-1, 'Unexpected Zope exception: %s' % value)
else:
f=Fault(-2, 'Unexpected Zope error value: %s' % value)
except:
f=Fault(-3, "Unknown Zope fault type")
#
Do the
damage.
self.setBody(f)
self._real.setStatus(200)
self.setBody(f)
self._real.setStatus(200)
return tb
By that way,
I could send my own fault code and fault descriptions via
XML-RPC.
But as you
can see, I have to extend ZOPE code, and I don't want to do it, I have to work
with standard releases of ZOPE.
Do you think
that something like that would be improved in an early future for next ZOPE
releases?
Any opinion
will be really appreciated.
Thanks for
advance.
Regards.
Aitor Illarramendi Amilibia | |
Ingeniero de software
Mando y Control | |
| |
Carretera de Loeches, 9
28850 - Torrejón de Ardoz, Madrid (ESPAÑA) Tel: +34-91-626.80.60 Fax: +34-91-626.81.14 |
<<Indra.bmp>>