Source code for tic.web.rpc.serviceHandler

from tic.web.browser.console import get_js
import logging
import os
from tic.core import Component, ExtensionPoint
from tic.web.rpc.api import CustomJsException, IJsonRpcService
from tic.web.rpc.json import JSONEncodeException, dumps, loads

[docs]class ServiceException(Exception): pass
[docs]class ServiceRequestNotTranslatable(ServiceException): pass
[docs]class BadServiceRequest(ServiceException): pass
[docs]class ServiceMethodNotFound(ServiceException): def __init__(self, name): msg = "Could not find a service that has the method '" + name + "'" ServiceException.__init__(self, msg) self.methodName = name
[docs]class ServiceHandler(Component): services = ExtensionPoint(IJsonRpcService)
[docs] def handle_request(self, json, request): self.request = request err = None result = None id_ = '' try: req = self._translate_request(json) except ServiceRequestNotTranslatable, e: err = e req = {'id':id_} if err == None: try: id_ = req['id'] methName = req['method'] args = req['params'] except: err = BadServiceRequest(json) if err == None: try: meth = self._find_service_endpoint(methName) except Exception, e: err = e if err == None: try: result = self._invoke_service_endpoint(meth, args) except Exception, e: err = e resultdata = self._translate_result(result, err, id_) return resultdata
def _translate_request(self, data): try: req = loads(data) except: raise ServiceRequestNotTranslatable(data) return req def _find_service_endpoint(self, rpc_method_name): ''' finds the requested method and returns it ''' try: #get the module, class and method names module, class_name, method_name = rpc_method_name.rsplit('.', 2) service = None #find the called service for srv in self.services: if (srv.__class__.__name__ == class_name) and (srv.__class__.__module__ == module): service = srv service.request = self.request break if not service: raise ServiceMethodNotFound(rpc_method_name) #get the method and return it meth = getattr(service, method_name) return meth except AttributeError: raise ServiceMethodNotFound(rpc_method_name) def _invoke_service_endpoint(self, meth, args): return meth(*args) def _translate_result(self, rslt, err, id_): if err != None: if isinstance(err, CustomJsException): return err.message log = self._log_errors() if log: return log err = {"name": err.__class__.__name__, "message":err.message} rslt = None try: if isinstance(rslt, basestring): data = '{"result":%s,"id":%i,"error":%s}' % (rslt, id_, dumps(err)) else: data = dumps({"result":rslt, "id":id_, "error":err}) except JSONEncodeException, e: err = {"name": "JSONEncodeException", "message":"Result Object Not Serializable"} data = dumps({"result":None, "id":id_, "error":err}) browser_hook = get_js(data) if browser_hook: return browser_hook return data def _log_errors(self): """ In development env, it will logs the error to the browser's console as well as the logs file. otherwise, it will only be logged in the log files (appengine app console) """ import traceback, sys exc_type, exc_value, exc_tb = sys.exc_info() tb = traceback.format_exception(exc_type, exc_value, exc_tb) err = ''.join(tb) logging.error(err) if 'Development' in os.environ['SERVER_SOFTWARE']: return "console.warn(%s)" % dumps("Python Error:\n%s" % err)