"""
Make benchmarkstt available through a rudimentary JSON-RPC_ interface
.. attention::
Only supported for Python versions 3.6 and above
.. _JSON-RPC: https://www.jsonrpc.org
"""
import jsonrpcserver
import os
from flask import Flask, request, Response, render_template
from benchmarkstt.docblock import format_docs, parse, process_rst
from benchmarkstt.api.jsonrpc import get_methods
[docs]def argparser(parser):
"""
Adds the help and arguments specific to this module
"""
parser.add_argument('--debug', action='store_true',
help='Run in debug mode')
parser.add_argument('--host',
help='Hostname or ip to serve api')
parser.add_argument('--port', type=int, default=8080,
help='Port used by the server')
parser.add_argument('--entrypoint', default='/api',
help='The jsonrpc api address')
parser.add_argument('--list-methods', action='store_true',
help='List the available jsonrpc methods')
parser.add_argument('--with-explorer', action='store_true',
help='Also create the explorer to test api calls with, '
'this is a rudimentary feature currently '
'only meant for testing and debugging.\n'
'Warning: the API explorer is provided as-is, without any tests '
'or code reviews. This is marked as a low-priority feature.')
return parser
[docs]def create_app(entrypoint: str = None, with_explorer: bool = None):
"""
Create the Flask app
:param entrypoint: The HTTP path on which the api will be served
:param bool with_explorer: Whether to also serve the JSON-RPC API explorer
:return:
"""
template_folder = os.path.abspath(os.path.join(
__file__,
os.pardir,
os.pardir,
os.pardir,
'api',
'templates'
))
app = Flask(__name__, template_folder=template_folder)
if entrypoint is None:
entrypoint = '/api'
methods = get_methods()
@app.route(entrypoint, methods=["POST"])
def jsonrpc():
req = request.get_data().decode()
response = jsonrpcserver.dispatch(req, methods=methods, debug=True, convert_camel_case=False)
response_str = str(response)
return Response(response_str, response.http_status, mimetype="application/json")
if with_explorer: # pragma: nocover
app.template_filter('parse_rst')(process_rst)
@app.route(entrypoint, methods=['GET'])
def explorer():
split_methods = {}
individual_methods = []
for name, func in methods.items.items():
id_ = name.replace('.', '-')
cat = 'METHODS'
splitted = name.split('.', 1)
if len(splitted) == 2:
cat = splitted[0]
item = dict(id=id_, name=name, details=parse(func))
individual_methods.append(item)
if cat not in split_methods:
split_methods[cat] = []
split_methods[cat].append(item)
return render_template('api-explorer.html', grouped_methods=split_methods, methods=individual_methods)
return app
[docs]def run(_parser, args): # pragma: nocover
if args.list_methods:
methods = get_methods()
for name, func in methods.items.items():
print('%s\n%s' % (name, '-' * len(name)))
print('')
print(format_docs(func.__doc__))
print('')
else:
app = create_app(args.entrypoint, args.with_explorer)
app.run(host=args.host, port=args.port, debug=args.debug)