diff options
author | rfkelly0 <rfkelly0@67cdc799-7952-0410-af00-57a81ceafa0f> | 2009-06-03 13:00:25 +0000 |
---|---|---|
committer | rfkelly0 <rfkelly0@67cdc799-7952-0410-af00-57a81ceafa0f> | 2009-06-03 13:00:25 +0000 |
commit | 10912480bfe863b1539582d083aa942390d92b54 (patch) | |
tree | 299c82792b764c3de74b6028743d3eaa9ad18488 | |
parent | a2dfd7cd02521ce51e8c19ee455f87e3cfdf239b (diff) | |
download | pyfilesystem-10912480bfe863b1539582d083aa942390d92b54.tar.gz |
move RPCFSServer into 'expose' submodule
git-svn-id: http://pyfilesystem.googlecode.com/svn/branches/rfk-ideas@149 67cdc799-7952-0410-af00-57a81ceafa0f
-rw-r--r-- | fs/expose/sftp.py | 10 | ||||
-rw-r--r-- | fs/expose/xmlrpc.py | 115 | ||||
-rw-r--r-- | fs/rpcfs.py | 120 | ||||
-rw-r--r-- | fs/tests.py | 7 |
4 files changed, 130 insertions, 122 deletions
diff --git a/fs/expose/sftp.py b/fs/expose/sftp.py index 058a251..9147f3a 100644 --- a/fs/expose/sftp.py +++ b/fs/expose/sftp.py @@ -35,11 +35,6 @@ from fs.errors import * from fs.helpers import * -# Default host key used by BaseSFTPServer -# -DEFAULT_HOST_KEY = paramiko.RSAKey.from_private_key(StringIO("-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKCAIEAl7sAF0x2O/HwLhG68b1uG8KHSOTqe3Cdlj5i/1RhO7E2BJ4B\n3jhKYDYtupRnMFbpu7fb21A24w3Y3W5gXzywBxR6dP2HgiSDVecoDg2uSYPjnlDk\nHrRuviSBG3XpJ/awn1DObxRIvJP4/sCqcMY8Ro/3qfmid5WmMpdCZ3EBeC0CAwEA\nAQKCAIBSGefUs5UOnr190C49/GiGMN6PPP78SFWdJKjgzEHI0P0PxofwPLlSEj7w\nRLkJWR4kazpWE7N/bNC6EK2pGueMN9Ag2GxdIRC5r1y8pdYbAkuFFwq9Tqa6j5B0\nGkkwEhrcFNBGx8UfzHESXe/uE16F+e8l6xBMcXLMJVo9Xjui6QJBAL9MsJEx93iO\nzwjoRpSNzWyZFhiHbcGJ0NahWzc3wASRU6L9M3JZ1VkabRuWwKNuEzEHNK8cLbRl\nTyH0mceWXcsCQQDLDEuWcOeoDteEpNhVJFkXJJfwZ4Rlxu42MDsQQ/paJCjt2ONU\nWBn/P6iYDTvxrt/8+CtLfYc+QQkrTnKn3cLnAkEAk3ixXR0h46Rj4j/9uSOfyyow\nqHQunlZ50hvNz8GAm4TU7v82m96449nFZtFObC69SLx/VsboTPsUh96idgRrBQJA\nQBfGeFt1VGAy+YTLYLzTfnGnoFQcv7+2i9ZXnn/Gs9N8M+/lekdBFYgzoKN0y4pG\n2+Q+Tlr2aNlAmrHtkT13+wJAJVgZATPI5X3UO0Wdf24f/w9+OY+QxKGl86tTQXzE\n4bwvYtUGufMIHiNeWP66i6fYCucXCMYtx6Xgu2hpdZZpFw==\n-----END RSA PRIVATE KEY-----\n")) - - try: from functools import wraps except ImportError: @@ -47,6 +42,11 @@ except ImportError: return f +# Default host key used by BaseSFTPServer +# +DEFAULT_HOST_KEY = paramiko.RSAKey.from_private_key(StringIO("-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKCAIEAl7sAF0x2O/HwLhG68b1uG8KHSOTqe3Cdlj5i/1RhO7E2BJ4B\n3jhKYDYtupRnMFbpu7fb21A24w3Y3W5gXzywBxR6dP2HgiSDVecoDg2uSYPjnlDk\nHrRuviSBG3XpJ/awn1DObxRIvJP4/sCqcMY8Ro/3qfmid5WmMpdCZ3EBeC0CAwEA\nAQKCAIBSGefUs5UOnr190C49/GiGMN6PPP78SFWdJKjgzEHI0P0PxofwPLlSEj7w\nRLkJWR4kazpWE7N/bNC6EK2pGueMN9Ag2GxdIRC5r1y8pdYbAkuFFwq9Tqa6j5B0\nGkkwEhrcFNBGx8UfzHESXe/uE16F+e8l6xBMcXLMJVo9Xjui6QJBAL9MsJEx93iO\nzwjoRpSNzWyZFhiHbcGJ0NahWzc3wASRU6L9M3JZ1VkabRuWwKNuEzEHNK8cLbRl\nTyH0mceWXcsCQQDLDEuWcOeoDteEpNhVJFkXJJfwZ4Rlxu42MDsQQ/paJCjt2ONU\nWBn/P6iYDTvxrt/8+CtLfYc+QQkrTnKn3cLnAkEAk3ixXR0h46Rj4j/9uSOfyyow\nqHQunlZ50hvNz8GAm4TU7v82m96449nFZtFObC69SLx/VsboTPsUh96idgRrBQJA\nQBfGeFt1VGAy+YTLYLzTfnGnoFQcv7+2i9ZXnn/Gs9N8M+/lekdBFYgzoKN0y4pG\n2+Q+Tlr2aNlAmrHtkT13+wJAJVgZATPI5X3UO0Wdf24f/w9+OY+QxKGl86tTQXzE\n4bwvYtUGufMIHiNeWP66i6fYCucXCMYtx6Xgu2hpdZZpFw==\n-----END RSA PRIVATE KEY-----\n")) + + def report_sftp_errors(func): """Decorator to catch and report FS errors as SFTP error codes. diff --git a/fs/expose/xmlrpc.py b/fs/expose/xmlrpc.py new file mode 100644 index 0000000..1f57a16 --- /dev/null +++ b/fs/expose/xmlrpc.py @@ -0,0 +1,115 @@ +""" + + fs.expose.xmlrpc: server to expose an FS via XML-RPC + +This module provides the necessary infrastructure to expose an FS object +over XML-RPC. The main class is 'RPCFSServer', a SimpleXMLRPCServer subclass +designed to expose an underlying FS. + +If you need to use a more powerful server than SimpleXMLRPCServer, you can +use the RPCFSInterface class to provide an XML-RPC-compatible wrapper around +an FS object, which can then be exposed using whatever server you choose +(e.g. Twisted's XML-RPC server). + +""" + +import xmlrpclib +from SimpleXMLRPCServer import SimpleXMLRPCServer + + +class RPCFSInterface(object): + """Wrapper to expose an FS via a XML-RPC compatible interface. + + The only real trick is using xmlrpclib.Binary objects to transport + the contents of files. + """ + + def __init__(self,fs): + self.fs = fs + + def get_contents(self,path): + data = self.fs.getcontents(path) + return xmlrpclib.Binary(data) + + def set_contents(self,path,data): + self.fs.createfile(path,data.data) + + def exists(self,path): + return self.fs.exists(path) + + def isdir(self,path): + return self.fs.isdir(path) + + def isfile(self,path): + return self.fs.isfile(path) + + def listdir(self,path="./",wildcard=None,full=False,absolute=False,dirs_only=False,files_only=False): + return list(self.fs.listdir(path,wildcard,full,absolute,dirs_only,files_only)) + + def makedir(self,path,recursive=False,allow_recreate=False): + return self.fs.makedir(path,recursive,allow_recreate) + + def remove(self,path): + return self.fs.remove(path) + + def removedir(self,path,recursive=False,force=False): + return self.fs.removedir(path,recursive,force) + + def rename(self,src,dst): + return self.fs.rename(src,dst) + + def getinfo(self,path): + return self.fs.getinfo(path) + + def desc(self,path): + return self.fs.desc(path) + + def getattr(self,path,attr): + return self.fs.getattr(path,attr) + + def setattr(self,path,attr,value): + return self.fs.setattr(path,attr,value) + + def copy(self,src,dst,overwrite=False,chunk_size=16384): + return self.fs.copy(src,dst,overwrite,chunk_size) + + def move(self,src,dst,overwrite=False,chunk_size=16384): + return self.fs.move(src,dst,overwrite,chunk_size) + + def movedir(self,src,dst,overwrite=False,ignore_errors=False,chunk_size=16384): + return self.fs.movedir(src,dst,overwrite,ignore_errors,chunk_size) + + def copydir(self,src,dst,overwrite=False,ignore_errors=False,chunk_size=16384): + return self.fs.copydir(src,dst,overwrite,ignore_errors,chunk_size) + + +class RPCFSServer(SimpleXMLRPCServer): + """Server to expose an FS object via XML-RPC. + + This class takes as its first argument an FS instance, and as its second + argument a (hostname,port) tuple on which to listen for XML-RPC requests. + Example: + + fs = OSFS('/var/srv/myfiles') + s = RPCFSServer(fs,("",8080)) + s.serve_forever() + + To cleanly shut down the server after calling serve_forever, set the + attribute "serve_more_requests" to False. + """ + + def __init__(self,fs,addr,requestHandler=None,logRequests=None): + kwds = dict(allow_none=True) + if requestHandler is not None: + kwds['requestHandler'] = requestHandler + if logRequests is not None: + kwds['logRequests'] = logRequests + self.serve_more_requests = True + SimpleXMLRPCServer.__init__(self,addr,**kwds) + self.register_instance(RPCFSInterface(fs)) + + def serve_forever(self): + """Override serve_forever to allow graceful shutdown.""" + while self.serve_more_requests: + self.handle_request() + diff --git a/fs/rpcfs.py b/fs/rpcfs.py index 8db6da3..904bae9 100644 --- a/fs/rpcfs.py +++ b/fs/rpcfs.py @@ -1,30 +1,18 @@ """ - fs.rpcfs: Client and Server to expose an FS via XML-RPC + fs.rpcfs: client to access an FS via XML-RPC -This module provides the following pair of classes that can be used to expose -a remote filesystem using XML-RPC: - - RPCFSServer: a subclass of SimpleXMLRPCServer that exposes the methods - of an FS instance via XML-RPC - - RPCFS: a subclass of FS that delegates all filesystem operations to - a remote server using XML-RPC. - -If you need to use a more powerful server than SimpleXMLRPCServer, you can -use the RPCFSInterface class to provide an XML-RPC-compatible wrapper around -an FS object, which can then be exposed using whatever server you choose -(e.g. Twisted's XML-RPC server). +This module provides the class 'RPCFS' to access a remote FS object over +XML-RPC. You probably want to use this in conjunction with the 'RPCFSServer' +class from the fs.expose.xmlrpc module. """ import xmlrpclib -from SimpleXMLRPCServer import SimpleXMLRPCServer from fs.base import * from StringIO import StringIO - if hasattr(StringIO,"__exit__"): class StringIO(StringIO): pass @@ -100,7 +88,7 @@ class RPCFS(FS): """Access a filesystem exposed via XML-RPC. This class provides the client-side logic for accessing a remote FS - object, and is dual to the RPCFSServer class also defined in this module. + object, and is dual to the RPCFSServer class defined in fs.expose.xmlrpc. Example: @@ -113,7 +101,7 @@ class RPCFS(FS): The only required argument is the uri of the server to connect to. This will be passed to the underlying XML-RPC server proxy - object along with the 'transport' argument if it is provided. + object, along with the 'transport' argument if it is provided. """ self.uri = uri self._transport = transport @@ -224,99 +212,3 @@ class RPCFS(FS): return self.proxy.copydir(src,dst,overwrite,ignore_errors,chunk_size) -class RPCFSInterface(object): - """Wrapper to expose an FS via a XML-RPC compatible interface. - - The only real trick is using xmlrpclib.Binary objects to transport - the contents of files. - """ - - def __init__(self,fs): - self.fs = fs - - def get_contents(self,path): - data = self.fs.getcontents(path) - return xmlrpclib.Binary(data) - - def set_contents(self,path,data): - self.fs.createfile(path,data.data) - - def exists(self,path): - return self.fs.exists(path) - - def isdir(self,path): - return self.fs.isdir(path) - - def isfile(self,path): - return self.fs.isfile(path) - - def listdir(self,path="./",wildcard=None,full=False,absolute=False,dirs_only=False,files_only=False): - return list(self.fs.listdir(path,wildcard,full,absolute,dirs_only,files_only)) - - def makedir(self,path,recursive=False,allow_recreate=False): - return self.fs.makedir(path,recursive,allow_recreate) - - def remove(self,path): - return self.fs.remove(path) - - def removedir(self,path,recursive=False,force=False): - return self.fs.removedir(path,recursive,force) - - def rename(self,src,dst): - return self.fs.rename(src,dst) - - def getinfo(self,path): - return self.fs.getinfo(path) - - def desc(self,path): - return self.fs.desc(path) - - def getattr(self,path,attr): - return self.fs.getattr(path,attr) - - def setattr(self,path,attr,value): - return self.fs.setattr(path,attr,value) - - def copy(self,src,dst,overwrite=False,chunk_size=16384): - return self.fs.copy(src,dst,overwrite,chunk_size) - - def move(self,src,dst,overwrite=False,chunk_size=16384): - return self.fs.move(src,dst,overwrite,chunk_size) - - def movedir(self,src,dst,overwrite=False,ignore_errors=False,chunk_size=16384): - return self.fs.movedir(src,dst,overwrite,ignore_errors,chunk_size) - - def copydir(self,src,dst,overwrite=False,ignore_errors=False,chunk_size=16384): - return self.fs.copydir(src,dst,overwrite,ignore_errors,chunk_size) - - -class RPCFSServer(SimpleXMLRPCServer): - """Server to expose an FS object via XML-RPC. - - This class takes as its first argument an FS instance, and as its second - argument a (hostname,port) tuple on which to listen for XML-RPC requests. - Example: - - fs = OSFS('/var/srv/myfiles') - s = RPCFSServer(fs,("",8080)) - s.serve_forever() - - To cleanly shut down the server after calling serve_forever, set the - attribute "serve_more_requests" to False. - """ - - def __init__(self,fs,addr,requestHandler=None,logRequests=None): - kwds = dict(allow_none=True) - if requestHandler is not None: - kwds['requestHandler'] = requestHandler - if logRequests is not None: - kwds['logRequests'] = logRequests - self.serve_more_requests = True - SimpleXMLRPCServer.__init__(self,addr,**kwds) - self.register_instance(RPCFSInterface(fs)) - - def serve_forever(self): - """Override serve_forever to allow graceful shutdown.""" - while self.serve_more_requests: - self.handle_request() - diff --git a/fs/tests.py b/fs/tests.py index 495c872..6ce2a5f 100644 --- a/fs/tests.py +++ b/fs/tests.py @@ -14,6 +14,8 @@ import unittest import shutil import tempfile import pickle +import socket +import threading import base as fs from helpers import * @@ -755,8 +757,7 @@ class TestS3FS(unittest.TestCase,FSTestCases): import rpcfs -import socket -import threading +from fs.expose.xmlrpc import RPCFSServer class TestRPCFS(unittest.TestCase,FSTestCases): def setUp(self): @@ -764,7 +765,7 @@ class TestRPCFS(unittest.TestCase,FSTestCases): self.server = None while not self.server: try: - self.server = rpcfs.RPCFSServer(tempfs.TempFS(),("localhost",self.port),logRequests=False) + self.server = RPCFSServer(tempfs.TempFS(),("localhost",self.port),logRequests=False) except socket.error, e: if e.args[1] == "Address already in use": self.port += 1 |