diff options
author | Josh Marshall <catchjosh@gmail.com> | 2021-03-30 11:01:58 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-30 11:01:58 +0900 |
commit | 9f1cb474c7e0f7e5ff87d5fa3acd5cb6adab2ae1 (patch) | |
tree | c5b8205303f473bf5178ec511f32375bdae77087 | |
parent | e7cb8ba791bd89109022ff7b516787f16922a39b (diff) | |
parent | ee90663dde0e46927d11d049f9a516e5381b0d0f (diff) | |
download | jsonrpclib-9f1cb474c7e0f7e5ff87d5fa3acd5cb6adab2ae1.tar.gz |
Merge pull request #59 from prs247au/master
Updates for Python 3.x compatibility
-rw-r--r-- | .travis.yml | 5 | ||||
-rw-r--r-- | dev-requirements.txt | 14 | ||||
-rw-r--r-- | jsonrpclib/SimpleJSONRPCServer.py | 39 | ||||
-rw-r--r-- | jsonrpclib/jsonclass.py | 49 | ||||
-rw-r--r-- | jsonrpclib/jsonrpc.py | 61 |
5 files changed, 91 insertions, 77 deletions
diff --git a/.travis.yml b/.travis.yml index fe1cd05..b855e1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,10 @@ language: python sudo: false python: -- '2.7' +- "2.7" +- "3.3" +- "3.4" +- "3.5" install: - pip install -r dev-requirements.txt - pip install twine diff --git a/dev-requirements.txt b/dev-requirements.txt index 95cb849..c1c28fa 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,11 +1,11 @@ -coverage==4.0 +coverage==4.4 linecache2==1.0.0 nose==1.3.7 -pluggy==0.3.1 -py==1.4.30 -six==1.9.0 -tox==2.1.1 +pluggy==0.4.0 +py==1.4.33 +six==1.10.0 +tox==2.7.0 traceback2==1.4.0 unittest2==1.1.0 -virtualenv==13.1.2 -wheel==0.24.0 +virtualenv==15.1.0 +wheel==0.29.0 diff --git a/jsonrpclib/SimpleJSONRPCServer.py b/jsonrpclib/SimpleJSONRPCServer.py index 3a0a3bb..708c5d2 100644 --- a/jsonrpclib/SimpleJSONRPCServer.py +++ b/jsonrpclib/SimpleJSONRPCServer.py @@ -1,12 +1,15 @@ import jsonrpclib from jsonrpclib import Fault from jsonrpclib.jsonrpc import USE_UNIX_SOCKETS -import SimpleXMLRPCServer -import SocketServer +try: + import xmlrpc.server as SimpleXMLRPCServer # Python 3.x + import socketserver as SocketServer +except ImportError: + import SimpleXMLRPCServer # Python 2.7 + import SocketServer import socket import logging import os -import types import traceback import sys try: @@ -15,6 +18,10 @@ except ImportError: # For Windows fcntl = None +try: + basestring # Python 2.7 +except NameError: + basestring = str # Python 3.x def get_version(request): # must be a dict @@ -39,9 +46,8 @@ def validate_request(request): 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: + if not method or not isinstance(method, basestring) or \ + not isinstance(params, (list, dict, tuple)): fault = Fault( -32600, 'Invalid request parameters or method.', rpcid=rpcid ) @@ -59,7 +65,7 @@ class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher): response = None try: request = jsonrpclib.loads(data) - except Exception, e: + except Exception as e: fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e)) response = fault.response() return response @@ -134,7 +140,7 @@ class SimpleJSONRPCDispatcher(SimpleXMLRPCServer.SimpleXMLRPCDispatcher): pass if func is not None: try: - if isinstance(params, types.ListType): + if isinstance(params, list): response = func(*params) else: response = func(**params) @@ -164,12 +170,13 @@ class SimpleJSONRPCRequestHandler( L = [] while size_remaining: chunk_size = min(size_remaining, max_chunk_size) - L.append(self.rfile.read(chunk_size)) + chunk = self.rfile.read(chunk_size).decode() + L.append(chunk) size_remaining -= len(L[-1]) data = ''.join(L) response = self.server._marshaled_dispatch(data) self.send_response(200) - except Exception: + except Exception as ex: self.send_response(500) err_lines = traceback.format_exc().splitlines() trace_string = '%s | %s' % (err_lines[-3], err_lines[-1]) @@ -180,7 +187,10 @@ class SimpleJSONRPCRequestHandler( self.send_header("Content-type", "application/json-rpc") self.send_header("Content-length", str(len(response))) self.end_headers() - self.wfile.write(response) + if isinstance(response, bytes): + self.wfile.write(response) + else: + self.wfile.write(response.encode()) self.wfile.flush() self.connection.shutdown(1) @@ -218,7 +228,6 @@ class SimpleJSONRPCServer(SocketServer.TCPServer, SimpleJSONRPCDispatcher): flags |= fcntl.FD_CLOEXEC fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) - class CGIJSONRPCRequestHandler(SimpleJSONRPCDispatcher): def __init__(self, encoding=None): @@ -226,9 +235,9 @@ class CGIJSONRPCRequestHandler(SimpleJSONRPCDispatcher): def handle_jsonrpc(self, request_text): response = self._marshaled_dispatch(request_text) - print 'Content-Type: application/json-rpc' - print 'Content-Length: %d' % len(response) - print + print( 'Content-Type: application/json-rpc' ) + print( 'Content-Length: %d' % len(response) ) + print() sys.stdout.write(response) handle_xmlrpc = handle_jsonrpc diff --git a/jsonrpclib/jsonclass.py b/jsonrpclib/jsonclass.py index 4326f28..31f829d 100644 --- a/jsonrpclib/jsonclass.py +++ b/jsonrpclib/jsonclass.py @@ -1,30 +1,16 @@ -import types import inspect import re from jsonrpclib import config -iter_types = [ - types.DictType, - types.ListType, - types.TupleType -] - -string_types = [ - types.StringType, - types.UnicodeType -] - -numeric_types = [ - types.IntType, - types.LongType, - types.FloatType -] - -value_types = [ - types.BooleanType, - types.NoneType -] +iter_types = (dict, list, tuple) +value_types = (bool, ) +try: + string_types = (basestring, ) # Python 2.7 + numeric_types = (int, long, float) +except NameError: + string_types = (str, ) # Python 3.x + numeric_types = (int, float) supported_types = iter_types+string_types+numeric_types+value_types invalid_module_chars = r'[^a-zA-Z0-9\_\.]' @@ -39,23 +25,22 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]): serialize_method = config.serialize_method if not ignore_attribute: ignore_attribute = config.ignore_attribute - obj_type = type(obj) # Parse / return default "types"... - if obj_type in numeric_types+string_types+value_types: + if obj is None or isinstance(obj, numeric_types+string_types+value_types): return obj - if obj_type in iter_types: - if obj_type in (types.ListType, types.TupleType): + if isinstance(obj, iter_types): + if isinstance(obj, (list, tuple)): new_obj = [] for item in obj: new_obj.append( dump(item, serialize_method, ignore_attribute, ignore)) - if isinstance(obj_type, types.TupleType): + if isinstance(obj, tuple): new_obj = tuple(new_obj) return new_obj # It's a dict... else: new_obj = {} - for key, value in obj.iteritems(): + for key, value in obj.items(): new_obj[key] = dump( value, serialize_method, ignore_attribute, ignore) return new_obj @@ -81,7 +66,7 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]): return_obj['__jsonclass__'].append([]) attrs = {} ignore_list = getattr(obj, ignore_attribute, [])+ignore - for attr_name, attr_value in obj.__dict__.iteritems(): + for attr_name, attr_value in obj.__dict__.items(): if type(attr_value) in supported_types and \ attr_name not in ignore_list and \ attr_value not in ignore_list: @@ -92,7 +77,7 @@ def dump(obj, serialize_method=None, ignore_attribute=None, ignore=[]): def load(obj): - if type(obj) in string_types + numeric_types + value_types: + if obj is None or isinstance(obj, string_types + numeric_types + value_types): return obj if isinstance(obj, list): @@ -103,7 +88,7 @@ def load(obj): # Othewise, it's a dict type if '__jsonclass__' not in obj: return_dict = {} - for key, value in obj.iteritems(): + for key, value in obj.items(): new_value = load(value) return_dict[key] = new_value return return_dict @@ -148,7 +133,7 @@ def load(obj): new_obj = json_class(**params) else: raise TranslationError('Constructor args must be a dict or list.') - for key, value in obj.iteritems(): + for key, value in obj.items(): if key == '__jsonclass__': continue setattr(new_obj, key, value) diff --git a/jsonrpclib/jsonrpc.py b/jsonrpclib/jsonrpc.py index 167bcd7..4861e4a 100644 --- a/jsonrpclib/jsonrpc.py +++ b/jsonrpclib/jsonrpc.py @@ -46,14 +46,28 @@ appropriately. See http://code.google.com/p/jsonrpclib/ for more info. """ -import types -from xmlrpclib import Transport as XMLTransport -from xmlrpclib import SafeTransport as XMLSafeTransport -from xmlrpclib import ServerProxy as XMLServerProxy -from xmlrpclib import _Method as XML_Method +try: + # Python 3.x + from xmlrpc.client import Transport as XMLTransport + from xmlrpc.client import SafeTransport as XMLSafeTransport + from xmlrpc.client import ServerProxy as XMLServerProxy + from xmlrpc.client import _Method as XML_Method +except ImportError: + # Python 2.7 + from xmlrpclib import Transport as XMLTransport + from xmlrpclib import SafeTransport as XMLSafeTransport + from xmlrpclib import ServerProxy as XMLServerProxy + from xmlrpclib import _Method as XML_Method + import string import random +try: + basestring # Python 2.7 +except NameError: + basestring = str # Python 3.x + + # Library includes from jsonrpclib import config from jsonrpclib import history @@ -95,7 +109,8 @@ def jdumps(obj, encoding='utf-8'): if cjson: return cjson.encode(obj) else: - return json.dumps(obj, encoding=encoding) +# return json.dumps(obj, encoding=encoding) + return json.dumps(obj) def jloads(json_string): @@ -151,7 +166,7 @@ class JSONTarget(object): self.data.append(data) def close(self): - return ''.join(self.data) + return ''.join([d.decode() for d in self.data]) class Transport(TransportMixIn, XMLTransport): @@ -165,7 +180,10 @@ class SafeTransport(TransportMixIn, XMLSafeTransport): TransportMixIn.__init__(self) XMLSafeTransport.__init__(self) -from httplib import HTTP, HTTPConnection +try: + from httplib import HTTPConnection +except ImportError: + from http.client import HTTPConnection from socket import socket USE_UNIX_SOCKETS = False @@ -183,14 +201,11 @@ if (USE_UNIX_SOCKETS): self.sock = socket(AF_UNIX, SOCK_STREAM) self.sock.connect(self.host) - class UnixHTTP(HTTP): - _connection_class = UnixHTTPConnection - class UnixTransport(TransportMixIn, XMLTransport): def make_connection(self, host): host, extra_headers, x509 = self.get_host_info(host) - return UnixHTTP(host) + return UnixHTTPConnection(host) class ServerProxy(XMLServerProxy): @@ -201,11 +216,14 @@ class ServerProxy(XMLServerProxy): def __init__(self, uri, transport=None, encoding=None, verbose=0, version=None): - import urllib + try: + from urllib.parse import splittype, splithost # python 3.x + except ImportError: + from urllib import splittype, splithost if not version: version = config.version self.__version = version - schema, uri = urllib.splittype(uri) + schema, uri = splittype(uri) if schema not in ('http', 'https', 'unix'): raise IOError('Unsupported JSON-RPC protocol.') if schema == 'unix': @@ -215,7 +233,7 @@ class ServerProxy(XMLServerProxy): self.__host = uri self.__handler = '/' else: - self.__host, self.__handler = urllib.splithost(uri) + self.__host, self.__handler = splithost(uri) if not self.__handler: # Not sure if this is in the JSON spec? # self.__handler = '/' @@ -445,7 +463,7 @@ class Payload(dict): self.version = float(version) def request(self, method, params=[]): - if type(method) not in types.StringTypes: + if not isinstance(method, basestring): raise ValueError('Method name must be a string.') if not self.id: self.id = random_id() @@ -491,9 +509,8 @@ def dumps( """ if not version: version = config.version - valid_params = (types.TupleType, types.ListType, types.DictType) - if methodname in types.StringTypes and \ - type(params) not in valid_params and \ + if isinstance(methodname, str) and \ + not isinstance(params, (tuple, list, dict)) and \ not isinstance(params, Fault): """ If a method, and params are not in a listish or a Fault, @@ -505,11 +522,11 @@ def dumps( payload = Payload(rpcid=rpcid, version=version) if not encoding: encoding = 'utf-8' - if type(params) is Fault: + if isinstance(params, Fault): response = payload.error(params.faultCode, params.faultString) return jdumps(response, encoding=encoding) - if type(methodname) not in types.StringTypes and \ + if not isinstance(methodname, str) and \ methodresponse is not True: raise ValueError( 'Method name must be a string, or methodresponse must ' @@ -569,7 +586,7 @@ def check_for_errors(result): def isbatch(result): - if type(result) not in (types.ListType, types.TupleType): + if not isinstance(result, (list, tuple)): return False if len(result) < 1: return False |