Advertisement
Guest User

Untitled

a guest
Feb 12th, 2016
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.72 KB | None | 0 0
  1. # encoding: utf-8
  2. __author__ = 'mFoxRU'
  3.  
  4. import json
  5.  
  6. from twisted.internet.defer import maybeDeferred
  7.  
  8.  
  9. class Rpc(object):
  10. _fields = {'jsonrpc', 'method'}
  11.  
  12. def __init__(self):
  13. self._fn = {}
  14. self._sig = {}
  15.  
  16. def process(self, user_id, msg, callback):
  17. """ Executes received JSON-RPC message
  18. :param user_id: Recipient user's ID
  19. :type user_id: int
  20. :param msg: JSON-RPC message
  21. :type msg: str
  22. :param callback: Callback for sending reply
  23. :type callback: collections.Callable
  24. """
  25. try:
  26. message = json.loads(msg)
  27. except (ValueError, TypeError):
  28. return callback(user_id, self.reply_err_parse())
  29. if not self._fields.issubset(message):
  30. return callback(user_id, self.reply_err_invalid())
  31.  
  32. _id = message.get('id')
  33. method = message.get('method')
  34. params = message.get('params', {})
  35. params['user_id'] = user_id
  36. if method not in self._fn:
  37. return callback(user_id, self.reply_err_method(_id))
  38. if params.keys() != self._sig[method]:
  39. return callback(user_id, self.reply_err_params(_id))
  40.  
  41. d = maybeDeferred(self._fn[method], **params)
  42. d.addCallback(self.success, user_id, _id, callback)
  43. d.addErrback(self.failure, user_id, _id, callback)
  44.  
  45. def success(self, result, user_id, msg_id, callback):
  46. """ Send reply to user
  47. :param result: Call result
  48. :type result: tuple[bool | dict]
  49. :param user_id: Requester ID
  50. :type user_id: int
  51. :param msg_id: Request message ID
  52. :type msg_id: int
  53. :param callback: Callback for sending reply
  54. :type callback: collections.Callable
  55. """
  56. callback(user_id, self.reply_ok(msg_id, result[1]))
  57.  
  58. def failure(self, failure, user_id, msg_id, callback):
  59. """Send error reply to user
  60. :param failure: Failure result
  61. :type failure: twisted.python.failure.Failure
  62. :param user_id: Requester ID
  63. :type user_id: int
  64. :param msg_id: Request message ID
  65. :type msg_id: int
  66. :param callback: Callback for sending reply
  67. :type callback: collections.Callable
  68. """
  69. callback(user_id, self.reply_err(
  70. msg_id, -2, failure.getErrorMessage()))
  71.  
  72. def reg(self, name=None):
  73. """ Decorator to register function
  74. :param name: Optional
  75. :type name: []
  76. :return:
  77. """
  78. if callable(name):
  79. self.add(name)
  80. return name
  81.  
  82. def f(fn):
  83. self.add(fn, name=name)
  84. return fn
  85. return f
  86.  
  87. def add(self, fn, name=None):
  88. """ Register function
  89. :param fn: Function to add
  90. :type fn: collections.Callable
  91. :param name:
  92. """
  93. assert callable(fn), 'fn is not callable'.format(fn)
  94. if name is None:
  95. name = fn.__name__
  96. sig = list(fn.func_code.co_varnames[:fn.func_code.co_argcount])
  97. if 'self' in sig:
  98. sig.remove('self')
  99. print name, sig
  100. if name in self._fn:
  101. raise KeyError('Already have function with name {}'.format(name))
  102. self._fn[name] = fn
  103. self._sig[name] = sig
  104.  
  105. @staticmethod
  106. def reply_ok(request_id, result):
  107. """Form result reply
  108. :param request_id: Request id
  109. :type request_id: int
  110. :param result:
  111. :type result: any
  112. :return: JSON-RPC formatted message
  113. :rtype: str
  114. """
  115. reply = {'jsonrpc': '2.0',
  116. 'id': request_id,
  117. 'result': result}
  118. return json.dumps(reply)
  119.  
  120. @staticmethod
  121. def reply_err(request_id, error_code, error_msg):
  122. """Form error reply
  123. :param request_id: Request id
  124. :type request_id: [int, None]
  125. :param error_code: Error code
  126. :type error_code: int
  127. :param error_msg: Error message
  128. :type error_msg: str
  129. :return: JSON-RPC formatted message
  130. :rtype: str
  131. """
  132. reply = {'jsonrpc': '2.0',
  133. 'id': request_id,
  134. 'error': {
  135. 'code': error_code,
  136. 'message': error_msg
  137. }}
  138. return json.dumps(reply)
  139.  
  140. @staticmethod
  141. def notification(method, params):
  142. """Form notification reply
  143. :param method:
  144. :type method: str
  145. :param params:
  146. :type params: dict
  147. :return: JSON-RPC formatted message
  148. :rtype: str
  149. """
  150. message = {'jsonrpc': '2.0',
  151. 'method': method,
  152. 'params': params}
  153. return json.dumps(message)
  154.  
  155. @classmethod
  156. def reply_err_parse(cls):
  157. """Form parse error reply
  158. :return: JSON-RPC formatted message
  159. :rtype: str
  160. """
  161. return cls.reply_err(None, -32700, 'Parse error')
  162.  
  163. @classmethod
  164. def reply_err_invalid(cls):
  165. """Form invalid JSON-RPC reply
  166. :return: JSON-RPC formatted message
  167. :rtype: str
  168. """
  169. return cls.reply_err(None, -32600, 'Invalid JSON-RPC')
  170.  
  171. @classmethod
  172. def reply_err_method(cls, request_id=None):
  173. """Form method not found reply
  174. :param request_id: Request id
  175. :type request_id: int
  176. :return: JSON-RPC formatted message
  177. :rtype: str
  178. """
  179. return cls.reply_err(request_id, -32601, 'Method not found')
  180.  
  181. @classmethod
  182. def reply_err_params(cls, request_id=None):
  183. """Form invalid parameter(s) reply
  184. :param request_id: Request id
  185. :type request_id: int
  186. :return: JSON-RPC formatted message
  187. :rtype: str
  188. """
  189. return cls.reply_err(request_id, -32602, 'Invalid method parameter(s)')
  190.  
  191. rpc = Rpc()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement