Update to 0.3.0
This commit is contained in:
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
|
||||
# Distribution / packaging
|
||||
build/
|
||||
dist/
|
||||
jsonrpc.egg-info/
|
||||
|
||||
prototypes/
|
||||
.tox/
|
||||
tests/
|
||||
@@ -1,51 +1,66 @@
|
||||
import json
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from inspect import signature
|
||||
|
||||
PARSE_ERROR = -32700
|
||||
INVALID_REQUEST = -32600
|
||||
METHOD_NOT_FOUND = -32601
|
||||
INVALID_PARAMS = -32602
|
||||
INTERNAL_ERROR = -32603
|
||||
GENERIC_APPLICATION_ERROR = -32000
|
||||
from .exceptions import *
|
||||
|
||||
|
||||
class JsonRpcException(Exception):
|
||||
"""Исключение
|
||||
"""
|
||||
def __init__(self, id, code, message):
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Response:
|
||||
def __init__(self, id: int, result):
|
||||
self.id = id
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.result = result
|
||||
|
||||
def as_dict(self):
|
||||
"""Класс в JSON словарь
|
||||
"""
|
||||
result = {
|
||||
'jsonrpc':'2.0',
|
||||
'id': self.id,
|
||||
'error': {
|
||||
'code': self.code,
|
||||
'message':self.message
|
||||
def __json__(self):
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"result": self.result,
|
||||
"id": self.id,
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
def __str__(self):
|
||||
return json.dumps(self.as_dict())
|
||||
return response
|
||||
|
||||
|
||||
class Method:
|
||||
def __init__(self, function, handler = None, fields = None):
|
||||
def __init__(self, function, pre = None):
|
||||
self.function = function
|
||||
self.handler = handler
|
||||
self.fields = fields
|
||||
self.pre = pre
|
||||
|
||||
def __call__(self, query):
|
||||
if self.handler is None:
|
||||
return self.function()
|
||||
result = self.handler(query, self.function)
|
||||
return result
|
||||
params = None
|
||||
if 'params' in query:
|
||||
params = query['params']
|
||||
log.error(params)
|
||||
if isinstance(self.pre, list):
|
||||
pass
|
||||
elif type(self.pre).__name__=='function':
|
||||
self.pre(query)
|
||||
|
||||
|
||||
if params is None:
|
||||
response = self.function()
|
||||
elif isinstance(params, list):
|
||||
response = self.function(*params)
|
||||
elif isinstance(params, dict):
|
||||
response = self.function(**params)
|
||||
else:
|
||||
raise InvalidParamsError(
|
||||
id=query['id'],
|
||||
message='Invalid params: {0}'.format(params)
|
||||
)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}>'.format(self.function)
|
||||
|
||||
|
||||
class Wrapper:
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
|
||||
|
||||
class JSONRPC:
|
||||
@@ -54,23 +69,15 @@ class JSONRPC:
|
||||
def __init__(self):
|
||||
self.methods = {}
|
||||
|
||||
def method(self, name: str, handler = None, fields = None):
|
||||
def method(self, name: str, pre = None):
|
||||
"""Декоратор метода
|
||||
"""
|
||||
assert len(name) > 0, 'Не указано имя метода'
|
||||
# logging.info('{} {}: {}'.format(
|
||||
# func.__module__,
|
||||
# func.__name__,
|
||||
# func.__doc__
|
||||
# ))
|
||||
# funcname = func.__name__
|
||||
# modulename = func.__module__
|
||||
|
||||
def wrap(function):
|
||||
# print(func)
|
||||
method = Method(
|
||||
function = function,
|
||||
handler = handler,
|
||||
fields = fields
|
||||
pre = pre
|
||||
)
|
||||
self.methods[name] = method
|
||||
return function
|
||||
@@ -127,20 +134,17 @@ class JSONRPC:
|
||||
"""Валидация запроса
|
||||
"""
|
||||
keys = query.keys()
|
||||
logging.info(f'keys: {keys}')
|
||||
if 'id' not in query:
|
||||
return JsonRpcException(
|
||||
query['id'],
|
||||
INVALID_REQUEST,
|
||||
f'Некорректный запрос: {query}'
|
||||
).as_dict()
|
||||
return InvalidRequestError(
|
||||
id=query['id'],
|
||||
message=f'Некорректный запрос: {query}'
|
||||
).__json__()
|
||||
|
||||
if 'method' not in query:
|
||||
return JsonRpcException(
|
||||
query['id'],
|
||||
INVALID_REQUEST,
|
||||
f'Некорректный запрос: {query}'
|
||||
).as_dict()
|
||||
return InvalidRequestError(
|
||||
id=query['id'],
|
||||
message=f'Некорректный запрос: {query}'
|
||||
).__json__()
|
||||
|
||||
def process(self, query):
|
||||
"""Выполнение метода
|
||||
@@ -148,58 +152,36 @@ class JSONRPC:
|
||||
self.validate(query)
|
||||
name = query['method']
|
||||
if name not in self.methods:
|
||||
return JsonRpcException(
|
||||
result = MethodNotFoundError(
|
||||
query['id'],
|
||||
METHOD_NOT_FOUND,
|
||||
f'Метод не найден: {name}'
|
||||
).as_dict()
|
||||
message=f'Метод не найден: {name}'
|
||||
)
|
||||
return result.__json__()
|
||||
|
||||
|
||||
method = self.methods[name]
|
||||
|
||||
params = None
|
||||
if 'params' in query:
|
||||
params = query['params']
|
||||
# for key in params:
|
||||
# print(f'{key}: {type(params[key]).__name__} = {params[key]}')
|
||||
logging.debug('params: {}'.format(params))
|
||||
|
||||
try:
|
||||
if method.handler is None:
|
||||
pass
|
||||
else:
|
||||
method.handler(
|
||||
query,
|
||||
method.function
|
||||
response = method(query)
|
||||
except JSONRPCError as e:
|
||||
log.error(traceback.format_exc())
|
||||
# print(traceback.format_exc())
|
||||
response = traceback.format_exc()
|
||||
except Exception as e:
|
||||
log.error(traceback.format_exc())
|
||||
response = InternalError(
|
||||
id=query['id'],
|
||||
# message=str(e)
|
||||
message=traceback.format_exc()
|
||||
)
|
||||
if params is None:
|
||||
response = method.function()
|
||||
elif isinstance(params, list):
|
||||
response = method.function(*params)
|
||||
elif isinstance(params, dict):
|
||||
response = method.function(**params)
|
||||
else:
|
||||
return JsonRpcException(
|
||||
query['id'],
|
||||
INVALID_PARAMS,
|
||||
'Invalid params: {0}'.format(params)
|
||||
response = Response(
|
||||
id=query['id'],
|
||||
result=response
|
||||
)
|
||||
except BaseException as e:
|
||||
result = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": query['id'],
|
||||
"error": {
|
||||
"message": str(e)
|
||||
}
|
||||
}
|
||||
else:
|
||||
result = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": query['id'],
|
||||
"result": response
|
||||
}
|
||||
result = response.__json__()
|
||||
return result
|
||||
|
||||
|
||||
def __call__(self, queries):
|
||||
"""Вызов метода
|
||||
"""
|
||||
@@ -221,8 +203,8 @@ class JSONRPC:
|
||||
def __len__(self):
|
||||
return len(self.methods)
|
||||
|
||||
def __setitem__(self, key, function, handler = None, fields = None):
|
||||
method = Method(function = function, handler = None, fields = None)
|
||||
def __setitem__(self, key, function, pre=None):
|
||||
method = Method(function=function, pre=pre)
|
||||
self.methods[key] = method
|
||||
|
||||
def __delitem__(self, key):
|
||||
|
||||
74
jsonrpc/exceptions.py
Normal file
74
jsonrpc/exceptions.py
Normal file
@@ -0,0 +1,74 @@
|
||||
class JSONRPCError(Exception):
|
||||
def __init__(self, id: int, message):
|
||||
pass
|
||||
|
||||
def __json__(self):
|
||||
result = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": self.id,
|
||||
"error": {
|
||||
"code": self.CODE,
|
||||
"message": self.message
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
class InvalidRequestError(JSONRPCError):
|
||||
CODE = -32600
|
||||
|
||||
def __init__(self, id: int, message: str = 'Invalid Request'):
|
||||
self.id = id
|
||||
self.message = message
|
||||
self.code = CODE
|
||||
|
||||
|
||||
class ParseError(JSONRPCError):
|
||||
CODE = -32700
|
||||
|
||||
def __init__(self, id: int, message: str = 'Parse error'):
|
||||
self.id = id
|
||||
self.message = message
|
||||
self.code = CODE
|
||||
|
||||
|
||||
class MethodNotFoundError(JSONRPCError):
|
||||
CODE = -32601
|
||||
|
||||
def __init__(self, id: int, message: str = 'Method not found'):
|
||||
self.id = id
|
||||
self.message = message
|
||||
self.code = self.CODE
|
||||
|
||||
|
||||
class InvalidParamsError(JSONRPCError):
|
||||
CODE = -32602
|
||||
|
||||
def __init__(self, id: int, message: str = 'Invalid params'):
|
||||
self.id = id
|
||||
self.message = message
|
||||
self.code = self.CODE
|
||||
|
||||
|
||||
class InternalError(JSONRPCError):
|
||||
"""Internal JSON-RPC error
|
||||
"""
|
||||
CODE = -32603
|
||||
|
||||
def __init__(self, id: int, message: str = 'Internal error'):
|
||||
self.id = id
|
||||
self.message = message
|
||||
self.code = self.CODE
|
||||
|
||||
|
||||
class ServerError(JSONRPCError):
|
||||
"""Reserved for implementation-defined server-errors.
|
||||
|
||||
code: -32000 to -32099 Server error.
|
||||
"""
|
||||
CODE = -32000
|
||||
|
||||
def __init__(self, id: int, message: str = 'Server error'):
|
||||
self.id = id
|
||||
self.message = message
|
||||
self.code = self.CODE
|
||||
Reference in New Issue
Block a user