# HG changeset patch # User Ben Croston # Date 1325463161 0 # Node ID 34611402352863698082320c6d3997c345073dbf # Parent d86e7357a91b3512b21b424e4fca8393f4c27471 Added __getfile__ mechanism diff -r d86e7357a91b -r 346114023528 AuthRPC/client/__init__.py --- a/AuthRPC/client/__init__.py Sun Jan 01 15:59:39 2012 +0000 +++ b/AuthRPC/client/__init__.py Mon Jan 02 00:12:41 2012 +0000 @@ -59,9 +59,13 @@ if self._password is not None: request['password'] = _encrypt_password(self._password) + if request['method'] == '__getfile__': + return self.call(json.dumps(request)) + resp = self.call(json.dumps(request)) if resp is None: raise Exception('Server response is None') + resp = json.loads(resp.decode()) if resp['id'] != request['id']: raise Exception('Inconsistent JSON request id returned') if resp['error'] is not None: @@ -165,7 +169,7 @@ except socket.error: raise NetworkSocketException if response.status == 200: - return json.loads(response.read().decode()) + return response.read() elif response.status == 400: raise BadRequestException(response.read().decode()) elif response.status == 401: @@ -182,10 +186,7 @@ raise Exception('HTTP Status %s'%response.status) def __repr__(self): - return ( - "" % - (self.__host, self.__handler) - ) + return "" %(self.__host, self.__handler) __str__ = __repr__ @@ -193,7 +194,6 @@ # magic method dispatcher return _Method(self._request, name, self._username, self._password) - ################# batch calls vvv class _BatchMethod(object): @@ -256,7 +256,7 @@ req += ', '.join(str(q) for q in self._queue) req += ']' - response = self._server._request(req) + response = json.loads(self._server._request(req).decode()) result = [] for i,r in enumerate(response): diff -r d86e7357a91b -r 346114023528 AuthRPC/server/__init__.py --- a/AuthRPC/server/__init__.py Sun Jan 01 15:59:39 2012 +0000 +++ b/AuthRPC/server/__init__.py Mon Jan 02 00:12:41 2012 +0000 @@ -86,31 +86,42 @@ except KeyError as e: raise exc.HTTPBadRequest("JSON body missing parameter: %s" % e) self._check_auth(username, password, req.user_agent, id) + + if method == '__getfile__': + try: + with open(params[0],'rb') as f: + body = f.read() + except IOError: + raise exc.HTTPNotFound('File not found: %s'%params[0]) + return Response(content_type='application/octet-stream', + body=body) + result = self._process_single(method, params, id) return Response(content_type='application/json', body=dumps(result).encode()) def _check_auth(self, username, password, user_agent, id=None): - if self.auth is not None: - try: - auth_result = self.auth(username, password, user_agent) - except: - text = traceback.format_exc() - exc_value = sys.exc_info()[1] - error_value = dict( - name='JSONRPCError', - code=100, - message=str(exc_value), - error=text) - return Response( - status=500, - content_type='application/json', - body=dumps(dict(result=None, - error=error_value, - id=id))) - if not auth_result: - raise exc.HTTPUnauthorized() + if self.auth is None: + return + try: + auth_result = self.auth(username, password, user_agent) + except: + text = traceback.format_exc() + exc_value = sys.exc_info()[1] + error_value = dict( + name='JSONRPCError', + code=100, + message=str(exc_value), + error=text) + return Response( + status=500, + content_type='application/json', + body=dumps(dict(result=None, + error=error_value, + id=id))) + if not auth_result: + raise exc.HTTPUnauthorized() def _process_single(self, method, params, id): retval = {} @@ -130,7 +141,7 @@ break elif method.startswith('%s.'%self.obj.__class__.__name__): method = method.replace('%s.'%self.obj.__class__.__name__,'',1) - if method.startswith('_'): + if method.startswith('_') and method != '__getfile__': retval['error'] = 'Bad method name %s: must not start with _' % method return retval try: diff -r d86e7357a91b -r 346114023528 AuthRPC/tests.py --- a/AuthRPC/tests.py Sun Jan 01 15:59:39 2012 +0000 +++ b/AuthRPC/tests.py Mon Jan 02 00:12:41 2012 +0000 @@ -156,6 +156,29 @@ with self.assertRaises(ProtocolError): self.client.api.test(1, '2', three=3) +class FileTest(AuthRPCTests): + def runTest(self): + filename = 'LICENCE.txt' + with open(filename,'rb') as f: + source = f.read() + self.assertEqual(self.client.__getfile__(filename), source) + +class NonExistentFileTest(AuthRPCTests): + def runTest(self): + from client import NotFoundException + with self.assertRaises(NotFoundException): + self.client.__getfile__('nonexistant.file') + +class BadAuthFileTest(unittest.TestCase): + def runTest(self): + from client import ServerProxy, UnauthorisedException + self.client = ServerProxy('http://localhost:1337/', + username='testuser', + password='s3cr3t', + user_agent='InternetExploiter') + with self.assertRaises(UnauthorisedException): + self.client.__getfile__('LICENCE.txt') + class BatchTest(AuthRPCTests): def runTest(self): from client import BatchCall @@ -205,6 +228,9 @@ suite.addTest(AddTest()) suite.addTest(ReturnNothing()) suite.addTest(ProtocolErrorTest()) + suite.addTest(FileTest()) + suite.addTest(NonExistentFileTest()) + suite.addTest(BadAuthFileTest()) suite.addTest(BatchTest()) suite.addTest(SetFinishedFlag()) suite.addTest(BadBatchTest()) diff -r d86e7357a91b -r 346114023528 CHANGELOG.txt --- a/CHANGELOG.txt Sun Jan 01 15:59:39 2012 +0000 +++ b/CHANGELOG.txt Mon Jan 02 00:12:41 2012 +0000 @@ -1,6 +1,10 @@ Change Log ========== +0.2.0a +------ +- Added __getfile__ mechanism + 0.1.0a ------ - Added batch requests diff -r d86e7357a91b -r 346114023528 README.txt --- a/README.txt Sun Jan 01 15:59:39 2012 +0000 +++ b/README.txt Mon Jan 02 00:12:41 2012 +0000 @@ -33,6 +33,7 @@ password='secret', user_agent='myprogram') retval = client.do_something('test') + file_contents = client.__getfile__('myfile.pdf') batch = BatchCall(client) batch.do_something('call 1') batch.do_something('call 2') diff -r d86e7357a91b -r 346114023528 setup.py --- a/setup.py Sun Jan 01 15:59:39 2012 +0000 +++ b/setup.py Mon Jan 02 00:12:41 2012 +0000 @@ -18,7 +18,7 @@ extra['use_2to3'] = True setup(name = 'AuthRPC', - version = '0.1.0a', + version = '0.2.0a', packages = find_packages(), install_requires = 'WebOb>=1.2b2', author = 'Ben Croston',