rendered paste body"""An implementation of the SRPC client protocol in Python.Includes a simple proxy for working over HTTP.Example usage: >>> serv = srpc.http_proxy('http://awesomeblag.org/srpc') >>> post = serv.post.view(1) >>> post {u'content': u'baz', u'title': u'bar', u'author': u'foo'} >>> post[u'content'] = u'hello, world' >>> serv.post.edit(1, post) >>> serv.post.view(1) {u'content': u'hello, world', u'title': u'bar', u'author': 'foo'}"""import reimport urllib2import simplejson__all__ = ['SRPCRequest', 'SRPCError']name_re = re.compile(r'^[a-zA-Z_]([a-zA-Z0-9_]|\.[a-zA-Z_])*[a-zA-Z0-9_]?$')def valid_name(name): return name_re.match(name) is not Noneclass SRPCRequest(object): def __init__(self, name, *params): if valid_name(name): self.name = name self.params = params else: raise ArgumentError("%s is not a valid name" % (name, )) def to_dict(self): return {'version': '1.0', 'name': self.name, 'params': self.params} def __str__(self): return simplejson.dumps(self.to_dict()) def dump(self, stream): simplejson.dump(self.to_dict(), stream)class SRPCError(StandardError): def __init__(self, name, result): self.name = name self.result = result def __str__(self): if self.result: return '%s: %s' % (self.name, self.result) else: return self.nameclass SRPCWrongVersion(SRPCError): def __init__(self, expected): self.expected = expected def __str__(self): return 'Expected version %s, using 1.0' % (self.expected, )class SRPCWrongProc(SRPCError): def __init__(self, name): self.name = name def __str__(self): return 'Unknown procedure %s' % (self.name, )class SRPCWrongParams(SRPCError, TypeError): def __init__(self, result): self.result = result def __str__(self): res = 'Wrong parameters to procedure' if self.result: return '%s (%s)' % (res, self.result) else: return resdef do_request(infile, outfile, name, *params): req = SRPCRequest(name, *params) req.dump(outfile) resp = simplejson.load(infile) if resp['error'] is None: return resp['result'] else: raise SRPCError(resp.version, resp.error, resp.result)class SRPCAttrProxy(object): def __init__(self, infile, outfile, name): self.infile = infile self.outfile = outfile self.name = name def __call__(self, *params): return do_request(self.infile, self.outfile, self.name, *params) def __getattr__(self, name): if name == 'stream' or name == 'name': return object.__getattr__(self, name) else: return SRPCAttrProxy(self.infile, self.outfile, '%s.%s' % (self.name, name))class SRPCProxy(object): def __init__(self, infile, outfile): self.infile = infile self.outfile = outfile def __getattr__(self, name): if name == 'stream': return object.__getattr__(self, name) else: return SRPCAttrProxy(self.infile, self.outfile, name)class SRPCHTTPFile(object): def __init__(self, url): self.url = url self.handle = None def write(self, data): self.handle = urllib2.urlopen(self.url, data) def read(self): self.handle.read()def http_proxy(url): return SRPCProxy(SRPCHTTPFile(url))