Йоан обнови решението на 28.04.2015 22:48 (преди над 9 години)
+class FileSystemError(Exception):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeExistsError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class FileSystemMountError(FileSystemError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class NotAMountpointError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class LinkNotFound(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileSystemError):
+ pass
+
+
+class LinkPathError(FileSystemError):
+ pass
+
+
+class Node:
+ @property
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, name):
+ self._name = name
+
+ @property
+ def is_directory(self):
+ return type(self) is Directory
+
+ @property
+ def is_file(self):
+ return type(self) is File
+
+
+class File(Node):
+ def __init__(self, name, content=''):
+ self._content = content
+ self._name = name
+
+ @property
+ def content(self):
+ return self._content
+
+ @content.setter
+ def content(self, content):
+ self._content = content
+
+ @property
+ def size(self):
+ return len(self._content) + 1
+
+ def append(self, text):
+ self._content = self._content + str(text)
+
+ def truncate(self, text):
+ self._content = str(text)
+
+
+class Link(Node):
+ def __init__(self, name, node=None):
+ self._name = name
+
+ if node:
+ self._is_file = node.is_file
+ self._link_path = node
+
+ def __getattr__(self, attr):
+ if self._link_path and hasattr(self._link_path, attr):
+ return getattr(self._link_path, attr)
+ else:
+ raise LinkPathError
+
+ @property
+ def is_file(self):
+ return self._is_file
+
+ @property
+ def is_directory(self):
+ return not self._is_file
+
+ @property
+ def link_path(self):
+ return self._link_path
+
+ @property
+ def size(self):
+ return self._link_path.size
+
+
+class Directory(Node):
+ def __init__(self, name, file_system=False):
+ self._nodes = []
+ self._name = name
+ self._is_file_system = file_system
+
+ @property
+ def is_empty(self):
+ return not self._nodes
+
+ @property
+ def directories(self):
+ return [item for item in self._nodes if item.is_directory]
+
+ @property
+ def files(self):
+ return [item for item in self._nodes if item.is_file]
+
+ @property
+ def nodes(self):
+ return self._nodes
+
+ @property
+ def nodes_dict(self):
+ return dict((item.name, item) for item in self._nodes)
+
+ @property
+ def is_file_system(self):
+ return self._is_file_system
+
+ @is_file_system.setter
+ def is_file_system(self, is_file_system):
+ self._is_file_system = is_file_system
+
+ @property
+ def size(self):
+ size = 1
+
+ for node in self.nodes:
+ if type(node) is FileSystem:
+ size += 1
+ else:
+ size += node.size
+
+ return size
+
+
+class FileSystem:
+ def __init__(self, size):
+ self._size = size
+ self._root = Directory('/')
+ self._available_size = size - self._root.size
+
+ @property
+ def size(self):
+ return self._size
+
+ @property
+ def available_size(self):
+ return self._size - self._root.size
+
+ def get_node(self, path):
+ node_paths = filter(None, path.split('/'))
+
+ if '/' not in path and not path:
+ raise NodeDoesNotExistError
+
+ current_node = self._root
+
+ for node_path in node_paths:
+ if node_path in current_node.nodes_dict:
+ current_node = current_node.nodes_dict[node_path]
+ else:
+ raise NodeDoesNotExistError
+
+ return current_node
+
+ def create(self, path, directory=False, content=''):
+ destination, name = self._split_path(path)
+
+ try:
+ destination_directory = self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ if name in destination_directory.nodes_dict:
+ raise DestinationNodeExistsError
+ elif len(content) >= self.available_size:
+ raise NotEnoughSpaceError
+
+ if directory is True:
+ destination_directory.nodes.append(Directory(name))
+ else:
+ destination_directory.nodes.append(File(name, content))
+
+ def remove(self, path, directory=False, force=True):
+ destination, name = self._split_path(path)
+
+ node = self.get_node(path)
+ parent = self.get_node(destination)
+ size = node.size
+
+ if directory is False and node.is_directory:
+ raise NonExplicitDirectoryDeletionError
+ elif directory is True and force is False:
+ if node.is_empty is False:
+ raise NonEmptyDirectoryDeletionError
+ else:
+ parent.nodes.remove(node)
+
+ def move(self, source, destination):
+ source_destination, source_name = self._split_path(source)
+
+ try:
+ node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+
+ try:
+ destination_node = self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ if destination_node.is_file:
+ raise DestinationNotADirectoryError
+
+ if source_name in destination_node.nodes_dict:
+ raise DestinationNodeExistsError
+
+ self.remove(source, node.is_directory, True)
+
+ destination_node.nodes.append(node)
+
+ def link(self, source, destination, symbolic=True):
+ parent_destination, name = self._split_path(destination)
+ parent = self.get_node(parent_destination)
+
+ if symbolic is True:
+ node = self.get_node(source)
+
+ parent.nodes.append(Link(name, node))
+ else:
+ try:
+ node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+
+ if node.is_directory:
+ raise DirectoryHardLinkError
+
+ linked_node = File(name)
+ linked_node.content = self.get_node(source).content
+
+ parent.nodes.append(linked_node)
+
+ def mount(self, file_system, path):
+ destination, name = self._split_path(path)
+
+ parent = self.get_node(destination)
+
+ try:
+ destination = self.get_node(path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError
+
+ if destination.is_directory is False:
+ raise MountPointNotADirectoryError
+ elif destination.is_empty is False:
+ raise MountPointNotEmptyError
+
+ parent.nodes.remove(destination)
+
+ directory = file_system.get_node('/')
+ directory.name = name
+ directory.is_file_system = True
+
+ parent.nodes.append(directory)
+
+ def unmount(self, path):
+ destination, name = self._split_path(path)
+ file_system = self.get_node(path)
+ parent = self.get_node(destination)
+
+ if not file_system.is_file_system:
+ raise NotAMountpointError
+
+ parent.nodes.remove(file_system)
+ parent.nodes.append(Directory(name))
+
+ def _split_path(self, path):
+ destination, name = tuple(path.rsplit('/', 1))
+
+ if not destination:
+ destination = '/'
+
+ return (destination, name)