Skip to content

Commit

Permalink
Update jsonrpclib to 0.1.7
Browse files Browse the repository at this point in the history
  • Loading branch information
labrys committed Jun 19, 2016
1 parent 69d3605 commit 656b2c3
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 111 deletions.
47 changes: 26 additions & 21 deletions lib/jsonrpclib/SimpleJSONRPCServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
# For Windows
fcntl = None


def get_version(request):
# must be a dict
if 'jsonrpc' in request.keys():
return 2.0
if 'id' in request.keys():
return 1.0
return None



def validate_request(request):
if type(request) is not types.DictType:
if not isinstance(request, dict):
fault = Fault(
-32600, 'Request must be {}, not %s.' % type(request)
)
Expand All @@ -33,27 +35,27 @@ def validate_request(request):
version = get_version(request)
if not version:
fault = Fault(-32600, 'Request %s invalid.' % request, rpcid=rpcid)
return fault
return fault
request.setdefault('params', [])
method = request.get('method', None)
params = request.get('params')
param_types = (types.ListType, types.DictType, types.TupleType)
if not method or type(method) not in types.StringTypes or \
type(params) not in param_types:
type(params) not in param_types:
fault = Fault(
-32600, 'Invalid request parameters or method.', rpcid=rpcid
)
return fault
return True


class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher):

def __init__(self, encoding=None):
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,
allow_none=True,
encoding=encoding)
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(
self, allow_none=True, encoding=encoding)

def _marshaled_dispatch(self, data, dispatch_method = None):
def _marshaled_dispatch(self, data, dispatch_method=None):
response = None
try:
request = jsonrpclib.loads(data)
Expand All @@ -64,7 +66,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None):
if not request:
fault = Fault(-32600, 'Request invalid -- no request data.')
return fault.response()
if type(request) is types.ListType:
if isinstance(request, list):
# This SHOULD be a batch, by spec
responses = []
for req_entry in request:
Expand All @@ -79,7 +81,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None):
response = '[%s]' % ','.join(responses)
else:
response = ''
else:
else:
result = validate_request(request)
if type(result) is Fault:
return result.response()
Expand All @@ -99,7 +101,7 @@ def _marshaled_single_dispatch(self, request):
exc_type, exc_value, exc_tb = sys.exc_info()
fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
return fault.response()
if 'id' not in request.keys() or request['id'] == None:
if 'id' not in request.keys() or request['id'] is None:
# It's a notification
return None
try:
Expand Down Expand Up @@ -132,25 +134,26 @@ def _dispatch(self, method, params):
pass
if func is not None:
try:
if type(params) is types.ListType:
if isinstance(params, types.ListType):
response = func(*params)
else:
response = func(**params)
return response
except TypeError:
return Fault(-32602, 'Invalid parameters.')
# except TypeError:
# return Fault(-32602, 'Invalid parameters.')
except:
err_lines = traceback.format_exc().splitlines()
trace_string = '%s | %s' % (err_lines[-3], err_lines[-1])
fault = jsonrpclib.Fault(-32603, 'Server error: %s' %
fault = jsonrpclib.Fault(-32603, 'Server error: %s' %
trace_string)
return fault
else:
return Fault(-32601, 'Method %s not supported.' % method)


class SimpleJSONRPCRequestHandler(
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):

def do_POST(self):
if not self.is_rpc_path_valid():
self.report_404()
Expand All @@ -166,13 +169,13 @@ def do_POST(self):
data = ''.join(L)
response = self.server._marshaled_dispatch(data)
self.send_response(200)
except Exception, e:
except Exception:
self.send_response(500)
err_lines = traceback.format_exc().splitlines()
trace_string = '%s | %s' % (err_lines[-3], err_lines[-1])
fault = jsonrpclib.Fault(-32603, 'Server error: %s' % trace_string)
response = fault.response()
if response == None:
if response is None:
response = ''
self.send_header("Content-type", "application/json-rpc")
self.send_header("Content-length", str(len(response)))
Expand All @@ -181,6 +184,7 @@ def do_POST(self):
self.wfile.flush()
self.connection.shutdown(1)


class SimpleJSONRPCServer(SocketServer.TCPServer, SimpleJSONRPCDispatcher):

allow_reuse_address = True
Expand All @@ -198,7 +202,7 @@ def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler,
# Unix sockets can't be bound if they already exist in the
# filesystem. The convention of e.g. X11 is to unlink
# before binding again.
if os.path.exists(addr):
if os.path.exists(addr):
try:
os.unlink(addr)
except OSError:
Expand All @@ -207,13 +211,14 @@ def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler,
if vi[0] < 3 and vi[1] < 6:
SocketServer.TCPServer.__init__(self, addr, requestHandler)
else:
SocketServer.TCPServer.__init__(self, addr, requestHandler,
bind_and_activate)
SocketServer.TCPServer.__init__(
self, addr, requestHandler, bind_and_activate)
if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
flags |= fcntl.FD_CLOEXEC
fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)


class CGIJSONRPCRequestHandler(SimpleJSONRPCDispatcher):

def __init__(self, encoding=None):
Expand Down
9 changes: 4 additions & 5 deletions lib/jsonrpclib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from config import Config
from jsonrpclib.config import Config
config = Config.instance()
from history import History
from jsonrpclib.history import History
history = History.instance()
import jsonrpc
from jsonrpc import Server, MultiCall, Fault
from jsonrpc import ProtocolError, loads, dumps
from jsonrpclib.jsonrpc import Server, MultiCall, Fault
from jsonrpclib.jsonrpc import ProtocolError, loads, dumps
8 changes: 5 additions & 3 deletions lib/jsonrpclib/config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import sys


class LocalClasses(dict):
def add(self, cls):
self[cls.__name__] = cls


class Config(object):
"""
This is pretty much used exclusively for the 'jsonclass'
This is pretty much used exclusively for the 'jsonclass'
functionality... set use_jsonclass to False to turn it off.
You can change serialize_method and ignore_attribute, or use
the local_classes.add(class) to include "local" classes.
Expand All @@ -15,7 +17,7 @@ class Config(object):
# Change to False to keep __jsonclass__ entries raw.
serialize_method = '_serialize'
# The serialize_method should be a string that references the
# method on a custom class object which is responsible for
# method on a custom class object which is responsible for
# returning a tuple of the constructor arguments and a dict of
# attributes.
ignore_attribute = '_ignore'
Expand All @@ -30,7 +32,7 @@ class Config(object):
'.'.join([str(ver) for ver in sys.version_info[0:3]])
# User agent to use for calls.
_instance = None

@classmethod
def instance(cls):
if not cls._instance:
Expand Down
6 changes: 3 additions & 3 deletions lib/jsonrpclib/history.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ class History(object):
"""
This holds all the response and request objects for a
session. A server using this should call "clear" after
each request cycle in order to keep it from clogging
each request cycle in order to keep it from clogging
memory.
"""
requests = []
responses = []
_instance = None

@classmethod
def instance(cls):
if not cls._instance:
Expand All @@ -17,7 +17,7 @@ def instance(cls):

def add_response(self, response_obj):
self.responses.append(response_obj)

def add_request(self, request_obj):
self.requests.append(request_obj)

Expand Down
38 changes: 24 additions & 14 deletions lib/jsonrpclib/jsonclass.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import types
import inspect
import re
import traceback

from jsonrpclib import config

Expand Down Expand Up @@ -30,9 +29,11 @@
supported_types = iter_types+string_types+numeric_types+value_types
invalid_module_chars = r'[^a-zA-Z0-9\_\.]'


class TranslationError(Exception):
pass


def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]):
if not serialize_method:
serialize_method = config.serialize_method
Expand All @@ -46,25 +47,25 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]):
if obj_type in (types.ListType, types.TupleType):
new_obj = []
for item in obj:
new_obj.append(dump(item, serialize_method,
ignore_attribute, ignore))
if obj_type is types.TupleType:
new_obj.append(
dump(item, serialize_method, ignore_attribute, ignore))
if isinstance(obj_type, types.TupleType):
new_obj = tuple(new_obj)
return new_obj
# It's a dict...
else:
new_obj = {}
for key, value in obj.iteritems():
new_obj[key] = dump(value, serialize_method,
ignore_attribute, ignore)
new_obj[key] = dump(
value, serialize_method, ignore_attribute, ignore)
return new_obj
# It's not a standard type, so it needs __jsonclass__
module_name = inspect.getmodule(obj).__name__
class_name = obj.__class__.__name__
json_class = class_name
if module_name not in ['', '__main__']:
json_class = '%s.%s' % (module_name, json_class)
return_obj = {"__jsonclass__":[json_class,]}
return_obj = {"__jsonclass__": [json_class]}
# If a serialization method is defined..
if serialize_method in dir(obj):
# Params can be a dict (keyword) or list (positional)
Expand All @@ -84,21 +85,23 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]):
if type(attr_value) in supported_types and \
attr_name not in ignore_list and \
attr_value not in ignore_list:
attrs[attr_name] = dump(attr_value, serialize_method,
ignore_attribute, ignore)
attrs[attr_name] = dump(
attr_value, serialize_method, ignore_attribute, ignore)
return_obj.update(attrs)
return return_obj


def load(obj):
if type(obj) in string_types+numeric_types+value_types:
if type(obj) in string_types + numeric_types + value_types:
return obj
if type(obj) is types.ListType:

if isinstance(obj, list):
return_list = []
for entry in obj:
return_list.append(load(entry))
return return_list
# Othewise, it's a dict type
if '__jsonclass__' not in obj.keys():
if '__jsonclass__' not in obj:
return_dict = {}
for key, value in obj.iteritems():
new_value = load(value)
Expand Down Expand Up @@ -129,12 +132,19 @@ def load(obj):
except ImportError:
raise TranslationError('Could not import %s from module %s.' %
(json_class_name, json_module_tree))

# The returned class is the top-level module, not the one we really
# want. (E.g., if we import a.b.c, we now have a.) Walk through other
# path components to get to b and c.
for i in json_module_parts[1:]:
temp_module = getattr(temp_module, i)

json_class = getattr(temp_module, json_class_name)
# Creating the object...
new_obj = None
if type(params) is types.ListType:
if isinstance(params, list):
new_obj = json_class(*params)
elif type(params) is types.DictType:
elif isinstance(params, dict):
new_obj = json_class(**params)
else:
raise TranslationError('Constructor args must be a dict or list.')
Expand Down
Loading

0 comments on commit 656b2c3

Please sign in to comment.