Михаил обнови решението на 30.04.2015 16:21 (преди над 9 години)
+"""Rejoice ye men who have seen this, for it is the worst homework the world has ever seen"""
+
+
+class FileSystemError(Exception):
+
+ def __init__(self):
+ super()
+ self.message = 'Fool! You broke it!'
+
+
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class DestinationNodeExistsError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class LinkPathError():
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileSystemError):
+ pass
+
+
+class FileSystemMountError(FileSystemError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class NotAMountpointError(FileSystemMountError):
+ pass
+
+
+class Dir(dict):
+
+ def __getattribute__(self, attr):
+ if attr == 'files':
+ files = []
+ for i in self.values():
+ if not isinstance(i, str) and not i.is_directory:
+ files.append(i)
+ return files
+ elif attr == 'directories':
+ dirs = []
+ for i in self.values():
+ if not isinstance(i, str) and i.is_directory:
+ dirs.append(i)
+ return dirs
+ elif attr == 'nodes':
+ return list(self.values())
+ else:
+ return object.__getattribute__(self, attr)
+
+
+class File:
+
+ def __init__(self, text):
+ self.content = text
+ self.size = len(text) + 1
+
+ def append(self, text):
+ self.content += text
+ size = len(self.content) + 1
+
+ def truncate(self, text):
+ self.content = text
+ size = len(self.content) + 1
+
+
+def check_path(path):
+ if path == '/':
+ return ['']
+ if path == '':
+ raise NodeDoesNotExistError
+ path = path.split('/')
+ if path[0] != '':
+ raise NodeDoesNotExistError
+ return path
+
+
+class FileSystem:
+
+ def __init__(self, size):
+ self.size = size
+ self.paths = Dir([('', Dir())])
+ self.available_size = size - 1
+ self.link_targets = []
+
+ def get_node(self, path):
+ path = check_path(path)
+
+ current = self.paths
+ for i in path:
+ try:
+ if isinstance(current[i], str):
+ print(current[i])
+ current = self.get_node(current[i])
+ else:
+ current = current[i]
+ except KeyError:
+ raise NodeDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+ if isinstance(current, int):
+ return self.link_targets[current][0]
+ return current
+
+ def create(self, path, directory=False, content=''):
+ path = check_path(path)
+
+ new_size = self.available_size
+ if directory:
+ new_size -= 1
+ else:
+ new_size -= len(content) + 1
+ if new_size < 0:
+ raise NotEnoughSpaceError
+
+ current = self.paths
+ for i in path[:-1]:
+ try:
+ if isinstance(current[i], str):
+ current = self.get_node(current[i])
+ else:
+ current = current[i]
+ except KeyError:
+ raise DestinationNodeDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+
+ if path[-1] in current:
+ raise DestinationNodeExistsError
+ if directory:
+ current[path[-1]] = Dir()
+ current[path[-1]].is_directory = True
+ else:
+ current[path[-1]] = File(content)
+ current[path[-1]].is_directory = False
+ self.available_size = new_size
+
+ def remove(self, path, directory=False, force=True):
+ path = check_path(path)
+
+ current = self.paths
+ for i in path[:-1]:
+ try:
+ if isinstance(current[i], str):
+ current = self.get_node(current[i])
+ else:
+ current = current[i]
+ except KeyError:
+ raise NodeDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+
+ if path[-1] not in current:
+ raise NodeDoesNotExistError
+
+ if isinstance(current[path[-1]], Dir):
+ if not directory:
+ raise NonExplicitDirectoryDeletionError
+ if len(current[path[-1]]) != 0 and not force:
+ raise NonEmptyDirectoryDeletionError
+ self.available_size += 1
+
+ if isinstance(current[path[-1]], int):
+ self.available_size += 1
+ if self.link_targets[current[path[-1]]] < 2:
+ size = self.link_targets[current[path[-1]]].size
+ del self.link_targets[current[path[-1]]]
+ self.available_size += size
+ else:
+ a, c = self.link_targets[current[path[-1]]]
+ self.link_targets[current[path[-1]]] = (a, c - 1)
+
+ if isinstance(current[path[-1]], File):
+ self.available_size += current[path[-1]].size
+
+ del current[path[-1]]
+
+ def move(self, source, destination):
+ source = check_path(source)
+ destination = check_path(destination)
+
+ source_path = self.paths
+ for i in source[:-1]:
+ try:
+ if isinstance(source_path[i], str):
+ source_path = self.get_node(source_path[i])
+ else:
+ source_path = source_path[i]
+ except KeyError:
+ raise SourceNodeDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+ if source[-1] not in source_path:
+ raise SourceNodeDoesNotExistError
+
+ dest_path = self.paths
+ for i in destination:
+ try:
+ if isinstance(dest_path[i], str):
+ dest_path = self.get_node(dest_path[i])
+ else:
+ dest_path = dest_path[i]
+ except KeyError:
+ raise DestinationNodeDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+
+ if not isinstance(dest_path, Dir):
+ raise DestinationNotADirectoryError
+
+ if source[-1] in dest_path:
+ raise DestinationNodeExistsError
+
+ dest_path[destination[-1]] = source_path[source[-1]]
+ del source_path[source[-1]]
+
+ def link(self, source, destination, symbolic=True):
+ source_cpy = source
+ source = check_path(source)
+ destination = check_path(destination)
+
+ source_path = self.paths
+ for i in source[:-1]:
+ try:
+ if isinstance(source_path[i], str):
+ source_path = self.get_node(source_path[i])
+ else:
+ source_path = source_path[i]
+ except KeyError:
+ if symbolic:
+ raise NodeDoesNotExistError
+ raise SourceNodeDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+
+ if source[-1] not in source_path:
+ if symbolic:
+ raise NodeDoesNotExistError
+ else:
+ raise SourceNodeDoesNotExistError
+
+ if isinstance(source_path[source[-1]], Dir) and not symbolic:
+ raise DirectoryHardLinkError
+
+ dest_path = self.paths
+ for i in destination[:-1]:
+ try:
+ if isinstance(dest_path[i], str):
+ dest_path = self.get_node(dest_path[i])
+ else:
+ dest_path = dest_path[i]
+ except KeyError:
+ raise DestinationNodeDoesNotExistError # !!!!!!!!
+ except TypeError:
+ raise NotADirectoryError
+
+ if destination[-1] in dest_path:
+ raise DestinationNodeExistsError
+
+ if symbolic:
+ dest_path[destination[-1]] = source_cpy
+ else:
+ address = len(self.link_targets)
+ self.link_targets.append((source_path[source[-1]], 2))
+ dest_path[destination[-1]] = address
+ source_path[source[-1]] = address
+
+ self.available_size -= 1
+
+ def mount(self, file_system, path):
+ path = check_path(path)
+
+ current = self.paths
+ for i in path[:-1]:
+ try:
+ if isinstance(current[i], str):
+ current = self.get_node(current[i])
+ else:
+ current = current[i]
+ except KeyError:
+ raise MountPointDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+ if path[-1] not in current:
+ raise MountPointDoesNotExistError
+
+ if not isinstance(current[path[-1]], Dir):
+ raise MountPointNotADirectoryError
+ if len(current[path[-1]]) > 0:
+ raise MountPointNotEmptyError
+
+ current[path[-1]] = file_system.paths['']
+ current[path[-1]].mount_point = True
+
+ def unmount(self, path):
+ path = check_path(path)
+
+ current = self.paths
+ for i in path[:-1]:
+ try:
+ if isinstance(current[i], str):
+ current = self.get_node(current[i])
+ else:
+ current = current[i]
+ except KeyError:
+ raise MountPointDoesNotExistError
+ except TypeError:
+ raise NotADirectoryError
+ if path[-1] not in current:
+ raise MountPointDoesNotExistError
+
+ if not hasattr(current[path[-1]], 'mount_point'):
+ raise NotAMountpointError
+
+ current[path[-1]] = Dir()