Permalink
Browse files

Add helpers, some tests and sysout in debug

  • Loading branch information...
1 parent 44868d9 commit 0bd8afb70a55866d10ef564cfcba5a6f34bffad7 @nycholas nycholas committed Dec 15, 2012
Showing with 198 additions and 25 deletions.
  1. +13 −8 flask_jsonrpc/__init__.py
  2. +26 −0 flask_jsonrpc/helpers.py
  3. +1 −1 flask_jsonrpc/proxy.py
  4. +7 −16 flask_jsonrpc/site.py
  5. +151 −0 flask_jsonrpc_tests.py
View
@@ -8,10 +8,11 @@
from collections import OrderedDict
-from flask import request, jsonify
+from flask import current_app, request, jsonify
from flask_jsonrpc.site import jsonrpc_site
-from flask_jsonrpc.types import Object, Number, Boolean, String, Array, Nil, Any
+from flask_jsonrpc.helpers import jsonify_status_code, extract_raw_data_request
+from flask_jsonrpc.types import Object, Number, Boolean, String, Array, Nil, Any, Type
from flask_jsonrpc.exceptions import (Error, ParseError, InvalidRequestError,
MethodNotFoundError, InvalidParamsError,
ServerError, RequestPostError,
@@ -130,14 +131,18 @@ def _inject_args(sig, types):
return sig
def _site_api(method=''):
- response_dict = default_site.dispatch(request, method)
- return jsonify(response_dict)
+ response_dict, status_code = default_site.dispatch(request, method)
+ if current_app.config['DEBUG']:
+ print('\n ++ data request')
+ print('>> request: {}'.format(extract_raw_data_request(request)))
+ print('<< response: {}, {}'.format(status_code, response_dict))
+ return jsonify_status_code(status_code, response_dict), status_code
class JSONRPC(object):
- def __init__(self, app=None, rule='/api', site=default_site):
- self.rule = rule
+ def __init__(self, app=None, service_url='/api', site=default_site):
+ self.service_url = service_url
self.site = site
if app is not None:
self.app = app
@@ -146,8 +151,8 @@ def __init__(self, app=None, rule='/api', site=default_site):
self.app = None
def init_app(self, app):
- app.add_url_rule(self.rule, '', _site_api, methods=['POST'])
- app.add_url_rule(self.rule + '/<method>', '', _site_api, methods=['GET'])
+ app.add_url_rule(self.service_url, '', _site_api, methods=['POST'])
+ app.add_url_rule(self.service_url + '/<method>', '', _site_api, methods=['GET'])
def method(self, name, authenticated=False, safe=False, validate=False, **options):
def decorator(f):
View
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012, Cenobit Technologies, Inc. http://cenobit.es/
+# All rights reserved.
+from flask import current_app, request, jsonify
+
+def jsonify_status_code(status_code, *args, **kw):
+ """Returns a jsonified response with the specified HTTP status code.
+
+ The positional and keyword arguments are passed directly to the
+ :func:`flask.jsonify` function which creates the response.
+
+ """
+ response = jsonify(*args, **kw)
+ response.status_code = status_code
+ return response
+
+def extract_raw_data_request(request):
+ if request.method == 'GET':
+ return request.query_string
+ elif request.method == 'POST':
+ if request.data:
+ return request.data
+ elif request.form.to_dict():
+ #return '&'.join(['{}={}'.format(k,v) for k,v in request.form.to_dict().items()])
+ return request.form.to_dict().keys()[0]
+ return ''
View
@@ -7,7 +7,7 @@
from flask import json, current_app
-from flask_jsonrpc.types import Object, Number, Boolean, String, Array, Nil, Any
+from flask_jsonrpc.types import Object, Any
class ServiceProxy(object):
View
@@ -9,7 +9,8 @@
from flask import json, jsonify, current_app, got_request_exception
-from flask_jsonrpc.types import Object, Number, Boolean, String, Array, Nil, Any
+from flask_jsonrpc.helpers import extract_raw_data_request
+from flask_jsonrpc.types import Object, Array, Any
from flask_jsonrpc.exceptions import (Error, ParseError, InvalidRequestError,
MethodNotFoundError, InvalidParamsError,
ServerError, RequestPostError,
@@ -107,15 +108,6 @@ def extract_id_request(self, raw_data):
return g1 if g1 else g2
return None
- def extract_raw_data_request(self, request):
- if request.method == 'GET':
- return request.query_string
- elif request.method == 'POST':
- if request.data:
- return request.data
- return request.form.keys()[0]
- return ''
-
def empty_response(self, version='1.0'):
resp = {'id': None}
if version == '1.1':
@@ -152,7 +144,7 @@ def response_dict(self, request, D, is_batch=False, version_hint='1.0'):
try:
# params: An Array or Object, that holds the actual parameter values
# for the invocation of the procedure. Can be omitted if empty.
- if 'params' not in D:
+ if 'params' not in D or not D['params']:
D['params'] = []
if 'method' not in D or 'params' not in D:
raise InvalidParamsError('Request requires str:"method" and list:"params"')
@@ -223,7 +215,7 @@ def dispatch(self, request, method=''):
# in case we do something json doesn't like, we always get back valid
# json-rpc response
response = self.empty_response()
- raw_data = self.extract_raw_data_request(request)
+ raw_data = extract_raw_data_request(request)
try:
if request.method == 'GET':
@@ -245,9 +237,8 @@ def dispatch(self, request, method=''):
else:
response, status = self.response_dict(request, D)
if response is None and (not u'id' in D or D[u'id'] is None): # a notification
- response = {}
- response['status'] = status
- return response
+ response = ''
+ return response, status
except Error, e:
#got_request_exception.send(sender=self.__class__, request=request)
@@ -267,7 +258,7 @@ def dispatch(self, request, method=''):
json_request_id = self.extract_id_request(raw_data)
response['id'] = json_request_id
- return response
+ return response, status
def procedure_desc(self, key):
M = self.urls[key]
View
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012, Cenobit Technologies, Inc. http://cenobit.es/
+# All rights reserved.
+import os
+import uuid
+import unittest
+import tempfile
+
+from flask import json
+
+from flask_jsonrpc.proxy import ServiceProxy
+from run import app, jsonrpc
+
+@jsonrpc.method('jsonrpc.echo')
+def echo(name='Flask JSON-RPC'):
+ return 'Hello {}'.format(name)
+
+@jsonrpc.method('jsonrpc.notify')
+def notify(string):
+ pass
+
+@jsonrpc.method('jsonrpc.fails')
+def fails(string):
+ raise IndexError
+
+@jsonrpc.method('jsonrpc.strangeEcho')
+def strangeEcho(string, omg, wtf, nowai, yeswai='Default'):
+ return [string, omg, wtf, nowai, yeswai]
+
+@jsonrpc.method('jsonrpc.safeEcho', safe=True)
+def safeEcho(string):
+ return string
+
+@jsonrpc.method('jsonrpc.strangeSafeEcho', safe=True)
+def strangeSafeEcho(*args, **kwargs):
+ return strangeEcho(*args, **kwargs)
+
+@jsonrpc.method('jsonrpc.checkedEcho(string=str, string2=str) -> str', safe=True, validate=True)
+def protectedEcho(string, string2):
+ return string + string2
+
+@jsonrpc.method('jsonrpc.checkedArgsEcho(string=str, string2=str)', validate=True)
+def protectedArgsEcho(string, string2):
+ return string + string2
+
+@jsonrpc.method('jsonrpc.checkedReturnEcho() -> String', validate=True)
+def protectedReturnEcho():
+ return 'this is a string'
+
+@jsonrpc.method('jsonrpc.authCheckedEcho(Object, Array) -> Object', validate=True)
+def authCheckedEcho(obj1, arr1):
+ return {'obj1': obj1, 'arr1': arr1}
+
+@jsonrpc.method('jsonrpc.varArgs(String, String, str3=String) -> Array', validate=True)
+def checkedVarArgsEcho(*args, **kw):
+ return list(args) + kw.values()
+
+
+class FlaskJSONRPCTestCase(unittest.TestCase):
+
+ def setUp(self):
+ app.config['DEBUG'] = True
+ app.config['TESTING'] = True
+ self.app = app.test_client()
+ self.service_url = jsonrpc.service_url
+
+ def tearDown(self):
+ pass
+
+ def _make_payload(self, method, params=None, version='1.0', is_notify=False):
+ return json.dumps({
+ 'jsonrpc': version,
+ 'method': method,
+ 'params': params if params else [],
+ 'id': None if is_notify else str(uuid.uuid1())
+ })
+
+ def _call(self, req):
+ return json.loads((self.app.post(self.service_url, data=req)).data)
+
+ def _assert_equals(self, resp, st):
+ assert st == resp, '{} != {}'.format(st, resp)
+
+ def test_echo(self):
+ R = [[
+ (self._make_payload('jsonrpc.echo', version=v), 'Hello Flask JSON-RPC'),
+ (self._make_payload('jsonrpc.echo', ['Flask'], version=v), 'Hello Flask'),
+ (self._make_payload('jsonrpc.echo', None, version=v), 'Hello Flask JSON-RPC'),
+ (self._make_payload('jsonrpc.echo', [], version=v), 'Hello Flask JSON-RPC'),
+ (self._make_payload('jsonrpc.echo', {}, version=v), 'Hello Flask JSON-RPC'),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_notify(self):
+ R = [[
+ (self._make_payload('jsonrpc.notify', ['this is a string'], version=v, is_notify=True), ''),
+ ] for v in ['2.0']][0]
+ [self._assert_equals((self.app.post(self.service_url, data=req)).data, resp) for req, resp in R]
+
+ def test_strangeEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.strangeEcho', {u'1': u'this is a string', u'2': u'this is omg', u'wtf': u'pants', u'nowai': 'nopants'}, version=v), ['1', '2', 'wtf', 'nowai', 'Default']),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_safeEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.safeEcho', [u'this is string'], version=v), 'this is string'),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_strangeSafeEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.strangeSafeEcho', {u'1': u'this is a string', u'2': u'this is omg', u'wtf': u'pants', u'nowai': 'nopants'}, version=v), ['1', '2', 'wtf', 'nowai', 'Default']),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_protectedEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.checkedEcho', ['hai', 'hai'], version=v), 'haihai'),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_protectedArgsEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.checkedArgsEcho', ['hai', 'hai'], version=v), 'haihai'),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_protectedReturnEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.checkedReturnEcho', [], version=v), 'this is a string'),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_authCheckedEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.authCheckedEcho', [1.0, [1,2,3]], version=v), {'obj1': 1.0, 'arr1': [1,2,3]}),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+ def test_checkedVarArgsEcho(self):
+ R = [[
+ (self._make_payload('jsonrpc.varArgs', ['hai', 'hai', ' -> \o/'], version=v), ['hai', 'hai', ' -> \o/']),
+ ] for v in ['1.0', '1.1', '2.0']][0]
+ [self._assert_equals(self._call(req)['result'], resp) for req, resp in R]
+
+
+if __name__ == '__main__':
+ unittest.main()

0 comments on commit 0bd8afb

Please sign in to comment.