from zope.interface import Interface, Attribute class VFSError(Exception): """Base class for all VFS errors.""" class PermissionError(VFSError): """The user does not have permission to perform the requested operation.""" class NotFoundError(VFSError): """The file or directory does not exist.""" class AlreadyExistsError(VFSError): """The file or directory already exists.""" class IFileSystemNode(Interface): parent = Attribute( """parent node""" ) def getMetadata(): """ returns a map of arbitrary metadata. As an example, here's what SFTP expects (but doesn't require): - C{'size'}: size of file in bytes - C{'uid'}: owner of the file - C{'gid'}: group owner of the file - C{'permissions'}: file permissions - C{'atime'}: last time the file was accessed - C{'mtime'}: last time the file was modified - C{'nlink'}: number of links to the file Protocols that need metadata should handle the case when a particular value isn't available as gracefully as possible. """ # XXX: There should be a setMetadata, probably taking a map of the same form # returned by getMetadata (although obviously keys like 'nlink' aren't # settable. Something like: # def setMetadata(metadata): # """Sets metadata for a node. # # Unrecognised keys will be ignored (but invalid values for a recognised # key may cause an error to be raised). # # Typical keys are 'permissions', 'uid', 'gid', 'atime' and 'mtime'. # # @param metadata: a dict, like the one getMetadata returns. # """ # osfs.OSNode implements this; other backends should be similarly updated. # -- spiv, 2006-06-02 def remove(): """ Removes this node. An error is raised if the node is a directory and is not empty. """ def rename(newName): """ Renames this node to newName. newName can be in a different directory. If the destination is an existing directory, an error will be raised. """ class IFileSystemLeaf(IFileSystemNode): def open(flags): """ Opens the file with flags. Flags should be a bitmask based on the os.O_* flags. """ def close(): """closes this node""" def readChunk(offset, length): """ Leaf should have been previously opened with suitable flags. Reads length bytes or until the end of file from this leaf from the given offset. """ def writeChunk(offset, data): """ Leaf should have been previously opened with suitable flags. Writes data to leaf from the given offset. """ class IFileSystemContainer(IFileSystemNode): def children(): """ returns a list of 2 element tuples [ ( path, nodeObject ) ] """ def child(childName): """ Returns a node object for child childName @raises NotFoundError if no child with that name exists. """ def createDirectory(childName): """ Creates a new folder named childName under this folder. An error is raised if the folder already exists. """ def createFile(childName, exclusive=True): """ Creates a new file named childName under this folder. If exclusive is True (the default), an AlreadyExistsError is raised if the file already exists. """ def exists(childName): """ returns True if container has a child childName, False otherwise """