classification
Title: xmlrpclib can no longer marshal Fault objects
Type: Stage:
Components: Library (Lib) Versions: Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: amaury.forgeotdarc, loewis, mbonnet, pitrou
Priority: normal Keywords:

Created on 2007-06-19 16:57 by mbonnet, last changed 2010-06-09 21:41 by terry.reedy. This issue is now closed.

Files
File name Uploaded Description Edit
xmlrpclib-marshal-objects.patch mbonnet, 2007-06-19 16:57 Patch which allows Fault objects (and all other new-style classes) to be marshalled as structs
Messages (7)
msg32369 - (view) Author: Mike Bonnet (mbonnet) Date: 2007-06-19 16:57
xmlrpclib attempts to marshal class instances by registering the dump_instance() method as the marshaller for the <type 'instance'> type.  This is how marshalling of Fault objects contained in a tuple (for example, one result in a multicall) is handled.  This worked for Fault objects in python2.4 and earlier because they were old-style classes, and their type was always <type 'instance'>.

In python2.5, Exception (and thus Fault, which inherits from it) moved from an old-style class to a new-style class (inheriting from object).  This means that rather than type(faultinstance) returning <type 'instance'>, it returns <class 'xmlrpclib.Fault'>.  This results in xmlrpclib.Marshaller.__dump() throwing TypeError when it encounters a Fault (or any other new-style class).  This is a regression from python2.4 and earlier, and is particularly problematic for applications that expect to be able to marshal Fault instances.

I've attached a simple patch which allows Fault objects (and all other new-style classes) to be marshalled as structs, the same way Fault objects and old-style classes were in python2.4 and earlier.  This fixes the regression caused by the change in the Exception inheritance hierarchy.
msg62528 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2008-02-18 13:52
It looks like this was fixed in the trunk by rev 52790. Can someone
check it is indeed the case?
msg62529 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-02-18 14:15
Seems fixed indeed. Tested the following script:

import xmlrpclib
e = xmlrpclib.Fault("Error", "Message")
((d,), _) = xmlrpclib.loads(xmlrpclib.dumps((e,)))
assert d['faultString'] == "Message"

which works with python2.4, fails with python2.5, and works again with
python 2.6a0.

Now, this is a bug in 2.5, but the fix can be considered as a new
feature. I don't know if we should backport this.
msg62531 - (view) Author: Mike Bonnet (mbonnet) Date: 2008-02-18 14:37
How can this be considered a new feature?  Code that worked under
python2.4 fails under python2.5 as a result of this bug.  That is
clearly a regression.  I think that qualifies it for a backport to
python2.5.
msg62532 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-02-18 15:10
description for rev 52790 is:
"""
Patch #1070046: Marshal new-style objects like InstanceType in xmlrpclib.
"""

This _change_ is a new feature. OTOH it corrects a real regression.
Other thoughts?
msg62533 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2008-02-18 15:21
Perhaps the backported version should only care about instances of the
Fault class?
msg62537 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-02-18 16:05
Trying to understand the real problem:
Exceptions are not correctly marshalled by xmlrpclib, even with 2.6.

Take a standard exception, and process it:
    e = KeyError("message")
    ((d,), _) = xmlrpclib.loads(xmlrpclib.dumps((e,)))
With python2.4: you get
    {'args': ['message']}
With python2.6: you get
    {}
because 'args' is no more in the Exception's __dict__ anymore (another
regression??)

So to be compatible with 2.4, the correction would be to marshal
BaseException (and subclasses) by dumping its __dict__ augmented with
the "args" member:
    d = value.__dict__.copy()
    d['args'] = value.args
    self.dump_struct(d, write)
Since this code would only concern exception objects which always raise
an error in 2.5, it would not break existing code.
History
Date User Action Args
2010-06-09 21:41:28terry.reedysetstatus: open -> closed
resolution: fixed
versions: + Python 2.6, - Python 2.5
2008-02-18 16:05:08amaury.forgeotdarcsetmessages: + msg62537
2008-02-18 15:21:28pitrousetmessages: + msg62533
2008-02-18 15:10:39amaury.forgeotdarcsetmessages: + msg62532
2008-02-18 14:37:50mbonnetsetmessages: + msg62531
2008-02-18 14:15:05amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg62529
2008-02-18 13:52:17pitrousetnosy: + loewis, pitrou
messages: + msg62528
2007-06-19 16:57:20mbonnetcreate