Георги обнови решението на 30.04.2015 02:56 (преди над 9 години)
+class FileSystemError(Exception):
+ def __init__(self, message=''):
+ self.message = message
+
+
+class DestinationNodeExistsError(FileSystemError):
+ pass
+
+
+class NodeDoesNotExistError(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:
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class FileSystemDirectoryError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemDirectoryError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemDirectoryError):
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemDirectoryError):
+ pass
+
+
+class DestinationNodeExistError(FileSystemDirectoryError):
+ pass
+
+
+class FileSystemLinkError(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileSystemLinkError):
+ pass
+
+
+class BaseFile:
+ def __init__(self, is_directory):
+ self.is_directory = is_directory
+
+
+class File(BaseFile):
+ def __init__(self, content):
+ BaseFile.__init__(self, False)
+ self.content = content
+
+ def __getattr__(self, name):
+ if name == 'size':
+ return len(self.content) + 1
+
+ def append(self, text):
+ self.content += text
+
+ def truncate(self, text):
+ self.content = text
+
+
+class Directory(BaseFile):
+ def __init__(self):
+ BaseFile.__init__(self, True)
+ self.files_pool = {}
+ self.dirs_pool = {}
+
+ def __getattribute__(self, name):
+ def get_objects(name):
+ return list(object.__getattribute__(self, name).values())
+
+ def get_pool(name):
+ return object.__getattribute__(self, name)
+
+ attributes = {
+ 'files': get_objects('files_pool'),
+ 'directories': get_objects('dirs_pool'),
+ 'nodes': get_objects('files_pool') + get_objects('dirs_pool'),
+ 'nodes_pool': dict(get_pool('files_pool'), **get_pool('dirs_pool'))
+ }
+
+ if name in attributes:
+ return attributes[name]
+ else:
+ return BaseFile.__getattribute__(self, name)
+
+ def __getattr__(self, name):
+ def get_size():
+ size = 1
+
+ for current_file in self.files:
+ size += current_file.size
+
+ for current_directory in self.directories:
+ size += current_directory.size
+
+ return size
+
+ attributes = {
+ 'size': get_size()
+ }
+
+ return attributes['size']
+
+ def __getitem__(self, current_object):
+ if current_object in self.nodes_pool:
+ return self.nodes_pool[current_object]
+ else:
+ raise NodeDoesNotExistError
+
+ def add_file(self, file_name, file_object):
+ self.files_pool.update({file_name: file_object})
+
+ def add_directory(self, directory_name, directory_object):
+ self.dirs_pool.update({directory_name: directory_object})
+
+ def remove(self, object_to_remove, directory=False, force=True):
+ if object_to_remove not in self.nodes_pool:
+ raise NodeDoesNotExistError
+
+ if object_to_remove in self.dirs_pool:
+ if not directory:
+ raise NonExplicitDirectoryDeletionError
+
+ if not self.dirs_pool[object_to_remove].nodes == [] and not force:
+ raise NonEmptyDirectoryDeletionError
+
+ del self.dirs_pool[object_to_remove]
+ else:
+ del self.files_pool[object_to_remove]
+
+
+class BaseLink:
+ def __init__(self, link_path, symbolic=True):
+ self.link_path = link_path
+ self.symbolic = symbolic
+
+
+class SymbolicLink(BaseLink):
+ def __init__(self, link_path):
+ BaseLink.__init__(self, link_path)
+
+
+class HardLink(BaseLink):
+ def __init__(self, link_path, symbolic):
+ BaseLink.__init__(self, link_path, symbolic)
+
+
+class FileSystem:
+ def __init__(self, size):
+ if not size > 0:
+ raise NotEnoughSpaceError
+
+ self.home = Directory()
+ self.size = size
+ self.available_size = self.size - self.home.size
+
+ def __find_object(self, current_directory, path):
+ if path.count('/') < 2:
+ if len(path) > 1:
+ current_object = path.split('/')[-1]
+ return current_directory[current_object]
+ else:
+ return current_directory
+ else:
+ current_path, rest_path = path.lstrip('/').split('/', 1)
+ current_directory = current_directory[current_path.lstrip('/')]
+ return self.__find_object(current_directory, '/' + rest_path)
+
+ def get_node(self, path):
+ if path == '':
+ raise NodeDoesNotExistError
+ else:
+ return self.__find_object(self.home, path)
+
+ def create(self, path, directory=False, content=''):
+ current_path, object_name = path.rsplit('/', 1)
+
+ try:
+ parent_directory = self.__find_object(self.home, current_path)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ try:
+ self.get_node(path)
+ except NodeDoesNotExistError:
+ pass
+ else:
+ raise DestinationNodeExistsError
+
+ if not directory:
+ new_file = File(content)
+ new_object_size = new_file.size
+
+ if not self.available_size - new_object_size >= 0:
+ raise NotEnoughSpaceError
+
+ parent_directory.add_file(object_name, new_file)
+ else:
+ new_directory = Directory()
+ new_object_size = new_directory.size
+
+ if not self.available_size - new_object_size >= 0:
+ raise NotEnoughSpaceError
+ parent_directory.add_directory(object_name, new_directory)
+
+ self.available_size -= new_object_size
+
+ def remove(self, path, directory=False, force=True):
+ parent_directory_path, object_name = path.rsplit('/', 1)
+ parent_directory = self.get_node(parent_directory_path + '/')
+
+ object_size = self.get_node(path).size
+
+ parent_directory.remove(object_name, directory=directory, force=force)
+
+ self.available_size += object_size
+
+ def move(self, source, destination):
+ try:
+ self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+
+ try:
+ self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ if not self.get_node(destination).is_directory:
+ raise DestinationNotADirectoryError
+
+ destination_directory = self.get_node(destination)
+
+ source_parent_path, source_name = source.rsplit('/', 1)
+ source_parent_directory = self.get_node(source_parent_path + '/')
+
+ object_to_move = source_parent_directory[source_name]
+
+ try:
+ self.get_node(destination.rstrip('/') + '/' + source_name)
+ except NodeDoesNotExistError:
+ pass
+ else:
+ raise DestinationNodeExistsError
+
+ if object_to_move.is_directory:
+ destination_directory.add_directory(source_name, object_to_move)
+ source_parent_directory.remove(source_name, True, True)
+ else:
+ destination_directory.add_file(source_name, object_to_move)
+ source_parent_directory.remove(source_name)
+
+ def link(self, source, destination, symbolic=True):
+ if symbolic:
+ self.get_node(source)
+ parent_path, link_name = destination.rsplit('/', 1)
+ else:
+ source_object = self.get_node(source)
+ if source_object.is_directory:
+ raise DirectoryHardLinkError
+
+ def mount(self, file_system, path):
+ try:
+ mount_point = self.get_node(path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError
+
+ if not mount_point.is_directory:
+ raise MountPointNotADirectoryError
+
+ if not mount_point.nodes == []:
+ raise MountPointNotEmptyError
+
+ parent_directory_path, mount_point_name = path.rsplit('/', 1)
+ parent_directory = self.get_node(parent_directory_path + '/')
+ file_system_root = file_system.get_node('/')
+
+ parent_directory.add_directory(mount_point_name, file_system_root)
+
+ def unmount(self, path):
+ mount_point = self.get_node(path)
+
+ if not mount_point.is_directory:
+ raise NotAMountPointError
+
+ parent_path, mount_name = path.rsplit('/', 1)
+
+ mount_point_parent_directory = self.get_node(parent_path + '/')
+ mount_point_parent_directory.remove(mount_name, True, True)
+
+ mount_point_parent_directory.add_directory(mount_name, Directory())