summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrfkelly0 <rfkelly0@67cdc799-7952-0410-af00-57a81ceafa0f>2009-06-03 13:00:25 +0000
committerrfkelly0 <rfkelly0@67cdc799-7952-0410-af00-57a81ceafa0f>2009-06-03 13:00:25 +0000
commit10912480bfe863b1539582d083aa942390d92b54 (patch)
tree299c82792b764c3de74b6028743d3eaa9ad18488
parenta2dfd7cd02521ce51e8c19ee455f87e3cfdf239b (diff)
downloadpyfilesystem-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.py10
-rw-r--r--fs/expose/xmlrpc.py115
-rw-r--r--fs/rpcfs.py120
-rw-r--r--fs/tests.py7
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