Sending JSON command from Python
#6
daledude Wrote:I cant remember where I found this python module. I believe it was on this forum. It makes accessing xbmc via json more pythonic and a dream. If anyone knows who wrote this I'd like to attribute them in the file!

Code:
...

Thanks for that, I've adapted it slightly to use httplib and exposing a single JSONConnection class.

Code:
try:
    import simplejson as json
except ImportError:
    import json
    
import base64
import httplib

__all__ = ['JSONConnection', 'JSONRPCError', 'JSONConnectionError', 'JSONUserPassError']

class JSONError(Exception):
    pass


class JSONRPCError(JSONError):
    def __init__(self, code, message):
        JSONError.__init__(self, message)
        self.code = code
        self.message = message


class JSONConnectionError(JSONError):
    def __init__(self, code, message):
        JSONError.__init__(self, message)
        self.code = code
        self.message = message


class JSONUserPassError(JSONError):
    pass


class JSONConnection(object):
    def __init__(self, host='127.0.0.1', port=8080, username='xbmc', password=''):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self._namespace_cache = {}

    def __getattr__(self, namespace):
        if namespace in self._namespace_cache:
            return self._namespace_cache[namespace]

        nsobj = self.Namespace(namespace, self)
        self._namespace_cache[namespace] = nsobj
        
        return nsobj
    
    class Namespace(object):
        def __init__(self, name, connection):
            self.name = name
            self.connection = connection
            self._id = 1
            self._handler_cache = {}
    
        def __getattr__(self, method):
            if method in self._handler_cache:
                return self._handler_cache[method]
    
            def handler(**kwargs):
                data = {'jsonrpc': '2.0',
                    'id': self._id,
                    'method': '%s.%s' % (self.name, method)
                }
                
                if args:
                    if len(args) == 1:
                        data['params'] = args[0]
                    else:
                        data['params'] = []
                        for arg in args:
                            data['params'].append(arg)
                elif kwargs:
                    data['params'] = {}
                    
                    for k in kwargs:
                        data['params'][k] = kwargs[k]
                        
                postdata = json.dumps(data, ensure_ascii=False)
                postdata = postdata.encode('utf-8')
                
                headers = {'Content-Type': 'application/json-rpc; charset=utf-8'}
        
                if self.connection.password != '':
                    userpass = base64.encodestring('%s:%s' % \
                        (self.connection.username, self.connection.password))[:-1]
                    headers['Authorization'] = 'Basic %s' % userpass
                
                conn = httplib.HTTPConnection(self.connection.host,
                    self.connection.port)
                conn.request('POST', '/jsonrpc', postdata, headers)
        
                data = None
                response = conn.getresponse()
                
                if response.status == httplib.OK:
                    data = response.read()
        
                conn.close()
                
                if response.status != httplib.OK:
                    if response.status == httplib.UNAUTHORIZED:
                        raise JSONUserPassError()
                    else:
                        raise JSONConnectionError(response.status,
                            'Connection Error: %s' % httplib.responses[response.status])
                    
                conn.close()
                
                self._id += 1
                
                if data is not None:
                    response = json.loads(data)
                    if 'error' in response:
                        raise JSONRPCError(json['error']['code'],
                            json['error']['message'])
                        
                    return response['result']
                else:
                    return None
                
            handler.method = method
            self._handler_cache[method] = handler
            
            return handler


if __name__ == '__main__':
    conn = JSONConnection()
    data = conn.JSONRPC.Introspect()
    print(json.dumps(data, sort_keys=True, indent=4))

Edit: Added code to send positional args. XBMC expects a single position arg to be sent as is which may not be valid JSON-RPC 2.0
Reply


Messages In This Thread
[No subject] - by topfs2 - 2011-01-26, 16:34
[No subject] - by daledude - 2011-01-26, 17:32
[No subject] - by topfs2 - 2011-01-26, 17:34
[No subject] - by daledude - 2011-01-26, 17:43
[No subject] - by sffjunkie - 2011-01-27, 11:09
Logout Mark Read Team Forum Stats Members Help
Sending JSON command from Python0