ipalib.rpc: now using allow_none=True after conversation with Rob; added xml_dumps() and xml_loads() functions; some name cleanup

This commit is contained in:
Jason Gerard DeRose 2009-01-15 23:52:50 -07:00
parent 2f829d015b
commit 6be5e4a0a5
3 changed files with 116 additions and 34 deletions

View File

@ -22,10 +22,10 @@ Core RPC functionality.
"""
from types import NoneType
from xmlrpclib import Binary
from xmlrpclib import Binary, Fault, dumps, loads
def xmlrpc_wrap(value):
def xml_wrap(value):
"""
Wrap all ``str`` in ``xmlrpclib.Binary``.
@ -42,13 +42,13 @@ def xmlrpc_wrap(value):
converted to UTF-8 encoded ``str`` instances (although as mentioned,
not by this function).
Also see `xmlrpc_unwrap`.
Also see `xml_unwrap`.
"""
if type(value) in (list, tuple):
return tuple(xmlrpc_wrap(v) for v in value)
return tuple(xml_wrap(v) for v in value)
if type(value) is dict:
return dict(
(k, xmlrpc_wrap(v)) for (k, v) in value.iteritems()
(k, xml_wrap(v)) for (k, v) in value.iteritems()
)
if type(value) is str:
return Binary(value)
@ -56,7 +56,7 @@ def xmlrpc_wrap(value):
return value
def xmlrpc_unwrap(value, encoding='UTF-8'):
def xml_unwrap(value, encoding='UTF-8'):
"""
Unwrap all ``xmlrpc.Binary``, decode all ``str`` into ``unicode``.
@ -69,13 +69,13 @@ def xmlrpc_unwrap(value, encoding='UTF-8'):
* All ``str`` instances are treated as UTF-8 encoded character data.
They are decoded and the resulting ``unicode`` instance is returned.
Also see `xmlrpc_wrap`.
Also see `xml_wrap`.
"""
if type(value) in (list, tuple):
return tuple(xmlrpc_unwrap(v, encoding) for v in value)
return tuple(xml_unwrap(v, encoding) for v in value)
if type(value) is dict:
return dict(
(k, xmlrpc_unwrap(v, encoding)) for (k, v) in value.iteritems()
(k, xml_unwrap(v, encoding)) for (k, v) in value.iteritems()
)
if type(value) is str:
return value.decode(encoding)
@ -84,3 +84,21 @@ def xmlrpc_unwrap(value, encoding='UTF-8'):
return value.data
assert type(value) in (unicode, int, float, bool, NoneType)
return value
def xml_dumps(params, methodname=None, methodresponse=False, encoding='UTF-8'):
if type(params) is tuple:
params = xml_wrap(params)
else:
assert isinstance(params, Fault)
return dumps(params,
methodname=methodname,
methodresponse=methodresponse,
encoding=encoding,
allow_none=True,
)
def xml_loads(data):
(params, method) = loads(data)
return (xml_unwrap(params), method)

View File

@ -24,7 +24,7 @@ Execute an RPC request.
from xmlrpclib import dumps, loads, Fault
from ipalib import Backend
from ipalib.errors import HandledError, CommandError
from ipalib.rpc import xmlrpc_wrap, xmlrpc_unwrap
from ipalib.rpc import xml_wrap, xml_unwrap
def params_2_args_options(params):
@ -44,9 +44,9 @@ class xmlrpc(Backend):
self.info('Received RPC call to %r', method)
if method not in self.Command:
raise CommandError(name=method)
(args, options) = params_2_args_options(xmlrpc_unwrap(params))
(args, options) = params_2_args_options(xml_unwrap(params))
result = self.Command[method](*args, **options)
return (xmlrpc_wrap(result),)
return (xml_wrap(result),)
def execute(self, data, ccache=None, client_ip=None, locale=None):
try:

View File

@ -21,64 +21,68 @@
Test the `ipalib.rpc` module.
"""
from xmlrpclib import Binary, dumps, loads
from tests.util import raises
from xmlrpclib import Binary, Fault, dumps, loads
from tests.util import raises, assert_equal
from tests.data import binary_bytes, utf8_bytes, unicode_str
from ipalib import rpc
def dump_n_load(value):
(param, method) = loads(
dumps((value,))
dumps((value,), allow_none=True)
)
return param[0]
def round_trip(value):
return rpc.xmlrpc_unwrap(
dump_n_load(rpc.xmlrpc_wrap(value))
return rpc.xml_unwrap(
dump_n_load(rpc.xml_wrap(value))
)
def test_round_trip():
"""
Test `ipalib.rpc.xmlrpc_wrap` and `ipalib.rpc.xmlrpc_unwrap`.
Test `ipalib.rpc.xml_wrap` and `ipalib.rpc.xml_unwrap`.
This tests the two functions together with ``xmlrpclib.dumps()`` and
``xmlrpclib.loads()`` in a full wrap/dumps/loads/unwrap round trip.
"""
# We first test that our assumptions about xmlrpclib module in the Python
# standard library are correct:
assert dump_n_load(utf8_bytes) == unicode_str
assert dump_n_load(unicode_str) == unicode_str
assert dump_n_load(Binary(binary_bytes)).data == binary_bytes
assert_equal(dump_n_load(utf8_bytes), unicode_str)
assert_equal(dump_n_load(unicode_str), unicode_str)
assert_equal(dump_n_load(Binary(binary_bytes)).data, binary_bytes)
assert isinstance(dump_n_load(Binary(binary_bytes)), Binary)
assert type(dump_n_load('hello')) is str
assert type(dump_n_load(u'hello')) is str
assert_equal(dump_n_load(''), '')
assert_equal(dump_n_load(u''), '')
assert dump_n_load(None) is None
# Now we test our wrap and unwrap methods in combination with dumps, loads:
# All str should come back str (because they get wrapped in
# xmlrpclib.Binary(). All unicode should come back unicode because str
# explicity get decoded by rpc.xmlrpc_unwrap() if they weren't already
# explicity get decoded by rpc.xml_unwrap() if they weren't already
# decoded by xmlrpclib.loads().
assert round_trip(utf8_bytes) == utf8_bytes
assert round_trip(unicode_str) == unicode_str
assert round_trip(binary_bytes) == binary_bytes
assert_equal(round_trip(utf8_bytes), utf8_bytes)
assert_equal(round_trip(unicode_str), unicode_str)
assert_equal(round_trip(binary_bytes), binary_bytes)
assert type(round_trip('hello')) is str
assert type(round_trip(u'hello')) is unicode
assert round_trip('') == ''
assert round_trip(u'') == u''
compound = [utf8_bytes, unicode_str, binary_bytes,
assert_equal(round_trip(''), '')
assert_equal(round_trip(u''), u'')
assert round_trip(None) is None
compound = [utf8_bytes, None, binary_bytes, (None, unicode_str),
dict(utf8=utf8_bytes, chars=unicode_str, data=binary_bytes)
]
assert round_trip(compound) == tuple(compound)
def test_xmlrpc_wrap():
def test_xml_wrap():
"""
Test the `ipalib.rpc.xmlrpc_wrap` function.
Test the `ipalib.rpc.xml_wrap` function.
"""
f = rpc.xmlrpc_wrap
f = rpc.xml_wrap
assert f([]) == tuple()
assert f({}) == dict()
b = f('hello')
@ -90,11 +94,11 @@ def test_xmlrpc_wrap():
value = f([dict(one=False, two=u'hello'), None, 'hello'])
def test_xmlrpc_unwrap():
def test_xml_unwrap():
"""
Test the `ipalib.rpc.xmlrpc_unwrap` function.
Test the `ipalib.rpc.xml_unwrap` function.
"""
f = rpc.xmlrpc_unwrap
f = rpc.xml_unwrap
assert f([]) == tuple()
assert f({}) == dict()
value = f(Binary(utf8_bytes))
@ -106,3 +110,63 @@ def test_xmlrpc_unwrap():
assert value == (True, 'hello', dict(one=1, two=unicode_str, three=None))
assert type(value[1]) is str
assert type(value[2]['two']) is unicode
def test_xml_dumps():
"""
Test the `ipalib.rpc.xml_dumps` function.
"""
f = rpc.xml_dumps
params = (binary_bytes, utf8_bytes, unicode_str, None)
# Test serializing an RPC request:
data = f(params, 'the_method')
(p, m) = loads(data)
assert_equal(m, u'the_method')
assert type(p) is tuple
assert rpc.xml_unwrap(p) == params
# Test serializing an RPC response:
data = f((params,), methodresponse=True)
(tup, m) = loads(data)
assert m is None
assert len(tup) == 1
assert type(tup) is tuple
assert rpc.xml_unwrap(tup[0]) == params
# Test serializing an RPC response containing a Fault:
fault = Fault(69, unicode_str)
data = f(fault, methodresponse=True)
e = raises(Fault, loads, data)
assert e.faultCode == 69
assert_equal(e.faultString, unicode_str)
def test_xml_loads():
"""
Test the `ipalib.rpc.xml_loads` function.
"""
f = rpc.xml_loads
params = (binary_bytes, utf8_bytes, unicode_str, None)
wrapped = rpc.xml_wrap(params)
# Test un-serializing an RPC request:
data = dumps(wrapped, 'the_method', allow_none=True)
(p, m) = f(data)
assert_equal(m, u'the_method')
assert_equal(p, params)
# Test un-serializing an RPC response:
data = dumps((wrapped,), methodresponse=True, allow_none=True)
(tup, m) = f(data)
assert m is None
assert len(tup) == 1
assert type(tup) is tuple
assert_equal(tup[0], params)
# Test un-serializing an RPC response containing a Fault:
fault = Fault(69, unicode_str)
data = dumps(fault, methodresponse=True, allow_none=True)
e = raises(Fault, f, data)
assert e.faultCode == 69
assert_equal(e.faultString, unicode_str)