Skip to content

Commit 2a091b4

Browse files
committed
misc updates
- Support custom json encoder for serializing response data - Support registering global decorators for jsonrpc methods - Support custom method prefix for Dispatcher.add_class - Support explicitly exporting subset of class methods with Dispatcher.add_class
1 parent a0bf414 commit 2a091b4

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

jsonrpc/backend/flask.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020

2121
class JSONRPCAPI(object):
22-
def __init__(self, dispatcher=None, check_content_type=True):
22+
def __init__(self, dispatcher=None, check_content_type=True,
23+
json_encoder=None):
2324
"""
2425
2526
:param dispatcher: methods dispatcher
@@ -31,6 +32,7 @@ def __init__(self, dispatcher=None, check_content_type=True):
3132
self.dispatcher = dispatcher if dispatcher is not None \
3233
else Dispatcher()
3334
self.check_content_type = check_content_type
35+
self.json_encoder = json_encoder or DatetimeDecimalEncoder
3436

3537
def as_blueprint(self, name=None):
3638
blueprint = Blueprint(name if name else str(uuid4()), __name__)
@@ -83,9 +85,9 @@ def _get_request_str(self):
8385
return request.data
8486
return list(request.form.keys())[0]
8587

86-
@staticmethod
87-
def _serialize(s):
88-
return json.dumps(s, cls=DatetimeDecimalEncoder)
88+
# @staticmethod
89+
def _serialize(self, s):
90+
return json.dumps(s, cls=self.json_encoder)
8991

9092

9193
api = JSONRPCAPI()

jsonrpc/dispatcher.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
55
"""
66
import collections
7+
from functools import wraps
78

89

910
class Dispatcher(collections.MutableMapping):
@@ -27,6 +28,7 @@ def __init__(self, prototype=None):
2728
None
2829
2930
"""
31+
self._decorators = []
3032
self.method_map = dict()
3133

3234
if prototype is not None:
@@ -36,7 +38,7 @@ def __getitem__(self, key):
3638
return self.method_map[key]
3739

3840
def __setitem__(self, key, value):
39-
self.method_map[key] = value
41+
self.method_map[key] = self._wrap_method(value)
4042

4143
def __delitem__(self, key):
4244
del self.method_map[key]
@@ -50,8 +52,24 @@ def __iter__(self):
5052
def __repr__(self):
5153
return repr(self.method_map)
5254

55+
def register_decorator(self, a):
56+
self._decorators.extend(a if hasattr(a, '__iter__') else [a])
57+
58+
def _wrap_method(self, f):
59+
@wraps(f)
60+
def _method(*args, **kwargs):
61+
nf = f
62+
for deco in reversed(self._decorators):
63+
nf = deco(nf)
64+
return nf(*args, **kwargs)
65+
66+
return _method
67+
5368
def add_class(self, cls):
54-
prefix = cls.__name__.lower() + '.'
69+
if hasattr(cls, 'rpc_method_prefix'):
70+
prefix = cls.rpc_method_prefix + '.'
71+
else:
72+
prefix = cls.__name__.lower() + '.'
5573
self.build_method_map(cls(), prefix)
5674

5775
def add_object(self, obj):
@@ -94,7 +112,7 @@ def mymethod(*args, **kwargs):
94112
print(args, kwargs)
95113
96114
"""
97-
self.method_map[name or f.__name__] = f
115+
self[name or f.__name__] = f
98116
return f
99117

100118
def build_method_map(self, prototype, prefix=''):
@@ -112,10 +130,19 @@ def build_method_map(self, prototype, prefix=''):
112130
Prefix of methods
113131
114132
"""
133+
rpc_exports = getattr(prototype, 'rpc_exports', None)
134+
135+
def _should_export(method):
136+
if method.startswith('_'):
137+
return False
138+
if rpc_exports is None:
139+
return True
140+
return method in rpc_exports
141+
115142
if not isinstance(prototype, dict):
116143
prototype = dict((method, getattr(prototype, method))
117144
for method in dir(prototype)
118-
if not method.startswith('_'))
145+
if _should_export(method))
119146

120147
for attr, method in prototype.items():
121148
if callable(method):

jsonrpc/tests/test_dispatcher.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ def test_to_dict(self):
9090
d = Dispatcher()
9191

9292
def func():
93-
return ""
93+
return "x"
9494

9595
d["method"] = func
96-
self.assertEqual(dict(d), {"method": func})
96+
self.assertEqual(dict(d)["method"](), "x")
9797

9898
def test_init_from_object_instance(self):
9999

0 commit comments

Comments
 (0)