PageRenderTime 33ms CodeModel.GetById 17ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/galaxy/util/json.py

https://bitbucket.org/cistrome/cistrome-harvard/
Python | 110 lines | 100 code | 9 blank | 1 comment | 28 complexity | bae755ce203fb3d4a07394bfc63571fe MD5 | raw file
  1from __future__ import absolute_import
  2
  3__all__ = [ "to_json_string", "from_json_string", "json_fix", "validate_jsonrpc_request", "validate_jsonrpc_response", "jsonrpc_request", "jsonrpc_response" ]
  4
  5import json
  6import logging
  7import random
  8import socket
  9import string
 10
 11to_json_string = json.dumps
 12from_json_string = json.loads
 13
 14log = logging.getLogger( __name__ )
 15
 16def json_fix( val ):
 17    if isinstance( val, list ):
 18        return [ json_fix( v ) for v in val ]
 19    elif isinstance( val, dict ):
 20        return dict( [ ( json_fix( k ), json_fix( v ) ) for ( k, v ) in val.iteritems() ] )
 21    elif isinstance( val, unicode ):
 22        return val.encode( "utf8" )
 23    else:
 24        return val
 25
 26# Methods for handling JSON-RPC
 27
 28def validate_jsonrpc_request( request, regular_methods, notification_methods ):
 29    try:
 30        request = from_json_string( request )
 31    except Exception, e:
 32        return False, request, jsonrpc_response( id = None, error = dict( code = -32700, message = 'Parse error', data = str( e ) ) )
 33    try:
 34        assert 'jsonrpc' in request, \
 35            'This server requires JSON-RPC 2.0 and no "jsonrpc" member was sent with the Request object as per the JSON-RPC 2.0 Specification.'
 36        assert request['jsonrpc'] == '2.0', \
 37                'Requested JSON-RPC version "%s" != required version "2.0".' % request['jsonrpc']
 38        assert 'method' in request, 'No "method" member was sent with the Request object'
 39    except AssertionError, e:
 40        return False, request, jsonrpc_response( request = request, error = dict( code = -32600, message = 'Invalid Request', data = str( e ) ) )
 41    try:
 42        assert request['method'] in ( regular_methods + notification_methods )
 43    except AssertionError, e:
 44        return False, request, jsonrpc_response( request = request,
 45                                        error = dict( code = -32601,
 46                                                      message = 'Method not found',
 47                                                      data = 'Valid methods are: %s' % ', '.join( regular_methods + notification_methods ) ) )
 48    try:
 49        if request['method'] in regular_methods:
 50            assert 'id' in request, 'No "id" member was sent with the Request object and the requested method "%s" is not a notification method' % request['method']
 51    except AssertionError, e:
 52        return False, request, jsonrpc_response( request = request, error = dict( code = -32600, message = 'Invalid Request', data = str( e ) ) )
 53    return True, request, None
 54
 55def validate_jsonrpc_response( response, id=None ):
 56    try:
 57        response = from_json_string( response )
 58    except Exception, e:
 59        log.error( 'Response was not valid JSON: %s' % str( e ) )
 60        log.debug( 'Response was: %s' % response )
 61        return False, response
 62    try:
 63        assert 'jsonrpc' in response, \
 64            'This server requires JSON-RPC 2.0 and no "jsonrpc" member was sent with the Response object as per the JSON-RPC 2.0 Specification.'
 65        assert ( 'result' in response or 'error' in response ), \
 66            'Neither of "result" or "error" members were sent with the Response object.'
 67        if 'error' in response:
 68            assert int( response['error']['code'] ), \
 69                'The "code" member of the "error" object in the Response is missing or not an integer.'
 70            assert 'message' in response, \
 71                'The "message" member of the "error" object in the Response is missing.'
 72    except Exception, e:
 73        log.error( 'Response was not valid JSON-RPC: %s' % str( e ) )
 74        log.debug( 'Response was: %s' % response )
 75        return False, response
 76    if id is not None:
 77        try:
 78            assert 'id' in response and response['id'] == id
 79        except Exception, e:
 80            log.error( 'The response id "%s" does not match the request id "%s"' % ( response['id'], id ) )
 81            return False, response
 82    return True, response
 83
 84def jsonrpc_request( method, params=None, id=None, jsonrpc='2.0' ):
 85    if method is None:
 86        log.error( 'jsonrpc_request(): "method" parameter cannot be None' )
 87        return None
 88    request = dict( jsonrpc = jsonrpc, method = method )
 89    if params:
 90        request['params'] = params
 91    if id is not None and id is True:
 92        request['id'] = ''.join( [ random.choice( string.hexdigits ) for i in range( 16 ) ] )
 93    elif id is not None:
 94        request['id'] = id
 95    return request
 96
 97def jsonrpc_response( request=None, id=None, result=None, error=None, jsonrpc='2.0' ):
 98    if result:
 99        rval = dict( jsonrpc = jsonrpc, result = result )
100    elif error:
101        rval = dict( jsonrpc = jsonrpc, error = error )
102    else:
103        msg = 'jsonrpc_response() called with out a "result" or "error" parameter'
104        log.error( msg )
105        rval = dict( jsonrpc = jsonrpc, error = msg )
106    if id is not None:
107        rval['id'] = id
108    elif request is not None and 'id' in request:
109        rval['id'] = request['id']
110    return rval