Христиан обнови решението на 30.04.2015 00:47 (преди над 9 години)
+class FileSystemError(Exception):
+ def __init__(self):
+ self.message = "File system error"
+ super().__init__()
+
+
+class NodeDoesNotExistError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The node does not exist"
+
+
+class DestinationNodeExistsError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The destination node exists"
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The source node does not exist"
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The destination node does not exist"
+
+
+class FileSystemMountError(FileSystemError):
+ def __init__(self):
+ self.message = "An error occured while mounting the file system"
+ super().__init__()
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The mount point does not exist"
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The mount point is not a directory"
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The mount point is not empty"
+
+
+class NotAMountpointError(FileSystemMountError):
+ def __init__(self):
+ super().__init__()
+ self.message = "Not a filesystem to unmount"
+
+
+class NotEnoughSpaceError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "Not enought space in the file system"
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "Not explicit deletion of directory"
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "Deletion of not empty directory"
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The destination is not a directory"
+
+
+class DirectoryHardLinkError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The source is a directory and symbolic is false"
+
+
+class LinkPathError(FileSystemError):
+ def __init__(self):
+ super().__init__()
+ self.message = "The symbolic link references to an unexisting path"
+
+
+class FileSystem:
+ def __init__(self, size):
+ if size == 0:
+ raise NotEnoughSpaceError
+ self.size = size
+ self.__directory = "/"
+ self.available_size = size - 1
+ self.file_system_tree = {"/": Directory("/")}
+
+ def get_sub_directory(self, path):
+ index = path[::-1].find("/") + 1
+ if len(path) == index:
+ return "/"
+ else:
+ return path[:-index]
+
+ def get_node(self, path):
+ object = self.file_system_tree.get(path)
+ if object is not None:
+ return object
+ else:
+ raise NodeDoesNotExistError
+
+ def put_node(self, path, node):
+ self.file_system_tree[path] = node
+
+ def create(self, path, directory=False, content=''):
+ if directory:
+ if self.available_size - 1 < 0:
+ raise NotEnoughSpaceError
+ sub_dir_path = self.get_sub_directory(path)
+
+ if sub_dir_path not in self.file_system_tree.keys():
+ raise DestinationNodeDoesNotExistError
+
+ if path in self.file_system_tree.keys():
+ raise DestinationNodeExistsError
+
+ dir1 = Directory(path)
+
+ sub_dir = self.get_node(sub_dir_path)
+ if dir1 in sub_dir.nodes:
+ raise DestinationNodeExistsError
+
+ self.file_system_tree[path] = dir1
+ self.available_size -= dir1.size
+
+ self.file_system_tree[sub_dir_path].directories.append(dir1)
+ self.file_system_tree[sub_dir_path].nodes.append(dir1)
+ else:
+ if path in self.file_system_tree.keys():
+ raise DestinationNodeExistsError
+
+ if self.available_size - (len(content) + 1) < 0:
+ raise NotEnoughSpaceError
+
+ sub_dir_path = self.get_sub_directory(path)
+
+ if sub_dir_path not in self.file_system_tree.keys():
+ raise DestinationNodeDoesNotExistError
+
+ file1 = File(path, content)
+
+ self.file_system_tree[path] = file1
+ self.available_size -= file1.size
+
+ self.file_system_tree[sub_dir_path].files.append(file1)
+ self.file_system_tree[sub_dir_path].nodes.append(file1)
+
+ def remove(self, path, directory=False, force=True):
+ object_to_remove = self.get_node(path)
+ if (isinstance(object_to_remove, Directory)
+ and not directory):
+ raise NonExplicitDirectoryDeletionError
+ if path not in self.file_system_tree.keys():
+ print(path)
+ print(self.file_system_tree.keys())
+ raise DestinationNodeDoesNotExistError
+ if directory and not force and object_to_remove.nodes:
+ raise NonEmptyDirectoryDeletionError
+
+ objects_to_remove = []
+ for path_to_object in self.file_system_tree.keys():
+ if path_to_object.startswith(path):
+ objects_to_remove.append(path_to_object)
+
+ for path_to_object in objects_to_remove:
+ object_to_remove = self.get_node(path_to_object)
+ self.available_size += object_to_remove.size
+
+ if path_to_object == path:
+ sub_dir_path = self.get_sub_directory(path_to_object)
+ self.file_system_tree[sub_dir_path].nodes\
+ .remove(object_to_remove)
+ if isinstance(object_to_remove, Directory):
+ self.file_system_tree[sub_dir_path].directories\
+ .remove(object_to_remove)
+ elif isinstance(object_to_remove, File):
+ self.file_system_tree[sub_dir_path].files\
+ .remove(object_to_remove)
+
+ del self.file_system_tree[path_to_object]
+
+ def move(self, source, destination):
+ if source not in self.file_system_tree.keys():
+ raise SourceNodeDoesNotExistError
+ if destination not in self.file_system_tree.keys():
+ raise DestinationNodeDoesNotExistError
+ elif not isinstance(self.file_system_tree.get(destination),
+ Directory):
+ raise DestinationNotADirectoryError
+
+ objects_to_move = []
+ for path_to_object in self.file_system_tree.keys():
+ if path_to_object.startswith(source):
+ objects_to_move.append(path_to_object)
+
+ sub_path = self.get_sub_directory(source)
+
+ for path_to_object in objects_to_move:
+ if sub_path != "/":
+ object_to_remove_path = path_to_object[len(sub_path):]
+ else:
+ object_to_remove_path = path_to_object[len(sub_path) - 1:]
+ if destination != "/":
+ new_destination = destination + object_to_remove_path
+ else:
+ new_destination = object_to_remove_path
+
+ if new_destination in self.file_system_tree.keys():
+ raise DestinationNodeExistsError
+
+ self.file_system_tree[new_destination] = \
+ self.file_system_tree[path_to_object]
+
+ object_to_move = self.get_node(path_to_object)
+ sub_dir_path = self.get_sub_directory(path_to_object)
+
+ self.file_system_tree[sub_dir_path].nodes.remove(object_to_move)
+ if self.get_sub_directory(new_destination) == destination:
+ self.file_system_tree[destination].nodes.append(object_to_move)
+ if isinstance(object_to_move, Directory):
+ self.file_system_tree[sub_dir_path].directories\
+ .remove(object_to_move)
+ if self.get_sub_directory(new_destination) == destination:
+ self.file_system_tree[destination].directories\
+ .append(object_to_move)
+ elif isinstance(object_to_move, File):
+ self.file_system_tree[sub_dir_path].files\
+ .remove(object_to_move)
+ if self.get_sub_directory(new_destination) == destination:
+ self.file_system_tree[destination].files\
+ .append(object_to_move)
+
+ for path_to_object in objects_to_move:
+ del self.file_system_tree[path_to_object]
+
+ def link(self, source, destination, symbolic=True):
+ if source not in self.file_system_tree.keys() and symbolic:
+ raise NodeDoesNotExistError
+ if not symbolic and source not in self.file_system_tree.keys():
+ raise SourceNodeDoesNotExistError
+ source_object = self.get_node(source)
+ if isinstance(source_object, Directory) and not symbolic:
+ raise DirectoryHardLinkError
+ if self.available_size - 1 < 0:
+ raise NotEnoughSpaceError
+ if symbolic:
+ symbolic_link = SymbolicLink(destination, source_object)
+ self.put_node(destination, symbolic_link)
+ self.available_size -= symbolic_link.size
+
+ if destination not in self.file_system_tree.keys():
+ print("not valid link")
+ symbolic_link.is_path_valid = False
+
+ sub_dir_path = self.get_sub_directory(destination)
+ self.file_system_tree[sub_dir_path].nodes.append(symbolic_link)
+ self.file_system_tree[sub_dir_path].files.append(symbolic_link)
+ else:
+ self.available_size -= 1
+ hard_link = HardLink(destination, source_object.content)
+ source_object.hard_links.append(hard_link)
+ hard_link.hard_links.append(source_object)
+ self.put_node(destination, hard_link)
+
+ sub_dir_path = self.get_sub_directory(destination)
+ self.file_system_tree[sub_dir_path].nodes.append(hard_link)
+ self.file_system_tree[sub_dir_path].files.append(hard_link)
+
+ def mount(self, file_system, path):
+ object_from_path = self.file_system_tree.get(path)
+ if (isinstance(object_from_path, Directory) and
+ object_from_path.nodes):
+ raise MountPointNotEmptyError
+ if (isinstance(object_from_path, File) and
+ path in self.file_system_tree.keys()):
+ raise MountPointNotADirectoryError
+ if path not in self.file_system_tree.keys():
+ raise MountPointDoesNotExistError
+
+ self.file_system_tree[path].is_mounted_file_system = True
+
+ for object_path in file_system.file_system_tree.keys():
+ if object_path == "/":
+ self.file_system_tree[path] = \
+ file_system.file_system_tree[object_path]
+ else:
+ self.file_system_tree[path + object_path] = \
+ file_system.file_system_tree[object_path]
+
+ def unmount(self, path):
+ if path not in self.file_system_tree.keys():
+ raise NodeDoesNotExistError
+ if not self.file_system_tree[path].is_mounted_file_system:
+ raise NotAMountpointError
+ for object_path in self.file_system_tree.keys():
+ if object_path.startswith(path):
+ self.remove(object_path)
+
+
+class File:
+ def __init__(self, path, content):
+ self.__path = path
+ self.is_directory = False
+ self._content = content
+ self._size = len(self._content) + 1
+ self.hard_links = []
+
+ @property
+ def get_path(self):
+ return self.__path
+
+ @property
+ def content(self):
+ return self._content
+
+ @content.setter
+ def content(self, item):
+ self._content = item
+
+ def append(self, text):
+ self._content += text
+ if self.hard_links != []:
+ for item in self.hard_links:
+ item.content += text
+
+ def truncate(self, text):
+ self._content = text
+ if self.hard_links != []:
+ for item in self.hard_links:
+ item.content = text
+
+ @property
+ def size(self):
+ return self._size
+
+
+class SymbolicLink(File):
+ def __init__(self, path, link_path):
+ File.__init__(self, path, "")
+ self.link_path = link_path
+ self._size = 1
+ self.__is_path_valid = True
+ if isinstance(link_path, File):
+ self._content = link_path.content
+ else:
+ self.__directories = link_path.directories
+ self.__files = link_path.files
+ self.__nodes = link_path.nodes
+
+ @property
+ def nodes(self):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ return self.__nodes
+
+ @nodes.setter
+ def nodes(self, item):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ self.__nodes = item
+
+ @property
+ def content(self):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ return self._content
+
+ @content.setter
+ def content(self, item):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ self._content = item
+
+ @property
+ def directories(self):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ return self.__directories
+
+ @directories.setter
+ def directories(self, item):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ self.__directories = item
+
+ @property
+ def files(self):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ return self.__files
+
+ @files.setter
+ def files(self, item):
+ if not self.__is_path_valid:
+ raise LinkPathError
+ self.__files = item
+
+ @property
+ def size(self):
+ return self._size
+
+ @property
+ def is_path_valid(self):
+ return self.__is_path_valid
+
+ @is_path_valid.setter
+ def is_path_valid(self, item):
+ self.__is_path_valid = item
+
+
+class HardLink(File):
+ def __int__(self, path, content):
+ File.__init__(self, path, content)
+ self._size = 1
+
+
+class Directory:
+ def __init__(self, path):
+ self.__path = path
+ self.is_directory = True
+ self.directories = []
+ self.files = []
+ self.nodes = []
+ self.__size = 1
+ self.is_mounted_file_system = False
+
+ @property
+ def path(self):
+ return self.__path
+
+ @property
+ def size(self):
+ return self.__size
+
+ def __contains__(self, key):
+ return key in self.nodes