Минх обнови решението на 29.04.2015 23:28 (преди над 9 години)
+import os
+import shutil
+
+
+class FileSystemError(BaseException):
+ def __init__(self):
+ self.description = "FileSystemError"
+
+ def __str__(self):
+ return self.description
+
+
+class FileSystemMountError(FileSystemError):
+ def __init__(self):
+ self.description = "FileSystemMountError"
+
+
+class NodeDoesNotExistError(FileSystemError):
+ def __init__(self):
+ self.description = "NodeDoesNotExistError"
+
+
+class DestinationNodeExistsError(FileSystemError):
+ def __init__(self):
+ self.description = "DestinationNodeExistsError"
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ def __init__(self):
+ self.description = "SourceNodeDoesNotExistError"
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ def __init__(self):
+ self.description = "DestinationNodeDoesNotExistError"
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ def __init__(self):
+ self.description = "MountPointDoesNotExistError"
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ def __init__(self):
+ self.description = "MountPointNotADirectoryError"
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ def __init__(self):
+ self.description = "MountPointNotEmptyError"
+
+
+class LinkPathError(FileSystemError):
+ def __init__(self):
+ self.description = "LinkPathError"
+
+
+class NotEnoughSpaceError(FileSystemError):
+ def __init__(self):
+ self.description = "NotEnoughSpaceError"
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ def __init__(self):
+ self.description = "NonExplicitDirectoryDeletionError"
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ def __init__(self):
+ self.description = "NonEmptyDirectoryDeletionError"
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ def __init__(self):
+ self.description = "DestinationNotADirectoryError"
+
+
+class DirectoryHardLinkError(FileSystemError):
+ def __init__(self):
+ self.description = "DirectoryHardLinkError"
+
+
+class Node:
+ def __init__(self, is_directory):
+ self.is_directory = is_directory
+
+
+class File(Node):
+ def __init__(self, path):
+ super().__init__(False)
+ self.path = path
+ self._update_content()
+
+ def append(self, text):
+ this_file = open(self.path, "a")
+ this_file.write(text)
+ this_file.close()
+ self._update_content()
+
+ def truncate(self, text):
+ this_file = open(self.path, "w")
+ this_file.write(text)
+ this_file.close()
+ self._update_content()
+
+ def size(self):
+ this_file = open(self.path, "r")
+ size = this_file.seek(0, 2) + 1
+ this_file.close()
+ return size
+
+ def _update_content(self):
+ this_file = open(self.path, "r")
+ self.content = this_file.read()
+ this_file.close()
+
+
+class Directory(Node):
+ def __init__(self, path):
+ super().__init__(True)
+ self.path = path
+ self.files = list()
+ self.directories = list()
+
+ def directories(self):
+ return self.directories
+
+ def files(self):
+ return self.files
+
+ def nodes(self):
+ return self.files + self.directories
+
+ def size(self):
+ size = 1
+ for _file in self.files:
+ size += _file.size()
+ for directory in self.directories:
+ size += directory.size()
+ return size
+
+class FileSystem:
+ def __init__(self, size):
+ self.size = size
+ self.available_size = size - 1
+ self.files = {}
+ self.directories = {}
+ os.chdir("/")
+
+ def get_node(self, path):
+ if self._valid_path(path):
+ if self._is_file(path):
+ return self.files[path]
+ else:
+ return self.directories[path]
+ else:
+ raise NodeDoesNotExistError
+
+ def create(self, path, directory=False, content=''):
+ containing_path = os.path.split(path)[0]
+
+ if not self._valid_path(containing_path):
+ raise DestinationNodeDoesNotExistError
+ elif not self._has_enough_space(directory, content):
+ raise NotEnoughSpaceError
+ elif self._valid_path(path):
+ raise DestinationNodeExistsError
+ else:
+ if directory:
+ os.mkdir(path)
+ self.directories[path] = Directory(path)
+ self.available_size -= 1
+ else:
+ this_file = open(path, "w")
+ this_file.write(content)
+ this_file.close()
+ self.files[path] = File(path)
+ self.available_size -= len(content)
+
+ def remove(self, path, directory=False, force=True):
+ if not self._valid_path(path):
+ raise NodeDoesNotExistError
+
+ elif self._is_directory(path):
+ if not directory:
+ raise NonExplicitDirectoryDeletionError
+ else:
+ if not self._is_empty_directory(path) and not force:
+ raise NonEmptyDirectoryDeletionError
+ else:
+ self.available_size += self.directories[path].size()
+ shutil.rmtree(path)
+ del self.directories[path]
+
+ elif self._is_file(path):
+ self.available_size += self.files[path].size()
+ os.remove(path)
+ del self.files[path]
+
+ def move(self, source, destination):
+ destination_path = destination + "/" + os.path.split(source)[1]
+
+ if not self._valid_path(source) or not self._valid_path(destination):
+ raise SourceNodeDoesNotExistError
+ elif not self._is_directory(destination):
+ raise DestinationNotADirectoryError
+ elif self._valid_path(destination_path):
+ raise DestinationNodeExistsError
+ else:
+ if self._is_file(source):
+ self.files[destination_path] = self.files[source]
+ del self.files[source]
+ elif self._is_directory(source):
+ self.directories[destination_path] = self.directories[source]
+ del self.directories[source]
+ os.rename(source, destination_path)
+
+ def link(self, source, destination, symbolic=True):
+ if symbolic:
+ if not self._valid_path(source):
+ raise NodeDoesNotExistError
+ else:
+ os.symlink(source, destination)
+ self.files[source] = File(destination)
+ else:
+ if self._is_directory(source):
+ raise DirectoryHardLinkError
+ elif not self._valid_path(source):
+ raise SourceNodeDoesNotExistError
+ else:
+ os.link(source, destination)
+ self.files[source] = File(destination)
+
+ def _valid_path(self, path):
+ return os.path.exists(path)
+
+ def _is_file(self, path):
+ return os.path.isfile(path)
+
+ def _is_directory(self, path):
+ return os.path.isdir(path)
+
+ def _is_empty_directory(self, path):
+ return len(self.directories[path].nodes()) == 0
+
+ def _has_enough_space(self, is_directory, content):
+ if is_directory:
+ return self.available_size - 1 >= 0
+ else:
+ return self.available_size - len(content) >= 0