グローバルな辞書に関数を登録し、その引数と返り値の型のリストを保持する。
XML-RPC(軽量なRPC(Remote Procedure Call)プロトコル、SOAPの代わりに利用される)
デコレータを使用すると引数の型情報を設定できるため、入出力に渡される値がそれに合うことを
保証してくれるようになる。
from itertools import izip rpc_info = {} def xmlrpc(in_=(), out=(type(None) ,)): def _xmlrpc(function): # registration of parameters' information func_name = function.func_name rpc_info[func_name] = (in_, out) def _check_types(elements, types): """Subfunction that checks the types.""" if len(elements) != len(types): raise TypeError('argument count is wrong') typed = enumerate(izip(elements, types)) for index, couple in typed: arg, of_the_right_type = couple if isinstance(arg, of_the_right_type): continue raise TypeError('arg #%d should be %s' % (index, of_the_right_type)) # wrapping function def __xmlrpc(*args): checkable_args = args[1:] _check_types(checkable_args, in_) res = function(*args) if not type(res) in (tuple, list): checkable_res = (res,) else: checkable_res = res _check_types(checkable_res, out) return res return __xmlrpc return _xmlrpc class RPCView(object): @xmlrpc((int, int)) # two int -> None def meth1(self, int1, int2): print('received %d and %d' % (int1, int2)) @xmlrpc((str,), (int,)) # string -> int def meth2(self, phrase): print('received %s' % phrase) return 12 print rpc_info my = RPCView() my.meth1(1,2) my.meth2('1') my.meth2(1)
{'meth2': *1, 'meth1': *2}
received 1 and 2
received 1
Traceback (most recent call last):
TypeError: arg #0 should be
デコレータを使用すると引数の型情報を設定できる