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 json
|
||||||
import logging
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
from inspect import signature
|
from inspect import signature
|
||||||
|
from .exceptions import *
|
||||||
PARSE_ERROR = -32700
|
|
||||||
INVALID_REQUEST = -32600
|
|
||||||
METHOD_NOT_FOUND = -32601
|
|
||||||
INVALID_PARAMS = -32602
|
|
||||||
INTERNAL_ERROR = -32603
|
|
||||||
GENERIC_APPLICATION_ERROR = -32000
|
|
||||||
|
|
||||||
|
|
||||||
class JsonRpcException(Exception):
|
log = logging.getLogger(__name__)
|
||||||
"""Исключение
|
|
||||||
"""
|
|
||||||
def __init__(self, id, code, message):
|
class Response:
|
||||||
|
def __init__(self, id: int, result):
|
||||||
self.id = id
|
self.id = id
|
||||||
self.code = code
|
self.result = result
|
||||||
self.message = message
|
|
||||||
|
|
||||||
def as_dict(self):
|
def __json__(self):
|
||||||
"""Класс в JSON словарь
|
response = {
|
||||||
"""
|
"jsonrpc": "2.0",
|
||||||
result = {
|
"result": self.result,
|
||||||
'jsonrpc':'2.0',
|
"id": self.id,
|
||||||
'id': self.id,
|
|
||||||
'error': {
|
|
||||||
'code': self.code,
|
|
||||||
'message':self.message
|
|
||||||
}
|
}
|
||||||
}
|
return response
|
||||||
return result
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return json.dumps(self.as_dict())
|
|
||||||
|
|
||||||
|
|
||||||
class Method:
|
class Method:
|
||||||
def __init__(self, function, handler = None, fields = None):
|
def __init__(self, function, pre = None):
|
||||||
self.function = function
|
self.function = function
|
||||||
self.handler = handler
|
self.pre = pre
|
||||||
self.fields = fields
|
|
||||||
|
|
||||||
def __call__(self, query):
|
def __call__(self, query):
|
||||||
if self.handler is None:
|
params = None
|
||||||
return self.function()
|
if 'params' in query:
|
||||||
result = self.handler(query, self.function)
|
params = query['params']
|
||||||
return result
|
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:
|
class JSONRPC:
|
||||||
@@ -54,23 +69,15 @@ class JSONRPC:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.methods = {}
|
self.methods = {}
|
||||||
|
|
||||||
def method(self, name: str, handler = None, fields = None):
|
def method(self, name: str, pre = None):
|
||||||
"""Декоратор метода
|
"""Декоратор метода
|
||||||
"""
|
"""
|
||||||
assert len(name) > 0, 'Не указано имя метода'
|
assert len(name) > 0, 'Не указано имя метода'
|
||||||
# logging.info('{} {}: {}'.format(
|
|
||||||
# func.__module__,
|
|
||||||
# func.__name__,
|
|
||||||
# func.__doc__
|
|
||||||
# ))
|
|
||||||
# funcname = func.__name__
|
|
||||||
# modulename = func.__module__
|
|
||||||
def wrap(function):
|
def wrap(function):
|
||||||
# print(func)
|
|
||||||
method = Method(
|
method = Method(
|
||||||
function = function,
|
function = function,
|
||||||
handler = handler,
|
pre = pre
|
||||||
fields = fields
|
|
||||||
)
|
)
|
||||||
self.methods[name] = method
|
self.methods[name] = method
|
||||||
return function
|
return function
|
||||||
@@ -127,20 +134,17 @@ class JSONRPC:
|
|||||||
"""Валидация запроса
|
"""Валидация запроса
|
||||||
"""
|
"""
|
||||||
keys = query.keys()
|
keys = query.keys()
|
||||||
logging.info(f'keys: {keys}')
|
|
||||||
if 'id' not in query:
|
if 'id' not in query:
|
||||||
return JsonRpcException(
|
return InvalidRequestError(
|
||||||
query['id'],
|
id=query['id'],
|
||||||
INVALID_REQUEST,
|
message=f'Некорректный запрос: {query}'
|
||||||
f'Некорректный запрос: {query}'
|
).__json__()
|
||||||
).as_dict()
|
|
||||||
|
|
||||||
if 'method' not in query:
|
if 'method' not in query:
|
||||||
return JsonRpcException(
|
return InvalidRequestError(
|
||||||
query['id'],
|
id=query['id'],
|
||||||
INVALID_REQUEST,
|
message=f'Некорректный запрос: {query}'
|
||||||
f'Некорректный запрос: {query}'
|
).__json__()
|
||||||
).as_dict()
|
|
||||||
|
|
||||||
def process(self, query):
|
def process(self, query):
|
||||||
"""Выполнение метода
|
"""Выполнение метода
|
||||||
@@ -148,58 +152,36 @@ class JSONRPC:
|
|||||||
self.validate(query)
|
self.validate(query)
|
||||||
name = query['method']
|
name = query['method']
|
||||||
if name not in self.methods:
|
if name not in self.methods:
|
||||||
return JsonRpcException(
|
result = MethodNotFoundError(
|
||||||
query['id'],
|
query['id'],
|
||||||
METHOD_NOT_FOUND,
|
message=f'Метод не найден: {name}'
|
||||||
f'Метод не найден: {name}'
|
)
|
||||||
).as_dict()
|
return result.__json__()
|
||||||
|
|
||||||
|
|
||||||
method = self.methods[name]
|
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:
|
try:
|
||||||
if method.handler is None:
|
response = method(query)
|
||||||
pass
|
except JSONRPCError as e:
|
||||||
else:
|
log.error(traceback.format_exc())
|
||||||
method.handler(
|
# print(traceback.format_exc())
|
||||||
query,
|
response = traceback.format_exc()
|
||||||
method.function
|
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:
|
else:
|
||||||
return JsonRpcException(
|
response = Response(
|
||||||
query['id'],
|
id=query['id'],
|
||||||
INVALID_PARAMS,
|
result=response
|
||||||
'Invalid params: {0}'.format(params)
|
|
||||||
)
|
)
|
||||||
except BaseException as e:
|
result = response.__json__()
|
||||||
result = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": query['id'],
|
|
||||||
"error": {
|
|
||||||
"message": str(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
result = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": query['id'],
|
|
||||||
"result": response
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def __call__(self, queries):
|
def __call__(self, queries):
|
||||||
"""Вызов метода
|
"""Вызов метода
|
||||||
"""
|
"""
|
||||||
@@ -221,8 +203,8 @@ class JSONRPC:
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.methods)
|
return len(self.methods)
|
||||||
|
|
||||||
def __setitem__(self, key, function, handler = None, fields = None):
|
def __setitem__(self, key, function, pre=None):
|
||||||
method = Method(function = function, handler = None, fields = None)
|
method = Method(function=function, pre=pre)
|
||||||
self.methods[key] = method
|
self.methods[key] = method
|
||||||
|
|
||||||
def __delitem__(self, key):
|
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
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = jsonrpc
|
name = jsonrpc
|
||||||
version = 0.2.0
|
version = 0.3.0
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -5,7 +5,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='jsonrpc',
|
name='jsonrpc',
|
||||||
version='0.2.0',
|
version='0.3.0',
|
||||||
author='RemiZOffAlex',
|
author='RemiZOffAlex',
|
||||||
author_email='remizoffalex@gmail.com',
|
author_email='remizoffalex@gmail.com',
|
||||||
packages=find_packages(exclude=['prototypes', 'tests']),
|
packages=find_packages(exclude=['prototypes', 'tests']),
|
||||||
|
|||||||
Reference in New Issue
Block a user