User Defined Types
115
User Defined Types
The NET-RPC protocol supports all the types supported by the service agent framework, as well as the
concept of user defined scalar types. That is, if a service responds with data incorporating additional
scalar types, they will by default be passed back as instances of the Opaque type, where the "type"
attribute gives the name of the type and the "data" attribute the encoded value. Similarly, new types
may be sent by initialising an instance of the Opaque type with the name of the type and the value in
its encoded form.
url = "http://localhost:8000/service/validator"
service = netrpc.RemoteService(url,"admin","secret")
# following are equivalent
value = complex(1,1)
print service.echo(value)
print service.echo(netrpc.Opaque("python:complex",repr(value)))
Encoders and decoders for additional user defined scalar types can be provided by registering the ap-
propriate functions using the "encoder()" and "decoder()" functions available in the "netrpc"
module. The functions for registering the encoder and decoder functions are used in exactly the same
was as those in the "netsvc" module. In fact, they are the same functions as the "netsvc" module
imports them from the "netrpc" module, as it does for the implementations of all of the extended
types.
As is the case in the service agent framework, you need to be mindful about the effect of registering
arbitrary encoders and decoders at global scope, especially if your client application makes calls
against different services implementing their own scalar types. This becomes even more of an issue if
the "netrpc" module is used to make client side calls from inside a server side application using the
"netsvc" module. This is because they will share the same global encoders and decoders.
If you need to support types which are specific to a service being called, rather than registering the en-
coder and decoder function at global scope, the safer way is to supply your own functions just for that
service. This is done by supplying the function using a keyword argument when initialising the in-
stance of the RemoteService class. The keyword argument for the encoder function is "encode"
and that for the decoder function is "decode". The functions you supply should call the corresponding
global function if it doesn’t know what to do with a specific type.
def encodeObject(object):
if type(object) == MySQLdb.DateTimeType:
return ("xsd:string",object.strftime())
elif type(object) == MySQLdb.DateTimeDeltaType:
return ("xsd:string",str(object))
return netsvc.encodeObject(object)
url = "http://localhost:8000/service/validator"
service = netrpc.RemoteService(url,encode=encodeObject)