def on_dispatcher_prepare(self, dispatcher: Dispatcher): for name in dir(self): item = getattr(self, name) if callable(item) and hasattr(item, ANNOTATIONS_RPC_METHOD_PROPERTY): rpc_name = getattr(item, ANNOTATIONS_RPC_METHOD_PROPERTY) if not getattr(item, ANNOTATIONS_IGNORE_PREFIX_PROPERTY, False): rpc_name = self.METHOD_PREFXIX + rpc_name dispatcher.add_method(item, rpc_name)
def server_routine(): d = Dispatcher() d.build_method_map(LibvirtController()) # d.build_method_map(grpc.gRPCDataCollector()) print("Collecting updates from server...") socket_sub.connect("tcp://localhost:%s" % port_sub) topicfilter = "test-id" socket_sub.setsockopt_string(zmq.SUBSCRIBE, topicfilter) while True: topic = socket_sub.recv().decode('ASCII') if socket_sub.get(zmq.RCVMORE) and topic == topicfilter: messagedata = socket_sub.recv() print(messagedata) pub_response(d, messagedata)
def master_state_service(args): # Start listening for connections sock = socket.socket() sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', 31337)) sock.listen() # Create order batch submission timer t = threading.Thread(target=sig_collector.send_batch_to_signer_services, daemon=True) t.start() # Configure RPC dispatchers state_dispatchers = { State.RECEIVE_ORDERS: Dispatcher({"receive_order": client_handler.receive_order}), State.COLLECT_BATCH_SIGNATURES: Dispatcher({}), State.RETRIEVE_DKG_PK_FOR_ORDERS: Dispatcher({}), State.RECEIVE_MATCHES: Dispatcher({ 'receive_matching': matcher_handler.receive_matching, 'return_latest_signed_batch': matcher_handler.return_latest_signed_batch }), State.COLLECT_MATCHINGS_SIGNATURES: Dispatcher({}), State.RETRIEVE_DKG_PK_FOR_MATCHINGS: Dispatcher({}), State.CHOOSE_OPTIMAL_MATCHING: Dispatcher({}), } global_dispatcher = Dispatcher({ "return_confirmation": client_handler.return_confirmation, "return_matching_confirmation": matcher_handler.return_matching_confirmation, }) # Accept connections and start handling them in own thread print("Gnodex Master State Server Started") while True: try: new_sock = sock.accept()[0] thread = threading.Thread( target=handle_rpc_client_stateful, args=(new_sock, certs.path_to('server.crt'), certs.path_to('server.key'), state_dispatchers, global_dispatcher, get_state_lock_func), daemon=True) thread.start() except KeyboardInterrupt: print("Master State Service Exit.") break
def __init_api(self): self._req_disp = Dispatcher() def add_api_meth(api_f, name): # method format: <api_prefix>.<methodName> passid_api_f = lambda *args, **kwargs: api_f(self, *args, **kwargs) self._req_disp.add_method( passid_api_f, "{}.{}".format(PassIdApiServer.api_method_prefix, name)) # register methods with @passidapi decorator as rpc api handler import inspect meths = inspect.getmembers(PassIdApiServer, predicate=inspect.isfunction) for m in meths: if m[1].__name__ == "wrapped_api_f": add_api_meth(m[1], m[0])
def __init__(self, dispatcher: Dispatcher = None, expose_version_api=True, expose_ping_api=True) -> None: self.dispatcher = dispatcher or Dispatcher() self.__api_version = None # type: str self.encoder = SizzleWSJsonEncoder() if expose_version_api: self.dispatcher[API_METHOD_VERSION] = self.m_get_version if expose_ping_api: self.dispatcher[API_METHOD_PING] = self.m_ping self.on_dispatcher_prepare(self.dispatcher)
def server_routine(): d = Dispatcher() d.build_method_map(LibvirtController) d.build_method_map(gRPCDataCollector) d.build_method_map(DockerController) d.build_method_map(BCMController) print("Collecting updates from server...") socket_sub.connect("tcp://localhost:%s" % port_sub) topicfilter = CONTROLLER_ID socket_sub.setsockopt_string(zmq.SUBSCRIBE, topicfilter) while True: received = socket_sub.recv() pub_response(d, received)
def signer_service(args): # Start listening for connections sock = socket.socket() sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', 31338 + signer.instance_id)) sock.listen() # Configure RPC dispatchers state_dispatchers = { State.RECEIVE_ORDER_BATCH: Dispatcher({"receive_batch": server_handler.receive_order_batch}), State.RECEIVE_MATCH_COLLECTION: Dispatcher({ "receive_match_collection": server_handler.receive_match_collection }), } global_dispatcher = Dispatcher({}) # Accept connections and start handling them in own thread print("Gnodex Signing Service %d Started" % signer.instance_id) thread = threading.Thread(target=handle_rpc_state_changes, args=(get_state_lock_func, set_state_func), daemon=True) thread.start() while True: try: new_sock = sock.accept()[0] thread = threading.Thread( target=handle_rpc_client_stateful, args=(new_sock, certs.path_to('server.crt'), certs.path_to('server.key'), state_dispatchers, global_dispatcher, get_state_lock_func)) thread.setDaemon(True) thread.start() except KeyboardInterrupt: print("Signing Service %d Exit." % signer.instance_id) break
def __init__( self, app: Flask, *, path: str = "/api/", swagger_kwargs: Dict[str, Any] = None, ): """ - `app` is a Flask app (https://flask.palletsprojects.com/en/1.1.x/) to which URL rules are added for the RPC. - `path` is the endpoint that will be added to the app for the JSON RPC. This is where requests will be POSTed. There will also be a path for each method based on the function name, e.g. `/api/scale` and `/api/translate`, see https://github.com/alexmojaki/instant_api#using-method-paths-instead-of-json-rpc - `swagger_kwargs` is a dictionary of keyword arguments to pass to the `flasgger.Swagger` constructor that is called with the app. For example, you can customise the Swagger UI by passing a dictionary to `config` (https://github.com/flasgger/flasgger#customize-default-configurations):: api = InstantAPI(app, swagger_kwargs={ "config": {"specs_route": "/my_apidocs/", ...} }) """ self.app = app self.path = path.rstrip("/") + "/" self.dispatcher = Dispatcher() self.swagger = Swagger(app, **(swagger_kwargs or {})) self._add_view( {"tags": ["JSON-RPC"]}, GLOBAL_PARAMS_SCHEMA, GLOBAL_SUCCESS_SCHEMA, self.path, type(self).__name__, "Generic JSON RPC endpoint", method=None, )
def __init__(self, datamanager: "DataManager", url: str, port: int, ConvertError: type, ConflictError: type, NotFoundError: type, WouldBlockError: type, callback=lambda r: None): super().__init__() self.datamanager = datamanager self.url = url self.port = port self.callback = callback self._define_errors() self.dispatcher = Dispatcher() self.setDaemon(True) @self.dispatcher.add_method def read(dataname: str): try: return { dataname: self.datamanager.read_data(dataname), 'message': 'success' } except WouldBlockError as e: return self._error(e, self.WOULD_BLOCK_ERROR) except NotFoundError as e: return self._error(e, self.NOT_FOUND_ERROR) except ConvertError as e: # This mean unsupported type obj is requested # Users should regard this as not found error return self._error(e, self.NOT_FOUND_ERROR) except Exception as e: return self._error(e, self.INTERNAL_ERROR) @self.dispatcher.add_method def write(dataname: str, data: dict, provider: str = 'server'): try: self.datamanager.write_data(dataname, data, provider) return {'message': 'success'} except WouldBlockError as e: return self._error(e, self.WOULD_BLOCK_ERROR) except AssertionError as e: return self._error(e, self.INVALID_VALUE_ERROR) except ConflictError as e: return self._error(e, self.CONFLICT_ERROR) except Exception as e: return self._error(e, self.INTERNAL_ERROR)
def __init__(self, handler, istream, ostream): self.handler = handler self.istream = istream self.ostream = ostream self.running = True self.dispatcher = Dispatcher({ 'initialize': self.initialize, 'shutdown': self.shutdown, '$/setTraceNotification': self.setTraceNotification, 'textDocument/didOpen': self.didOpen, 'textDocument/didChange': self.didChange, 'textDocument/hover': self.hover, 'textDocument/definition': self.definition, 'textDocument/completion': self.completion, })
class InstantAPI: """ Instantly create an HTTP API with automatic type conversions, JSON RPC, and a Swagger UI. Just add methods! Basic usage looks like this:: from dataclasses import dataclass from flask import Flask from instant_api import InstantAPI app = Flask(__name__) @dataclass class Point: x: int y: int @InstantAPI(app) class Methods: def translate(self, p: Point, dx: int, dy: int) -> Point: return Point(p.x + dx, p.y + dy) def scale(self, p: Point, factor: int) -> Point: return Point(p.x * factor, p.y * factor) if __name__ == '__main__': app.run() See the README at https://github.com/alexmojaki/instant_api for more details. Instances are callable so that they can be used as a decorator to add methods. See the docstring for __call__. You can subclass this class and override the following methods to customise behaviour: - is_authenticated - handle_request - call_method """ def __init__( self, app: Flask, *, path: str = "/api/", swagger_kwargs: Dict[str, Any] = None, ): """ - `app` is a Flask app (https://flask.palletsprojects.com/en/1.1.x/) to which URL rules are added for the RPC. - `path` is the endpoint that will be added to the app for the JSON RPC. This is where requests will be POSTed. There will also be a path for each method based on the function name, e.g. `/api/scale` and `/api/translate`, see https://github.com/alexmojaki/instant_api#using-method-paths-instead-of-json-rpc - `swagger_kwargs` is a dictionary of keyword arguments to pass to the `flasgger.Swagger` constructor that is called with the app. For example, you can customise the Swagger UI by passing a dictionary to `config` (https://github.com/flasgger/flasgger#customize-default-configurations):: api = InstantAPI(app, swagger_kwargs={ "config": {"specs_route": "/my_apidocs/", ...} }) """ self.app = app self.path = path.rstrip("/") + "/" self.dispatcher = Dispatcher() self.swagger = Swagger(app, **(swagger_kwargs or {})) self._add_view( {"tags": ["JSON-RPC"]}, GLOBAL_PARAMS_SCHEMA, GLOBAL_SUCCESS_SCHEMA, self.path, type(self).__name__, "Generic JSON RPC endpoint", method=None, ) def is_authenticated(self): """ Override and return False for certain requests to deny any access to the API. """ return True def handle_request(self, method: Optional[str]): """ Entrypoint which converts a raw flask request to a response. If `method` is None, the request was made to the generic JSON-RPC path. Otherwise `method` is a string with the method name at the end of the request path. """ if not self.is_authenticated(): return "Forbidden", 403 # Forward the request to the correct method # Ultimately this calls call_method request_data = request.get_data(as_text=True) if method is not None: request_data = ('{' ' "id": null,' ' "jsonrpc": "2.0",' f' "method": {json.dumps(method)},' f' "params": {request_data}' '}') result = JSONRPCResponseManager.handle(request_data, self.dispatcher) if result is None: # Request was a notification, i.e. client doesn't need response return "", 200 else: http_code = 200 if result.error: data = result.error.get("data") # See the InstantError handler at the end of call_method if isinstance(data, dict) and "__instant_http_code" in data: http_code = data["__instant_http_code"] result.error["data"] = data["data"] else: if result.error.get("code") in [ -32700, # JSON parse error -32600, # Invalid JSON structure -32602, # Invalid params ]: http_code = 400 # Bad request else: http_code = 500 # Internal server error # JSON RPC must always return 200 if method is None: http_code = 200 return result.data, http_code def call_method(self, func, *args, **kwargs): """ Calls the API method `func` with the given arguments. The arguments here are not yet deserialized according to the function type annotations. """ try: try: return func(*args, **kwargs) except InstantError: raise except ArgumentError as e: e = e.__cause__ if isinstance(e, ValidationError): data = e.messages else: data = None raise InstantError( code=-32602, # Invalid params message=format_exception(e), data=data, http_code=400, ) except JSONRPCDispatchException as e: raise InstantError( code=e.error.code, message=e.error.message, data=e.error.data, ) except Exception: raise InstantError( code=-32000, message=f"Unhandled error in method {func.__name__}", ) except InstantError as e: raise JSONRPCDispatchException( code=e.code, message=e.message, # Mash the http_code in here to be extracted later in handle_request # There's no easy way to get this info through the json-rpc # library up to the final response data=dict( __instant_http_code=e.http_code, data=e.data, ), ) def __call__(self, func_class_or_obj: Any = None, *, swagger_view_attrs: dict = None): """ Accepts any object, with special treatment for functions and classes, so this can be used as a decorator. Decorating a single function adds it as an API method. The function itself should not be a method of a class, since there is no way to provide the first argument `self`. Decorating a class will construct an instance of the class without arguments and then call the resulting object as described below. This means it will add bound methods, so the `self` argument is ignored. Passing an object will search through all its attributes and add to the API all functions (including bound methods) whose name doesn't start with an underscore (`_`). So given `api = InstantAPI(app)`, all of these are equivalent: @api def foo(bar: Bar) -> Spam: ... api(foo) @api class Methods: def foo(self, bar: Bar) -> Spam: ... api(Methods) api(Methods()) If a function is missing a type annotation for any of its parameters or for the return value, an exception will be raised. If you don't want a method to be added to the API, prefix its name with an underscore, e.g. `def _foo(...)`. For each function, a `flasgger.SwaggerView` will be created. (see https://github.com/flasgger/flasgger#using-marshmallow-schemas) You can customise the view by passing a dictionary class attributes in the argument `swagger_view_attrs` For example:: @api(swagger_view_attrs={"tags": ["Stuff"]}) def foo(...) This will put `foo` in the `Stuff` section of the Swagger UI. If a function has a docstring, its first line will be the "summary" in the OpenAPI spec of the method path, visible in the overview in the Swagger UI. The remaining lines will become the "description", visible when the path is expanded in the UI. """ if func_class_or_obj is None: # Decorator with arguments return functools.partial(self, swagger_view_attrs=swagger_view_attrs) if isinstance(func_class_or_obj, type): cls = func_class_or_obj self(cls(), swagger_view_attrs=swagger_view_attrs) return cls # noinspection PyTypeChecker self._decorate_function(func_class_or_obj, swagger_view_attrs) methods = func_class_or_obj for name, func in inspect.getmembers(methods): if not name.startswith("_"): self._decorate_function(func, swagger_view_attrs) return func_class_or_obj def _decorate_function(self, func, swagger_view_attrs): try: inspect.signature(func) except Exception: return name = func.__name__ func: datafunction = datafunction(func) @functools.wraps(func) def wrapper(*args, **kwargs): return self.call_method(func, *args, **kwargs) self.dispatcher.add_method(wrapper) @dataclass class _Success: id: int jsonrpc: str class Success(class_schema(_Success)): result = func.return_schemas.schema_class._declared_fields[ "_return"] Success.__name__ = f"{name}_success" self._add_view( swagger_view_attrs or {}, func.params_schemas.schema_class, Success, self.path + name, type(self).__name__ + "_" + name, func.__doc__, method=name, ) def _add_view( self, swagger_view_attrs: dict, body_schema, success_schema, path: str, view_name: str, doc: str, method: Optional[str], ): instant_api_self = self class MethodView(SwaggerView): summary, _, description = dedent(doc or "").strip().partition("\n") parameters = [{ "name": "body", "in": "body", "schema": body_schema, "required": True, }] responses = { "Success": { "schema": success_schema }, "Error": { "schema": ERROR_SCHEMA }, } tags = ["Methods"] locals().update(swagger_view_attrs) def post(self): return instant_api_self.handle_request(method) self.app.add_url_rule( path, view_func=MethodView.as_view(view_name), methods=["POST"], )
def rpc_server_worker(host, port, username, password, queue): dispatcher = Dispatcher() srv = None # prehash password password = int(sha256(bytes(password, "utf8")).hexdigest(), 16) @dispatcher.add_method def actions(args): try: actionlist = args[0] for action in actionlist: if action[0] not in ('mousemove', 'mousebutton', 'keyevent'): raise ValueError('unknown action') queue.put((None, 'actions', actionlist), True) return "OK" except: return "UNEXPECTED_INPUT" @dispatcher.add_method def mousebutton(args): respqueue = Queue(1) queue.put((respqueue, "mousebutton") + tuple(args), True) try: return respqueue.get(True, 5) except QueueEmpty: return "TIMEOUT" @dispatcher.add_method def mousemove(args): respqueue = Queue(1) queue.put((respqueue, "mousemove") + tuple(args), True) try: return respqueue.get(True, 5) except QueueEmpty: return "TIMEOUT" @dispatcher.add_method def keyevent(args): key, modifiers, down = args respqueue = Queue(1) queue.put((respqueue, "keyevent", key, modifiers or [], down), True) try: return respqueue.get(True, 5) except QueueEmpty: return "TIMEOUT" @dispatcher.add_method def devicecommand(args): devcommand = args respqueue = Queue(1) queue.put((respqueue, "devicecommand", devcommand), True) try: return respqueue.get(True, 5) except QueueEmpty: return "TIMEOUT" @dispatcher.add_method def exit(args): respqueue = Queue(1) queue.put((respqueue, "exit"), True) try: respqueue.get(True, 5) except: pass raise RPCServExitException() @Request.application def app(request): # auth with simplified version of equal op (timing attack secure) if (username != "" or password != "") and \ (getattr(request.authorization,"username","") != username or \ int(sha256(bytes(getattr(request.authorization,"password",""), "utf8")).hexdigest(), 16) - \ password != 0): json = JSONRPC20Response(error={ "code": 403, "message": "Invalid username or password!" }).json return Response(json, 403, mimetype='application/json') response = JSONRPCResponseManager.handle(request.data, dispatcher) return Response(response.json, mimetype='application/json') try: # response queue is used to notify result of attempt to run the server respqueue = queue.get() srv = make_server(host, port, app, request_handler=RequestHandler) logging.info("http-jsonrpc listening at {}:{}".format(host, port)) queue.task_done() # let run_rpc_server return respqueue.put("SUCCESS") srv.serve_forever() except RPCServExitException: logging.info("Exit exception raised!") except: queue.task_done() respqueue.put("FAIL") logging.error(traceback.format_exc())
import psycopg2 from werkzeug.wrappers import Request, Response from werkzeug.serving import run_simple from jsonrpc import JSONRPCResponseManager, dispatcher, Dispatcher dispatcher = Dispatcher() @dispatcher.add_method def example_method(*args, **kwargs): print("param 1: " + args[0]) print("param 2: " + args[1]) @dispatcher.add_method def connect_to_db(*args, **kwargs): try: connect_str = "dbname='pos_projekt' user='******' host='X' password='******'" # use our connection values to establish a connection conn = psycopg2.connect(connect_str) # create a psycopg2 cursor that can execute queries cursor = conn.cursor() # create a new table with a single column called "name" # cursor.execute("""CREATE TABLE tutorials (name char(40));""") # run a SELECT statement - no data in there, but we can try it cursor.execute("""SELECT * from User""") rows = cursor.fetchall() print(rows) except Exception as e: print("Uh oh, can't connect. Invalid dbname, user or password?")
def __init__(self, *args, **kwargs): message_handler = MessageHandler(kwargs.pop('to_printer')) self.dispatcher = Dispatcher(message_handler) super().__init__(*args, **kwargs)
class PassIdApiServer: """ PassID Api server """ api_method_prefix = "passID" def __init__(self, db: proto.StorageAPI, config: Config): self._conf = config.api_server self._proto = proto.PassIdProto(db, config.challenge_ttl) self._log = log.getLogger("passid.api") # Register rpc api methods self.__init_api() def start(self): run_simple(self._conf.host, self._conf.port, self.__create_calls, ssl_context=self._conf.ssl_ctx, threaded=True) def passidapi(api_f): def wrapped_api_f(self, *args, **kwargs): self.__log_api_call(api_f, **kwargs) ret = api_f(self, *args, **kwargs) self.__log_api_response(api_f, ret) return ret return wrapped_api_f # RPC API methods # API: passID.ping @passidapi def ping(self, ping: int) -> dict: """ Function returns challenge that passport needs to sign. Challenge is base64 encoded. """ try: pong = int.from_bytes(os.urandom(4), 'big') return {"pong": pong} except Exception as e: return self.__handle_exception(e) # API: passID.getChallenge @passidapi def getChallenge(self) -> dict: """ Function returns challenge that passport needs to sign. Challenge is base64 encoded. """ try: c = self._proto.createNewChallenge() return {"challenge": c.toBase64()} except Exception as e: return self.__handle_exception(e) # API: passID.cancelChallenge @passidapi def cancelChallenge(self, challenge: str) -> Union[None, dict]: """ Function erases challenge from server. :param challenge: base64 encoded string :return: Nothing if success, else error """ try: challenge = try_deser( lambda: proto.Challenge.fromBase64(challenge)) self._proto.cancelChallenge(challenge.id) return None except Exception as e: return self.__handle_exception(e) # API: passID.register @passidapi def register(self, dg15: str, sod: str, cid: str, csigs: List[str], dg14: str = None) -> dict: """ Register new user. It returns back to the client userId which is publicKey address, session key and session expiration time. :param dg15: eMRTD DG15 file :param sod: eMRTD SOD file :param cid: Challenge id :param csigs: Challenge signatures :param dg14: eMRTD DG14 file (optional) :return: 'uid' - base64 encoded user id 'session_key' - base64 encoded session key 'expires' - unix timestamp of time when session will expire """ try: dg15 = try_deser(lambda: ef.DG15.load(b64decode(dg15))) sod = try_deser(lambda: ef.SOD.load(b64decode(sod))) cid = try_deser(lambda: proto.CID.fromhex(cid)) csigs = _b64csigs_to_bcsigs(csigs) if dg14 is not None: dg14 = try_deser(lambda: ef.DG14.load(b64decode(dg14))) uid, sk, set = self._proto.register(dg15, sod, cid, csigs, dg14) return { "uid": uid.toBase64(), "session_key": sk.toBase64(), "expires": int(set.timestamp()) } except Exception as e: return self.__handle_exception(e) # API: passID.login @passidapi def login(self, uid: str, cid: str, csigs: List[str], dg1: str = None) -> dict: """ It returns back session key and session expiration time. :param uid: User id :param cid: Challenge id :param csigs: Challenge signatures :return: 'session_key' - base64 encoded session key 'expires' - unix timestamp of time when session will expire """ try: uid = try_deser(lambda: proto.UserId.fromBase64(uid)) cid = try_deser(lambda: proto.CID.fromhex(cid)) csigs = _b64csigs_to_bcsigs(csigs) if dg1 is not None: dg1 = try_deser(lambda: ef.DG1.load(b64decode(dg1))) sk, set = self._proto.login(uid, cid, csigs, dg1) return { "session_key": sk.toBase64(), "expires": int(set.timestamp()) } except Exception as e: return self.__handle_exception(e) # API: passID.sayHello @passidapi def sayHello(self, uid: str, mac: str) -> dict: """ It returns back greeting message based on whether user is anonymous or not. :param uid: User id :param mac: session mac over api name and uid :return: 'msg' - greeting message """ try: uid = try_deser(lambda: proto.UserId.fromBase64(uid)) mac = try_deser(lambda: b64decode(mac)) msg = self._proto.sayHello(uid, mac) return {"msg": msg} except Exception as e: return self.__handle_exception(e) # Request handler @Request.application def __create_calls(self, request): """Create API calls""" response = JRPCRespMgr.handle(request.data, self._req_disp) if response is not None: return Response(response.json, mimetype='application/json') return Response() def __handle_exception(self, e: Exception) -> dict: if isinstance(e, proto.ProtoError): self._log.debug("Request proto error: {}".format(e)) raise JSONRPCDispatchException(e.code, str(e)) if isinstance(e, proto.SeEntryNotFound): self._log.debug("Request storage error: {}".format(e)) raise JSONRPCDispatchException(404, str(e)) self._log.error("Unhandled exception encountered, e={}".format(e)) raise JSONRPCDispatchException(500, "Internal Server Error") def __init_api(self): self._req_disp = Dispatcher() def add_api_meth(api_f, name): # method format: <api_prefix>.<methodName> passid_api_f = lambda *args, **kwargs: api_f(self, *args, **kwargs) self._req_disp.add_method( passid_api_f, "{}.{}".format(PassIdApiServer.api_method_prefix, name)) # register methods with @passidapi decorator as rpc api handler import inspect meths = inspect.getmembers(PassIdApiServer, predicate=inspect.isfunction) for m in meths: if m[1].__name__ == "wrapped_api_f": add_api_meth(m[1], m[0]) def __log_api_call(self, f, **kwargs): if self._log.level <= log.VERBOSE: self._log.debug(":{}() ==>".format(f.__name__)) for a, v in kwargs.items(): self._log.verbose(" {}: {}".format(a, v)) def __log_api_response(self, f, resp: dict): if self._log.level <= log.VERBOSE: self._log.debug(":{}() <==".format(f.__name__)) if (resp is not None): for a, v in resp.items(): self._log.verbose(" {}: {}".format(a, v))
def __init__(self, server, connection) -> None: super().__init__() self.__server = server # type: LanguageTCPServer self.__connection = connection self.__reader = connection.makefile('r') self.__writer = connection.makefile('w') self.__workspace = None dispatcher = Dispatcher() self.dispatcher = dispatcher dispatcher.add_method(self.initialize) dispatcher.add_method(self.initialized) dispatcher.add_method(self.workspace_change_config, 'workspace/didChangeConfiguration') dispatcher.add_method(self.text_document_open, 'textDocument/didOpen') dispatcher.add_method(self.text_document_change, 'textDocument/didChange') dispatcher.add_method(self.text_document_close, 'textDocument/didClose') dispatcher.add_method(self.text_document_completion, 'textDocument/completion')
def on_dispatcher_prepare(self, dispatcher: Dispatcher): dispatcher.build_method_map(self, self.METHOD_PREFXIX)
return usr.to_dict() @classmethod def get_username(cls): if cls.user: return cls.user.name return None dispatcher = Dispatcher( { "create_chat": RPC.create_chat, "list_chats": RPC.list_chats, "create_message": RPC.create_message, "list_messages": lambda **kwargs: RPC.list_messages( kwargs["chat"], kwargs.get("start"), kwargs.get("end"), kwargs.get("last") ), "join_chat": RPC.join_chat, "register": RPC.register, "search_chats": RPC.search_chats, "get_username": RPC.get_username } ) def entry_point(request: flask.Request = None): """ Entrypoint rpc. flask view :param request: :return: """ if not request: