Skip to content

Commit 10bea44

Browse files
committed
Merge pull request joshmarshall#40 from joshmarshall/travis-and-pip
Adding Travis for testing, fixing minor PIP violations.
2 parents b59217c + f4bfd51 commit 10bea44

File tree

10 files changed

+306
-235
lines changed

10 files changed

+306
-235
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.pyc
22
build/*
33
dist/*
4+
.coverage

.travis.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
language: python
2+
sudo: false
3+
python:
4+
- '2.7'
5+
- '2.6'
6+
install:
7+
- pip install -r dev-requirements.txt
8+
# will need this when we automatically push to pypi
9+
# - pip install twine
10+
script: nosetests tests.py --with-coverage --cover-package=jsonrpclib

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
[![Build Status](https://travis-ci.org/joshmarshall/jsonrpclib.svg)](https://travis-ci.org/joshmarshall/jsonrpclib)
2+
13
JSONRPClib
24
==========
35
This library is an implementation of the JSON-RPC specification.
@@ -211,7 +213,8 @@ TESTS
211213
I've dropped almost-verbatim tests from the JSON-RPC spec 2.0 page.
212214
You can run it with:
213215

214-
python tests.py
216+
pip install -r dev-requirements.txt
217+
nosetests tests.py
215218

216219
TODO
217220
----

dev-requirements.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
coverage==4.0
2+
linecache2==1.0.0
3+
nose==1.3.7
4+
six==1.9.0
5+
traceback2==1.4.0
6+
unittest2==1.1.0

jsonrpclib/SimpleJSONRPCServer.py

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@
1515
# For Windows
1616
fcntl = None
1717

18+
1819
def get_version(request):
1920
# must be a dict
2021
if 'jsonrpc' in request.keys():
2122
return 2.0
2223
if 'id' in request.keys():
2324
return 1.0
2425
return None
25-
26+
27+
2628
def validate_request(request):
27-
if type(request) is not types.DictType:
29+
if not isinstance(request, dict):
2830
fault = Fault(
2931
-32600, 'Request must be {}, not %s.' % type(request)
3032
)
@@ -33,27 +35,27 @@ def validate_request(request):
3335
version = get_version(request)
3436
if not version:
3537
fault = Fault(-32600, 'Request %s invalid.' % request, rpcid=rpcid)
36-
return fault
38+
return fault
3739
request.setdefault('params', [])
3840
method = request.get('method', None)
3941
params = request.get('params')
4042
param_types = (types.ListType, types.DictType, types.TupleType)
4143
if not method or type(method) not in types.StringTypes or \
42-
type(params) not in param_types:
44+
type(params) not in param_types:
4345
fault = Fault(
4446
-32600, 'Invalid request parameters or method.', rpcid=rpcid
4547
)
4648
return fault
4749
return True
4850

51+
4952
class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
5053

5154
def __init__(self, encoding=None):
52-
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self,
53-
allow_none=True,
54-
encoding=encoding)
55+
SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(
56+
self, allow_none=True, encoding=encoding)
5557

56-
def _marshaled_dispatch(self, data, dispatch_method = None):
58+
def _marshaled_dispatch(self, data, dispatch_method=None):
5759
response = None
5860
try:
5961
request = jsonrpclib.loads(data)
@@ -64,7 +66,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None):
6466
if not request:
6567
fault = Fault(-32600, 'Request invalid -- no request data.')
6668
return fault.response()
67-
if type(request) is types.ListType:
69+
if isinstance(request, list):
6870
# This SHOULD be a batch, by spec
6971
responses = []
7072
for req_entry in request:
@@ -79,7 +81,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None):
7981
response = '[%s]' % ','.join(responses)
8082
else:
8183
response = ''
82-
else:
84+
else:
8385
result = validate_request(request)
8486
if type(result) is Fault:
8587
return result.response()
@@ -99,7 +101,7 @@ def _marshaled_single_dispatch(self, request):
99101
exc_type, exc_value, exc_tb = sys.exc_info()
100102
fault = Fault(-32603, '%s:%s' % (exc_type, exc_value))
101103
return fault.response()
102-
if 'id' not in request.keys() or request['id'] == None:
104+
if 'id' not in request.keys() or request['id'] is None:
103105
# It's a notification
104106
return None
105107
try:
@@ -132,25 +134,26 @@ def _dispatch(self, method, params):
132134
pass
133135
if func is not None:
134136
try:
135-
if type(params) is types.ListType:
137+
if isinstance(params, types.ListType):
136138
response = func(*params)
137139
else:
138140
response = func(**params)
139141
return response
140-
except TypeError:
141-
return Fault(-32602, 'Invalid parameters.')
142+
# except TypeError:
143+
# return Fault(-32602, 'Invalid parameters.')
142144
except:
143145
err_lines = traceback.format_exc().splitlines()
144146
trace_string = '%s | %s' % (err_lines[-3], err_lines[-1])
145-
fault = jsonrpclib.Fault(-32603, 'Server error: %s' %
147+
fault = jsonrpclib.Fault(-32603, 'Server error: %s' %
146148
trace_string)
147149
return fault
148150
else:
149151
return Fault(-32601, 'Method %s not supported.' % method)
150152

153+
151154
class SimpleJSONRPCRequestHandler(
152155
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
153-
156+
154157
def do_POST(self):
155158
if not self.is_rpc_path_valid():
156159
self.report_404()
@@ -166,13 +169,13 @@ def do_POST(self):
166169
data = ''.join(L)
167170
response = self.server._marshaled_dispatch(data)
168171
self.send_response(200)
169-
except Exception, e:
172+
except Exception:
170173
self.send_response(500)
171174
err_lines = traceback.format_exc().splitlines()
172175
trace_string = '%s | %s' % (err_lines[-3], err_lines[-1])
173176
fault = jsonrpclib.Fault(-32603, 'Server error: %s' % trace_string)
174177
response = fault.response()
175-
if response == None:
178+
if response is None:
176179
response = ''
177180
self.send_header("Content-type", "application/json-rpc")
178181
self.send_header("Content-length", str(len(response)))
@@ -181,6 +184,7 @@ def do_POST(self):
181184
self.wfile.flush()
182185
self.connection.shutdown(1)
183186

187+
184188
class SimpleJSONRPCServer(SocketServer.TCPServer, SimpleJSONRPCDispatcher):
185189

186190
allow_reuse_address = True
@@ -198,7 +202,7 @@ def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler,
198202
# Unix sockets can't be bound if they already exist in the
199203
# filesystem. The convention of e.g. X11 is to unlink
200204
# before binding again.
201-
if os.path.exists(addr):
205+
if os.path.exists(addr):
202206
try:
203207
os.unlink(addr)
204208
except OSError:
@@ -207,13 +211,14 @@ def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler,
207211
if vi[0] < 3 and vi[1] < 6:
208212
SocketServer.TCPServer.__init__(self, addr, requestHandler)
209213
else:
210-
SocketServer.TCPServer.__init__(self, addr, requestHandler,
211-
bind_and_activate)
214+
SocketServer.TCPServer.__init__(
215+
self, addr, requestHandler, bind_and_activate)
212216
if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
213217
flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
214218
flags |= fcntl.FD_CLOEXEC
215219
fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
216220

221+
217222
class CGIJSONRPCRequestHandler(SimpleJSONRPCDispatcher):
218223

219224
def __init__(self, encoding=None):

jsonrpclib/config.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import sys
22

3+
34
class LocalClasses(dict):
45
def add(self, cls):
56
self[cls.__name__] = cls
67

8+
79
class Config(object):
810
"""
9-
This is pretty much used exclusively for the 'jsonclass'
11+
This is pretty much used exclusively for the 'jsonclass'
1012
functionality... set use_jsonclass to False to turn it off.
1113
You can change serialize_method and ignore_attribute, or use
1214
the local_classes.add(class) to include "local" classes.
@@ -15,7 +17,7 @@ class Config(object):
1517
# Change to False to keep __jsonclass__ entries raw.
1618
serialize_method = '_serialize'
1719
# The serialize_method should be a string that references the
18-
# method on a custom class object which is responsible for
20+
# method on a custom class object which is responsible for
1921
# returning a tuple of the constructor arguments and a dict of
2022
# attributes.
2123
ignore_attribute = '_ignore'
@@ -30,7 +32,7 @@ class Config(object):
3032
'.'.join([str(ver) for ver in sys.version_info[0:3]])
3133
# User agent to use for calls.
3234
_instance = None
33-
35+
3436
@classmethod
3537
def instance(cls):
3638
if not cls._instance:

jsonrpclib/history.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ class History(object):
22
"""
33
This holds all the response and request objects for a
44
session. A server using this should call "clear" after
5-
each request cycle in order to keep it from clogging
5+
each request cycle in order to keep it from clogging
66
memory.
77
"""
88
requests = []
99
responses = []
1010
_instance = None
11-
11+
1212
@classmethod
1313
def instance(cls):
1414
if not cls._instance:
@@ -17,7 +17,7 @@ def instance(cls):
1717

1818
def add_response(self, response_obj):
1919
self.responses.append(response_obj)
20-
20+
2121
def add_request(self, request_obj):
2222
self.requests.append(request_obj)
2323

jsonrpclib/jsonclass.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import types
22
import inspect
33
import re
4-
import traceback
54

65
from jsonrpclib import config
76

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

32+
3333
class TranslationError(Exception):
3434
pass
3535

36+
3637
def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]):
3738
if not serialize_method:
3839
serialize_method = config.serialize_method
@@ -46,25 +47,25 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]):
4647
if obj_type in (types.ListType, types.TupleType):
4748
new_obj = []
4849
for item in obj:
49-
new_obj.append(dump(item, serialize_method,
50-
ignore_attribute, ignore))
51-
if obj_type is types.TupleType:
50+
new_obj.append(
51+
dump(item, serialize_method, ignore_attribute, ignore))
52+
if isinstance(obj_type, types.TupleType):
5253
new_obj = tuple(new_obj)
5354
return new_obj
5455
# It's a dict...
5556
else:
5657
new_obj = {}
5758
for key, value in obj.iteritems():
58-
new_obj[key] = dump(value, serialize_method,
59-
ignore_attribute, ignore)
59+
new_obj[key] = dump(
60+
value, serialize_method, ignore_attribute, ignore)
6061
return new_obj
6162
# It's not a standard type, so it needs __jsonclass__
6263
module_name = inspect.getmodule(obj).__name__
6364
class_name = obj.__class__.__name__
6465
json_class = class_name
6566
if module_name not in ['', '__main__']:
6667
json_class = '%s.%s' % (module_name, json_class)
67-
return_obj = {"__jsonclass__":[json_class,]}
68+
return_obj = {"__jsonclass__": [json_class]}
6869
# If a serialization method is defined..
6970
if serialize_method in dir(obj):
7071
# Params can be a dict (keyword) or list (positional)
@@ -84,21 +85,23 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]):
8485
if type(attr_value) in supported_types and \
8586
attr_name not in ignore_list and \
8687
attr_value not in ignore_list:
87-
attrs[attr_name] = dump(attr_value, serialize_method,
88-
ignore_attribute, ignore)
88+
attrs[attr_name] = dump(
89+
attr_value, serialize_method, ignore_attribute, ignore)
8990
return_obj.update(attrs)
9091
return return_obj
9192

93+
9294
def load(obj):
93-
if type(obj) in string_types+numeric_types+value_types:
95+
if type(obj) in string_types + numeric_types + value_types:
9496
return obj
95-
if type(obj) is types.ListType:
97+
98+
if isinstance(obj, list):
9699
return_list = []
97100
for entry in obj:
98101
return_list.append(load(entry))
99102
return return_list
100103
# Othewise, it's a dict type
101-
if '__jsonclass__' not in obj.keys():
104+
if '__jsonclass__' not in obj:
102105
return_dict = {}
103106
for key, value in obj.iteritems():
104107
new_value = load(value)
@@ -139,9 +142,9 @@ def load(obj):
139142
json_class = getattr(temp_module, json_class_name)
140143
# Creating the object...
141144
new_obj = None
142-
if type(params) is types.ListType:
145+
if isinstance(params, list):
143146
new_obj = json_class(*params)
144-
elif type(params) is types.DictType:
147+
elif isinstance(params, dict):
145148
new_obj = json_class(**params)
146149
else:
147150
raise TranslationError('Constructor args must be a dict or list.')

0 commit comments

Comments
 (0)