Automated update of Base Application package.
This commit is contained in:
parent
0f1495c5bd
commit
cd450dba57
BIN
dist/app-1.0.0-py3-none-any.whl
vendored
BIN
dist/app-1.0.0-py3-none-any.whl
vendored
Binary file not shown.
BIN
dist/app-1.0.0.tar.gz
vendored
BIN
dist/app-1.0.0.tar.gz
vendored
Binary file not shown.
151
src/app/rpc.py
151
src/app/rpc.py
@ -1,31 +1,37 @@
|
||||
|
||||
from xmlrpc.server import resolve_dotted_attribute
|
||||
from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode, ServerProxy,MultiCall
|
||||
from functools import partial
|
||||
from inspect import signature
|
||||
from aiohttp import web
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
from xmlrpc.client import (
|
||||
Fault,
|
||||
MultiCall,
|
||||
ServerProxy,
|
||||
dumps,
|
||||
loads,
|
||||
)
|
||||
from xmlrpc.server import resolve_dotted_attribute
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
|
||||
class AsyncSimpleXMLRPCDispatcher:
|
||||
"""
|
||||
Original not async version of this class is in the original python std lib:
|
||||
https://github.com/python/cpython/blob/main/Lib/xmlrpc/server.py.
|
||||
|
||||
|
||||
use_builtin_types=True allows the use of bytes-object which is preferred
|
||||
because else it's a custom xmlrpc.client.Binary which sucks.
|
||||
"""
|
||||
|
||||
def __init__(self, instance,allow_none=True, encoding="utf-8", use_builtin_types=True):
|
||||
def __init__(
|
||||
self, instance, allow_none=True, encoding="utf-8", use_builtin_types=True
|
||||
):
|
||||
self.setup_rpc(allow_none=allow_none, encoding=encoding, use_builtin_types=True)
|
||||
self.register_instance(instance,True)
|
||||
self.register_instance(instance, True)
|
||||
|
||||
def setup_rpc(self, allow_none=True, encoding="utf-8",
|
||||
use_builtin_types=True):
|
||||
def setup_rpc(self, allow_none=True, encoding="utf-8", use_builtin_types=True):
|
||||
self.funcs = {}
|
||||
self.instance = None
|
||||
self.allow_none = allow_none
|
||||
self.encoding = encoding or 'utf-8'
|
||||
self.encoding = encoding or "utf-8"
|
||||
self.use_builtin_types = use_builtin_types
|
||||
|
||||
def register_instance(self, instance, allow_dotted_names=True):
|
||||
@ -45,14 +51,18 @@ class AsyncSimpleXMLRPCDispatcher:
|
||||
return function
|
||||
|
||||
def register_introspection_functions(self):
|
||||
self.funcs.update({'system.listMethods' : self.system_listMethods,
|
||||
'system.methodSignature' : self.system_methodSignature,
|
||||
'system.methodHelp' : self.system_methodHelp})
|
||||
self.funcs.update(
|
||||
{
|
||||
"system.listMethods": self.system_listMethods,
|
||||
"system.methodSignature": self.system_methodSignature,
|
||||
"system.methodHelp": self.system_methodHelp,
|
||||
}
|
||||
)
|
||||
|
||||
def register_multicall_functions(self):
|
||||
self.funcs.update({'system.multicall' : self.system_multicall})
|
||||
self.funcs.update({"system.multicall": self.system_multicall})
|
||||
|
||||
async def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
|
||||
async def _marshaled_dispatch(self, data, dispatch_method=None, path=None):
|
||||
try:
|
||||
params, method = loads(data, use_builtin_types=self.use_builtin_types)
|
||||
|
||||
@ -61,45 +71,47 @@ class AsyncSimpleXMLRPCDispatcher:
|
||||
else:
|
||||
response = await self._dispatch(method, params)
|
||||
response = (response,)
|
||||
response = dumps(response, methodresponse=1,
|
||||
allow_none=self.allow_none, encoding=self.encoding)
|
||||
response = dumps(
|
||||
response,
|
||||
methodresponse=1,
|
||||
allow_none=self.allow_none,
|
||||
encoding=self.encoding,
|
||||
)
|
||||
except Fault as fault:
|
||||
response = dumps(fault, allow_none=self.allow_none,
|
||||
encoding=self.encoding)
|
||||
response = dumps(fault, allow_none=self.allow_none, encoding=self.encoding)
|
||||
except BaseException as exc:
|
||||
response = dumps(
|
||||
Fault(1, "%s:%s" % (type(exc), exc)),
|
||||
encoding=self.encoding, allow_none=self.allow_none,
|
||||
)
|
||||
Fault(1, f"{type(exc)}:{exc}"),
|
||||
encoding=self.encoding,
|
||||
allow_none=self.allow_none,
|
||||
)
|
||||
|
||||
return response.encode(self.encoding, 'xmlcharrefreplace')
|
||||
return response.encode(self.encoding, "xmlcharrefreplace")
|
||||
|
||||
def system_listMethods(self):
|
||||
methods = set(self.funcs.keys())
|
||||
if self.instance is not None:
|
||||
if hasattr(self.instance, '_listMethods'):
|
||||
if hasattr(self.instance, "_listMethods"):
|
||||
methods |= set(self.instance._listMethods())
|
||||
elif not hasattr(self.instance, '_dispatch'):
|
||||
elif not hasattr(self.instance, "_dispatch"):
|
||||
methods |= set(list_public_methods(self.instance))
|
||||
return sorted(methods)
|
||||
|
||||
def system_methodSignature(self, method_name):
|
||||
return 'signatures not supported'
|
||||
return "signatures not supported"
|
||||
|
||||
def system_methodHelp(self, method_name):
|
||||
method = None
|
||||
if method_name in self.funcs:
|
||||
method = self.funcs[method_name]
|
||||
elif self.instance is not None:
|
||||
if hasattr(self.instance, '_methodHelp'):
|
||||
if hasattr(self.instance, "_methodHelp"):
|
||||
return self.instance._methodHelp(method_name)
|
||||
elif not hasattr(self.instance, '_dispatch'):
|
||||
elif not hasattr(self.instance, "_dispatch"):
|
||||
try:
|
||||
method = resolve_dotted_attribute(
|
||||
self.instance,
|
||||
method_name,
|
||||
self.allow_dotted_names
|
||||
)
|
||||
self.instance, method_name, self.allow_dotted_names
|
||||
)
|
||||
except AttributeError:
|
||||
pass
|
||||
if method is None:
|
||||
@ -110,21 +122,17 @@ class AsyncSimpleXMLRPCDispatcher:
|
||||
async def system_multicall(self, call_list):
|
||||
results = []
|
||||
for call in call_list:
|
||||
method_name = call['methodName']
|
||||
params = call['params']
|
||||
method_name = call["methodName"]
|
||||
params = call["params"]
|
||||
|
||||
try:
|
||||
results.append([await self._dispatch(method_name, params)])
|
||||
except Fault as fault:
|
||||
results.append(
|
||||
{'faultCode' : fault.faultCode,
|
||||
'faultString' : fault.faultString}
|
||||
)
|
||||
{"faultCode": fault.faultCode, "faultString": fault.faultString}
|
||||
)
|
||||
except BaseException as exc:
|
||||
results.append(
|
||||
{'faultCode' : 1,
|
||||
'faultString' : "%s:%s" % (type(exc), exc)}
|
||||
)
|
||||
results.append({"faultCode": 1, "faultString": f"{type(exc)}:{exc}"})
|
||||
return results
|
||||
|
||||
async def _dispatch(self, method, params):
|
||||
@ -135,17 +143,15 @@ class AsyncSimpleXMLRPCDispatcher:
|
||||
else:
|
||||
if func is not None:
|
||||
return await func(*params)
|
||||
raise Exception('method "%s" is not supported' % method)
|
||||
raise Exception(f'method "{method}" is not supported')
|
||||
|
||||
if self.instance is not None:
|
||||
if hasattr(self.instance, '_dispatch'):
|
||||
if hasattr(self.instance, "_dispatch"):
|
||||
return await self.instance._dispatch(method, params)
|
||||
|
||||
try:
|
||||
func = resolve_dotted_attribute(
|
||||
self.instance,
|
||||
method,
|
||||
self.allow_dotted_names
|
||||
self.instance, method, self.allow_dotted_names
|
||||
)
|
||||
except AttributeError:
|
||||
pass
|
||||
@ -153,20 +159,21 @@ class AsyncSimpleXMLRPCDispatcher:
|
||||
if func is not None:
|
||||
return await func(*params)
|
||||
|
||||
raise Exception('method "%s" is not supported' % method)
|
||||
raise Exception(f'method "{method}" is not supported')
|
||||
|
||||
|
||||
def rpc_wrap_instance(obj):
|
||||
|
||||
class Session:
|
||||
|
||||
def __init__(self,data=None):
|
||||
def __init__(self, data=None):
|
||||
self._data = data or {}
|
||||
|
||||
async def get(self, key, default=None):
|
||||
return self._data.get(key,default)
|
||||
return self._data.get(key, default)
|
||||
|
||||
async def set(self,key, value):
|
||||
self._data[key] = value
|
||||
async def set(self, key, value):
|
||||
self._data[key] = value
|
||||
|
||||
async def delete(self, key):
|
||||
try:
|
||||
@ -175,39 +182,35 @@ def rpc_wrap_instance(obj):
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
async def exists(self,key):
|
||||
async def exists(self, key):
|
||||
return key in self._data
|
||||
|
||||
class Instance:
|
||||
|
||||
def __init__(self, _self):
|
||||
self._self = self
|
||||
self.session = Session()
|
||||
|
||||
def __get__(self,key):
|
||||
return getattr(self._self,key)
|
||||
|
||||
def ping(self,*args,**kwargs):
|
||||
return dict(
|
||||
args=args,
|
||||
kwargs=kwargs,
|
||||
timestamp=str(datetime.now())
|
||||
)
|
||||
def __init__(self, _self):
|
||||
self._self = self
|
||||
self.session = Session()
|
||||
|
||||
def __get__(self, key):
|
||||
return getattr(self._self, key)
|
||||
|
||||
def ping(self, *args, **kwargs):
|
||||
return {"args": args, "kwargs": kwargs, "timestamp": str(datetime.now())}
|
||||
|
||||
instance = Instance(obj)
|
||||
|
||||
for attr in dir(obj):
|
||||
if attr == 'rpc_handler':
|
||||
if attr == "rpc_handler":
|
||||
continue
|
||||
if attr.startswith("rpc_") and callable(getattr(obj, attr)):
|
||||
setattr(instance,attr[4:], getattr(obj,attr))
|
||||
setattr(instance, attr[4:], getattr(obj, attr))
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class Application(web.Application):
|
||||
|
||||
def __init__(self, url=None,host=None,port=None, *args, **kwargs):
|
||||
def __init__(self, url=None, host=None, port=None, *args, **kwargs):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self._url = url
|
||||
@ -221,14 +224,14 @@ class Application(web.Application):
|
||||
|
||||
def __get__(self, key):
|
||||
if self._rpc:
|
||||
return getattr(self._rpc,key)
|
||||
return getattr(self.arpc,key)
|
||||
return getattr(self._rpc, key)
|
||||
return getattr(self.arpc, key)
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
if self._url:
|
||||
return self._url
|
||||
return "http://{}:{}".format(self.host,self.port)
|
||||
return self._url
|
||||
return f"http://{self.host}:{self.port}"
|
||||
|
||||
@property
|
||||
def rpc_url(self):
|
||||
|
Loading…
Reference in New Issue
Block a user