diff options
author | 2015-08-24 10:51:13 +0300 | |
---|---|---|
committer | 2015-08-24 10:51:13 +0300 | |
commit | d3f26ece7d4383df0b22fe9c3cb3e695381ec737 (patch) | |
tree | ba42ddb547d363e92b1846df8a8712433981ddac /scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib | |
parent | 651a7d779551e193bd9dbadbe8b2a02bdab231b4 (diff) |
Initial push to external_lib migration
Diffstat (limited to 'scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib')
6 files changed, 0 insertions, 1014 deletions
diff --git a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/SimpleJSONRPCServer.py b/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/SimpleJSONRPCServer.py deleted file mode 100755 index d76da73e..00000000 --- a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/SimpleJSONRPCServer.py +++ /dev/null @@ -1,229 +0,0 @@ -import jsonrpclib -from jsonrpclib import Fault -from jsonrpclib.jsonrpc import USE_UNIX_SOCKETS -import SimpleXMLRPCServer -import SocketServer -import socket -import logging -import os -import types -import traceback -import sys -try: - import fcntl -except ImportError: - # 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: - fault = Fault( - -32600, 'Request must be {}, not %s.' % type(request) - ) - return fault - rpcid = request.get('id', None) - version = get_version(request) - if not version: - fault = Fault(-32600, 'Request %s invalid.' % request, rpcid=rpcid) - 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: - 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) - - def _marshaled_dispatch(self, data, dispatch_method = None): - response = None - try: - request = jsonrpclib.loads(data) - except Exception, e: - fault = Fault(-32700, 'Request %s invalid. (%s)' % (data, e)) - response = fault.response() - return response - if not request: - fault = Fault(-32600, 'Request invalid -- no request data.') - return fault.response() - if type(request) is types.ListType: - # This SHOULD be a batch, by spec - responses = [] - for req_entry in request: - result = validate_request(req_entry) - if type(result) is Fault: - responses.append(result.response()) - continue - resp_entry = self._marshaled_single_dispatch(req_entry) - if resp_entry is not None: - responses.append(resp_entry) - if len(responses) > 0: - response = '[%s]' % ','.join(responses) - else: - response = '' - else: - result = validate_request(request) - if type(result) is Fault: - return result.response() - response = self._marshaled_single_dispatch(request) - return response - - def _marshaled_single_dispatch(self, request): - # TODO - Use the multiprocessing and skip the response if - # it is a notification - # Put in support for custom dispatcher here - # (See SimpleXMLRPCServer._marshaled_dispatch) - method = request.get('method') - params = request.get('params') - try: - response = self._dispatch(method, params) - except: - 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: - # It's a notification - return None - try: - response = jsonrpclib.dumps(response, - methodresponse=True, - rpcid=request['id'] - ) - return response - except: - exc_type, exc_value, exc_tb = sys.exc_info() - fault = Fault(-32603, '%s:%s' % (exc_type, exc_value)) - return fault.response() - - def _dispatch(self, method, params): - func = None - try: - func = self.funcs[method] - except KeyError: - if self.instance is not None: - if hasattr(self.instance, '_dispatch'): - return self.instance._dispatch(method, params) - else: - try: - func = SimpleXMLRPCServer.resolve_dotted_attribute( - self.instance, - method, - True - ) - except AttributeError: - pass - if func is not None: - try: - if type(params) is types.ListType: - response = func(*params) - else: - response = func(**params) - return response - 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' % - 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() - return - try: - max_chunk_size = 10*1024*1024 - size_remaining = int(self.headers["content-length"]) - L = [] - while size_remaining: - chunk_size = min(size_remaining, max_chunk_size) - L.append(self.rfile.read(chunk_size)) - size_remaining -= len(L[-1]) - data = ''.join(L) - response = self.server._marshaled_dispatch(data) - self.send_response(200) - except Exception, e: - 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: - response = '' - self.send_header("Content-type", "application/json-rpc") - self.send_header("Content-length", str(len(response))) - self.end_headers() - self.wfile.write(response) - self.wfile.flush() - self.connection.shutdown(1) - -class SimpleJSONRPCServer(SocketServer.TCPServer, SimpleJSONRPCDispatcher): - - allow_reuse_address = True - - def __init__(self, addr, requestHandler=SimpleJSONRPCRequestHandler, - logRequests=True, encoding=None, bind_and_activate=True, - address_family=socket.AF_INET): - self.logRequests = logRequests - SimpleJSONRPCDispatcher.__init__(self, encoding) - # TCPServer.__init__ has an extra parameter on 2.6+, so - # check Python version and decide on how to call it - vi = sys.version_info - self.address_family = address_family - if USE_UNIX_SOCKETS and address_family == socket.AF_UNIX: - # 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): - try: - os.unlink(addr) - except OSError: - logging.warning("Could not unlink socket %s", addr) - # if python 2.5 and lower - if vi[0] < 3 and vi[1] < 6: - SocketServer.TCPServer.__init__(self, addr, requestHandler) - else: - 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): - SimpleJSONRPCDispatcher.__init__(self, encoding) - - 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 - sys.stdout.write(response) - - handle_xmlrpc = handle_jsonrpc diff --git a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/__init__.py b/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/__init__.py deleted file mode 100755 index 6e884b83..00000000 --- a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from jsonrpclib.config import Config -config = Config.instance() -from jsonrpclib.history import History -history = History.instance() -from jsonrpclib.jsonrpc import Server, MultiCall, Fault -from jsonrpclib.jsonrpc import ProtocolError, loads, dumps diff --git a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/config.py b/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/config.py deleted file mode 100755 index 4d28f1b1..00000000 --- a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/config.py +++ /dev/null @@ -1,38 +0,0 @@ -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' - 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. - """ - use_jsonclass = True - # 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 - # returning a tuple of the constructor arguments and a dict of - # attributes. - ignore_attribute = '_ignore' - # The ignore attribute should be a string that references the - # attribute on a custom class object which holds strings and / or - # references of the attributes the class translator should ignore. - classes = LocalClasses() - # The list of classes to use for jsonclass translation. - version = 2.0 - # Version of the JSON-RPC spec to support - user_agent = 'jsonrpclib/0.1 (Python %s)' % \ - '.'.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: - cls._instance = cls() - return cls._instance diff --git a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/history.py b/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/history.py deleted file mode 100755 index d11863dc..00000000 --- a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/history.py +++ /dev/null @@ -1,40 +0,0 @@ -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 - memory. - """ - requests = [] - responses = [] - _instance = None - - @classmethod - def instance(cls): - if not cls._instance: - cls._instance = cls() - return cls._instance - - def add_response(self, response_obj): - self.responses.append(response_obj) - - def add_request(self, request_obj): - self.requests.append(request_obj) - - @property - def request(self): - if len(self.requests) == 0: - return None - else: - return self.requests[-1] - - @property - def response(self): - if len(self.responses) == 0: - return None - else: - return self.responses[-1] - - def clear(self): - del self.requests[:] - del self.responses[:] diff --git a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/jsonclass.py b/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/jsonclass.py deleted file mode 100755 index 298c3da3..00000000 --- a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/jsonclass.py +++ /dev/null @@ -1,145 +0,0 @@ -import types -import inspect -import re -import traceback - -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 -] - -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 - 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: - return obj - if obj_type in iter_types: - 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 = 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) - 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,]} - # If a serialization method is defined.. - if serialize_method in dir(obj): - # Params can be a dict (keyword) or list (positional) - # Attrs MUST be a dict. - serialize = getattr(obj, serialize_method) - params, attrs = serialize() - return_obj['__jsonclass__'].append(params) - return_obj.update(attrs) - return return_obj - # Otherwise, try to figure it out - # Obviously, we can't assume to know anything about the - # parameters passed to __init__ - return_obj['__jsonclass__'].append([]) - attrs = {} - ignore_list = getattr(obj, ignore_attribute, [])+ignore - for attr_name, attr_value in obj.__dict__.iteritems(): - 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) - return_obj.update(attrs) - return return_obj - -def load(obj): - if type(obj) in string_types+numeric_types+value_types: - return obj - if type(obj) is types.ListType: - 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(): - return_dict = {} - for key, value in obj.iteritems(): - new_value = load(value) - return_dict[key] = new_value - return return_dict - # It's a dict, and it's a __jsonclass__ - orig_module_name = obj['__jsonclass__'][0] - params = obj['__jsonclass__'][1] - if orig_module_name == '': - raise TranslationError('Module name empty.') - json_module_clean = re.sub(invalid_module_chars, '', orig_module_name) - if json_module_clean != orig_module_name: - raise TranslationError('Module name %s has invalid characters.' % - orig_module_name) - json_module_parts = json_module_clean.split('.') - json_class = None - if len(json_module_parts) == 1: - # Local class name -- probably means it won't work - if json_module_parts[0] not in config.classes.keys(): - raise TranslationError('Unknown class or module %s.' % - json_module_parts[0]) - json_class = config.classes[json_module_parts[0]] - else: - json_class_name = json_module_parts.pop() - json_module_tree = '.'.join(json_module_parts) - try: - temp_module = __import__(json_module_tree) - except ImportError: - raise TranslationError('Could not import %s from module %s.' % - (json_class_name, json_module_tree)) - json_class = getattr(temp_module, json_class_name) - # Creating the object... - new_obj = None - if type(params) is types.ListType: - new_obj = json_class(*params) - elif type(params) is types.DictType: - new_obj = json_class(**params) - else: - raise TranslationError('Constructor args must be a dict or list.') - for key, value in obj.iteritems(): - if key == '__jsonclass__': - continue - setattr(new_obj, key, value) - return new_obj diff --git a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/jsonrpc.py b/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/jsonrpc.py deleted file mode 100755 index e11939ae..00000000 --- a/scripts/automation/trex_control_plane/python_lib/jsonrpclib-0.1.3/jsonrpclib/jsonrpc.py +++ /dev/null @@ -1,556 +0,0 @@ -""" -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -============================ -JSONRPC Library (jsonrpclib) -============================ - -This library is a JSON-RPC v.2 (proposed) implementation which -follows the xmlrpclib API for portability between clients. It -uses the same Server / ServerProxy, loads, dumps, etc. syntax, -while providing features not present in XML-RPC like: - -* Keyword arguments -* Notifications -* Versioning -* Batches and batch notifications - -Eventually, I'll add a SimpleXMLRPCServer compatible library, -and other things to tie the thing off nicely. :) - -For a quick-start, just open a console and type the following, -replacing the server address, method, and parameters -appropriately. ->>> import jsonrpclib ->>> server = jsonrpclib.Server('http://localhost:8181') ->>> server.add(5, 6) -11 ->>> server._notify.add(5, 6) ->>> batch = jsonrpclib.MultiCall(server) ->>> batch.add(3, 50) ->>> batch.add(2, 3) ->>> batch._notify.add(3, 5) ->>> batch() -[53, 5] - -See http://code.google.com/p/jsonrpclib/ for more info. -""" - -import types -import sys -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 time -import string -import random - -# Library includes -import jsonrpclib -from jsonrpclib import config -from jsonrpclib import history - -# JSON library importing -cjson = None -json = None -try: - import cjson -except ImportError: - try: - import json - except ImportError: - try: - import simplejson as json - except ImportError: - raise ImportError( - 'You must have the cjson, json, or simplejson ' + - 'module(s) available.' - ) - -IDCHARS = string.ascii_lowercase+string.digits - -class UnixSocketMissing(Exception): - """ - Just a properly named Exception if Unix Sockets usage is - attempted on a platform that doesn't support them (Windows) - """ - pass - -#JSON Abstractions - -def jdumps(obj, encoding='utf-8'): - # Do 'serialize' test at some point for other classes - global cjson - if cjson: - return cjson.encode(obj) - else: - return json.dumps(obj, encoding=encoding) - -def jloads(json_string): - global cjson - if cjson: - return cjson.decode(json_string) - else: - return json.loads(json_string) - - -# XMLRPClib re-implementations - -class ProtocolError(Exception): - pass - -class TransportMixIn(object): - """ Just extends the XMLRPC transport where necessary. """ - user_agent = config.user_agent - # for Python 2.7 support - _connection = None - - def send_content(self, connection, request_body): - connection.putheader("Content-Type", "application/json-rpc") - connection.putheader("Content-Length", str(len(request_body))) - connection.endheaders() - if request_body: - connection.send(request_body) - - def getparser(self): - target = JSONTarget() - return JSONParser(target), target - -class JSONParser(object): - def __init__(self, target): - self.target = target - - def feed(self, data): - self.target.feed(data) - - def close(self): - pass - -class JSONTarget(object): - def __init__(self): - self.data = [] - - def feed(self, data): - self.data.append(data) - - def close(self): - return ''.join(self.data) - -class Transport(TransportMixIn, XMLTransport): - pass - -class SafeTransport(TransportMixIn, XMLSafeTransport): - pass -from httplib import HTTP, HTTPConnection -from socket import socket - -USE_UNIX_SOCKETS = False - -try: - from socket import AF_UNIX, SOCK_STREAM - USE_UNIX_SOCKETS = True -except ImportError: - pass - -if (USE_UNIX_SOCKETS): - - class UnixHTTPConnection(HTTPConnection): - def connect(self): - 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): - import httplib - host, extra_headers, x509 = self.get_host_info(host) - return UnixHTTP(host) - - -class ServerProxy(XMLServerProxy): - """ - Unfortunately, much more of this class has to be copied since - so much of it does the serialization. - """ - - def __init__(self, uri, transport=None, encoding=None, - verbose=0, version=None): - import urllib - if not version: - version = config.version - self.__version = version - schema, uri = urllib.splittype(uri) - if schema not in ('http', 'https', 'unix'): - raise IOError('Unsupported JSON-RPC protocol.') - if schema == 'unix': - if not USE_UNIX_SOCKETS: - # Don't like the "generic" Exception... - raise UnixSocketMissing("Unix sockets not available.") - self.__host = uri - self.__handler = '/' - else: - self.__host, self.__handler = urllib.splithost(uri) - if not self.__handler: - # Not sure if this is in the JSON spec? - #self.__handler = '/' - self.__handler == '/' - if transport is None: - if schema == 'unix': - transport = UnixTransport() - elif schema == 'https': - transport = SafeTransport() - else: - transport = Transport() - self.__transport = transport - self.__encoding = encoding - self.__verbose = verbose - - def _request(self, methodname, params, rpcid=None): - request = dumps(params, methodname, encoding=self.__encoding, - rpcid=rpcid, version=self.__version) - response = self._run_request(request) - check_for_errors(response) - return response['result'] - - def _request_notify(self, methodname, params, rpcid=None): - request = dumps(params, methodname, encoding=self.__encoding, - rpcid=rpcid, version=self.__version, notify=True) - response = self._run_request(request, notify=True) - check_for_errors(response) - return - - def _run_request(self, request, notify=None): - history.add_request(request) - - response = self.__transport.request( - self.__host, - self.__handler, - request, - verbose=self.__verbose - ) - - # Here, the XMLRPC library translates a single list - # response to the single value -- should we do the - # same, and require a tuple / list to be passed to - # the response object, or expect the Server to be - # outputting the response appropriately? - - history.add_response(response) - if not response: - return None - return_obj = loads(response) - return return_obj - - def __getattr__(self, name): - # Same as original, just with new _Method reference - return _Method(self._request, name) - - @property - def _notify(self): - # Just like __getattr__, but with notify namespace. - return _Notify(self._request_notify) - - -class _Method(XML_Method): - - def __call__(self, *args, **kwargs): - if len(args) > 0 and len(kwargs) > 0: - raise ProtocolError('Cannot use both positional ' + - 'and keyword arguments (according to JSON-RPC spec.)') - if len(args) > 0: - return self.__send(self.__name, args) - else: - return self.__send(self.__name, kwargs) - - def __getattr__(self, name): - self.__name = '%s.%s' % (self.__name, name) - return self - # The old method returned a new instance, but this seemed wasteful. - # The only thing that changes is the name. - #return _Method(self.__send, "%s.%s" % (self.__name, name)) - -class _Notify(object): - def __init__(self, request): - self._request = request - - def __getattr__(self, name): - return _Method(self._request, name) - -# Batch implementation - -class MultiCallMethod(object): - - def __init__(self, method, notify=False): - self.method = method - self.params = [] - self.notify = notify - - def __call__(self, *args, **kwargs): - if len(kwargs) > 0 and len(args) > 0: - raise ProtocolError('JSON-RPC does not support both ' + - 'positional and keyword arguments.') - if len(kwargs) > 0: - self.params = kwargs - else: - self.params = args - - def request(self, encoding=None, rpcid=None): - return dumps(self.params, self.method, version=2.0, - encoding=encoding, rpcid=rpcid, notify=self.notify) - - def __repr__(self): - return '%s' % self.request() - - def __getattr__(self, method): - new_method = '%s.%s' % (self.method, method) - self.method = new_method - return self - -class MultiCallNotify(object): - - def __init__(self, multicall): - self.multicall = multicall - - def __getattr__(self, name): - new_job = MultiCallMethod(name, notify=True) - self.multicall._job_list.append(new_job) - return new_job - -class MultiCallIterator(object): - - def __init__(self, results): - self.results = results - - def __iter__(self): - for i in range(0, len(self.results)): - yield self[i] - raise StopIteration - - def __getitem__(self, i): - item = self.results[i] - check_for_errors(item) - return item['result'] - - def __len__(self): - return len(self.results) - -class MultiCall(object): - - def __init__(self, server): - self._server = server - self._job_list = [] - - def _request(self): - if len(self._job_list) < 1: - # Should we alert? This /is/ pretty obvious. - return - request_body = '[ %s ]' % ','.join([job.request() for - job in self._job_list]) - responses = self._server._run_request(request_body) - del self._job_list[:] - if not responses: - responses = [] - return MultiCallIterator(responses) - - @property - def _notify(self): - return MultiCallNotify(self) - - def __getattr__(self, name): - new_job = MultiCallMethod(name) - self._job_list.append(new_job) - return new_job - - __call__ = _request - -# These lines conform to xmlrpclib's "compatibility" line. -# Not really sure if we should include these, but oh well. -Server = ServerProxy - -class Fault(object): - # JSON-RPC error class - def __init__(self, code=-32000, message='Server error', rpcid=None): - self.faultCode = code - self.faultString = message - self.rpcid = rpcid - - def error(self): - return {'code':self.faultCode, 'message':self.faultString} - - def response(self, rpcid=None, version=None): - if not version: - version = config.version - if rpcid: - self.rpcid = rpcid - return dumps( - self, methodresponse=True, rpcid=self.rpcid, version=version - ) - - def __repr__(self): - return '<Fault %s: %s>' % (self.faultCode, self.faultString) - -def random_id(length=8): - return_id = '' - for i in range(length): - return_id += random.choice(IDCHARS) - return return_id - -class Payload(dict): - def __init__(self, rpcid=None, version=None): - if not version: - version = config.version - self.id = rpcid - self.version = float(version) - - def request(self, method, params=[]): - if type(method) not in types.StringTypes: - raise ValueError('Method name must be a string.') - if not self.id: - self.id = random_id() - request = { 'id':self.id, 'method':method } - if params: - request['params'] = params - if self.version >= 2: - request['jsonrpc'] = str(self.version) - return request - - def notify(self, method, params=[]): - request = self.request(method, params) - if self.version >= 2: - del request['id'] - else: - request['id'] = None - return request - - def response(self, result=None): - response = {'result':result, 'id':self.id} - if self.version >= 2: - response['jsonrpc'] = str(self.version) - else: - response['error'] = None - return response - - def error(self, code=-32000, message='Server error.'): - error = self.response() - if self.version >= 2: - del error['result'] - else: - error['result'] = None - error['error'] = {'code':code, 'message':message} - return error - -def dumps(params=[], methodname=None, methodresponse=None, - encoding=None, rpcid=None, version=None, notify=None): - """ - This differs from the Python implementation in that it implements - the rpcid argument since the 2.0 spec requires it for responses. - """ - 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 \ - not isinstance(params, Fault): - """ - If a method, and params are not in a listish or a Fault, - error out. - """ - raise TypeError('Params must be a dict, list, tuple or Fault ' + - 'instance.') - # Begin parsing object - payload = Payload(rpcid=rpcid, version=version) - if not encoding: - encoding = 'utf-8' - if type(params) is Fault: - response = payload.error(params.faultCode, params.faultString) - return jdumps(response, encoding=encoding) - if type(methodname) not in types.StringTypes and methodresponse != True: - raise ValueError('Method name must be a string, or methodresponse '+ - 'must be set to True.') - if config.use_jsonclass == True: - from jsonrpclib import jsonclass - params = jsonclass.dump(params) - if methodresponse is True: - if rpcid is None: - raise ValueError('A method response must have an rpcid.') - response = payload.response(params) - return jdumps(response, encoding=encoding) - request = None - if notify == True: - request = payload.notify(methodname, params) - else: - request = payload.request(methodname, params) - return jdumps(request, encoding=encoding) - -def loads(data): - """ - This differs from the Python implementation, in that it returns - the request structure in Dict format instead of the method, params. - It will return a list in the case of a batch request / response. - """ - if data == '': - # notification - return None - result = jloads(data) - # if the above raises an error, the implementing server code - # should return something like the following: - # { 'jsonrpc':'2.0', 'error': fault.error(), id: None } - if config.use_jsonclass == True: - from jsonrpclib import jsonclass - result = jsonclass.load(result) - return result - -def check_for_errors(result): - if not result: - # Notification - return result - if type(result) is not types.DictType: - raise TypeError('Response is not a dict.') - if 'jsonrpc' in result.keys() and float(result['jsonrpc']) > 2.0: - raise NotImplementedError('JSON-RPC version not yet supported.') - if 'result' not in result.keys() and 'error' not in result.keys(): - raise ValueError('Response does not have a result or error key.') - if 'error' in result.keys() and result['error'] != None: - code = result['error']['code'] - message = result['error']['message'] - raise ProtocolError((code, message)) - return result - -def isbatch(result): - if type(result) not in (types.ListType, types.TupleType): - return False - if len(result) < 1: - return False - if type(result[0]) is not types.DictType: - return False - if 'jsonrpc' not in result[0].keys(): - return False - try: - version = float(result[0]['jsonrpc']) - except ValueError: - raise ProtocolError('"jsonrpc" key must be a float(able) value.') - if version < 2: - return False - return True - -def isnotification(request): - if 'id' not in request.keys(): - # 2.0 notification - return True - if request['id'] == None: - # 1.0 notification - return True - return False |