Калоян обнови решението на 30.04.2015 00:38 (преди над 9 години)
+class FileSystemError(BaseException):
+ pass
+
+
+# 1.
+class FileSystemMountError (FileSystemError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class DestinationNodeExistsError(FileSystemError):
+ pass
+
+# 1.
+
+
+# 2.
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+# 2.
+
+# 3. other errors
+class NotADirectoryInTheSystemError(FileSystemError):
+ pass
+
+
+class NotAProperWayToCreateAFileSystemObjectError(FileSystemError):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class NotAProperWayToDeleteFileSystemError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class EpicFailError(FileSystemError):
+ pass
+
+
+class NotEnoughMemoryInMountedFileSystemError(FileSystemError):
+ pass
+
+
+class NotEnoughMemoryInPrimaryFileSystemError(FileSystemError):
+ pass
+
+
+class NotAMountpointError(FileSystemError):
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ pass
+
+
+class NotEnoughSpaceInTheFileSystemError(FileSystemError):
+ pass
+
+
+class LinkPathError(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileSystemError):
+ pass
+
+
+# 3.
+
+class Directory():
+ def __init__(self, name):
+ self.name = name
+ self.directories = []
+ self.files = []
+ self.nodes = []
+ self.is_directory = True
+ self.symbolic_pointers = []
+ self.size = 1
+
+
+class File():
+ def __init__(self, name, content):
+ self.name = name
+ self.content = str(content)
+ self.size = len(self.content) + 1
+ self.is_directory = False
+ self.symbolic_pointers = []
+ self.hard_pointers = [self]
+ self.entity = self
+ self.path = None
+ self.file_system = None
+
+ def append(self, text):
+ self.file_system.available_size += self.size
+ length = len(self.content + str(text))
+ if self.file_system.available_size - length < 0:
+ raise NotEnoughSpaceInTheFileSystemError()
+
+ path_list = []
+ for element in self.hard_pointers:
+ path_list.append(element.path)
+
+ for element in self.hard_pointers:
+ for element2 in path_list:
+ indicator = 0
+ if element.path in element2:
+ indicator = 1
+ if indicator == 1:
+ element.content += str(text)
+ element.size = len(self.content) + 1
+ if indicator == 0:
+
+ the_path = self.path
+ system = self.file_system
+ indicator2 = 1
+ while indicator2 == 1:
+ for element in system.mounted_paths.keys():
+ if element in path:
+ system = system.mounted_paths[element]
+ the_path = the_path.split(element)[-1]
+ break
+ else:
+ indicator2 = 0
+
+ containing_dir(system, the_path, self)
+ element.content += str(text)
+ element.size = len(self.content) + 1
+ containing_dir(system, the_path, self, substraction=True)
+ self.file_system.available_size -= self.size
+
+ def truncate(self, text):
+ self.file_system.available_size += self.size
+ length = len(str(text))
+ if self.file_system.available_size - length < 0:
+ raise NotEnoughSpaceInTheFileSystemError()
+
+ path_list = []
+ for element in self.hard_pointers:
+ path_list.append(element.path)
+
+ for element in self.hard_pointers:
+ indicator = 0
+ for element2 in path_list:
+ if element.path in element2:
+ indicator = 1
+ if indicator == 1:
+ element.content = str(text)
+ element.size = len(self.content) + 1
+ if indicator == 0:
+
+ the_path = self.path
+ system = self.file_system
+ indicator2 = 1
+ while indicator2 == 1:
+ for element in system.mounted_paths.keys():
+ if element in path:
+ system = system.mounted_paths[element]
+ the_path = the_path.split(element)[-1]
+ break
+ else:
+ indicator2 = 0
+
+ containing_dir(system, the_path, self)
+ element.content = str(text)
+ element.size = len(self.content) + 1
+ containing_dir(system, the_path, self, substraction=True)
+ self.file_system.available_size -= self.size
+
+
+class SymbolicLink():
+
+ def __init__(self, name, link_path):
+ self.link_path = link_path
+ self.name = name
+ self.size = 1
+ self.deleted_source = False
+ self.symbolic_pointers = []
+
+ def __getattr__(self, name):
+ if self.deleted_source is True:
+ raise LinkPathError()
+ else:
+ if name == 'is_directory':
+ return self.link_path.is_directory
+
+ if self.link_path.is_directory is False:
+ if name == 'content':
+ return self.link_path.content
+ else:
+ raise LinkPathError()
+
+ if self.link_path.is_directory is True:
+ if name == 'nodes':
+ return self.link_path.nodes
+ elif name == 'directories':
+ return self.link_path.directories
+ elif name == 'files':
+ return self.link_path.files
+ else:
+ raise LinkPathError()
+
+
+# 1. gives the directory within which the Action occurs
+def containing_dir(file_system, path, node=0, substraction=False):
+ path_split = path.split('/')
+ dir_path_split = path_split[0:-1]
+ if dir_path_split == ['']:
+ dir_path = '/'
+ else:
+ dir_path = '/'.join(dir_path_split)
+
+ k = 0
+ string = ''
+
+ the_directory = file_system.root
+ if node is not 0:
+ if substraction is False:
+ the_directory.size += node.size
+ else:
+ the_directory.size -= node.size
+
+ while string != dir_path and dir_path != '/':
+ indicator = 0
+ k += 1
+ string += '/' + dir_path_split[k]
+
+ for element in the_directory.directories:
+ if string.split('/')[-1] == element.name:
+ the_directory = element
+ if node is not 0:
+ if substraction is False:
+ the_directory.size += node.size
+ else:
+ the_directory.size -= node.size
+
+ indicator = 1
+ break
+ if indicator == 0:
+ raise NodeDoesNotExistError()
+
+ return the_directory
+
+
+# 2. gives the containing directory name
+def containing_dir_name(path):
+ if '/'.join(path.split('/')[0:-1]) == '':
+ dir_path = '/'
+ else:
+ dir_path = '/'.join(path.split('/')[0:-1])
+ return dir_path
+
+
+# 3. gives the name after the last '/'
+def item_name(path):
+ return path.split('/')[-1]
+
+
+# 4. gives the names of all nodes in a given directory
+def names_in_given_dir(FileSystem, path):
+ if path == '/':
+ given_directory = FileSystem.root
+ else:
+ given_directory = containing_dir(FileSystem, path + '/')
+ if given_directory.is_directory is False:
+ raise NotADirectoryInTheSystemError()
+ name_list = []
+ for element in given_directory.nodes:
+ name_list.append(element.name)
+ return name_list
+
+# 5. used in file_system.create, handles mounts
+
+
+def recursive_create(file_system, path, directory, node):
+
+ try:
+ containing_dir(file_system, path)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError()
+
+ for element in file_system.mounted_paths.keys():
+ if element in path:
+ new_path = path.split(element)[-1]
+ return recursive_create(file_system.mounted_paths[element],
+ new_path, directory, node)
+ else:
+ cd = containing_dir(file_system, path, node)
+ node.file_system = file_system
+ if directory is True:
+ cd.directories.append(node)
+ cd.nodes.append(node)
+ if file_system.available_size - node.size < 0:
+ raise NotEnoughSpaceError()
+ file_system.available_size -= node.size
+ else:
+ cd.files.append(node)
+ cd.nodes.append(node)
+ if type(node) is File:
+ node.path = path
+ node.file_system = file_system
+ if len(node.hard_pointers) > 1:
+ if file_system.available_size - 1 < 0:
+ raise NotEnoughSpaceError()
+ file_system.available_size -= 1
+ pass
+ else:
+ if file_system.available_size - node.size < 0:
+ raise NotEnoughSpaceError()
+ file_system.available_size -= node.size
+ else:
+ file_system.available_size -= node.size
+
+
+# 6. file_system.create, handles mounts
+def recursive_remove(file_system, path, node, directory, force):
+
+ for element in file_system.mounted_paths.keys():
+ if element in path:
+ new_path = path.split(element)[-1]
+ return recursive_remove(file_system.mounted_paths[element],
+ new_path, node, directory, force)
+ else:
+ cd = containing_dir(file_system, path)
+
+ for element in node.symbolic_pointers:
+ element.deleted_source = True
+
+ if directory is True:
+ cd.directories.remove(node)
+ cd.nodes.remove(node)
+ file_system.available_size += node.size
+ containing_dir(file_system, path, node, True)
+
+ else:
+ if type(node) is File:
+ if len(node.hard_pointers) > 1:
+ a_dict = {}
+ k = 1
+ for element in node.hard_pointers:
+ a_dict[k] = element
+ k += 1
+ for element in a_dict.values():
+ element.hard_pointers.remove(node)
+ node.hard_pointers.append(element)
+
+ else:
+ file_system.available_size += node.size
+ containing_dir(file_system, path, node, True)
+
+ cd.files.remove(node)
+ cd.nodes.remove(node)
+
+# !!
+
+
+class FileSystem():
+
+ def __init__(self, size):
+ self.size = size
+ self.available_size = size - 1
+ self.root = Directory('/')
+ self.mounted_paths = {}
+
+ def get_node(self, path):
+ if path == '/':
+ return self.root
+ cd = containing_dir(self, path)
+ item = item_name(path)
+ for element in cd.nodes:
+ if element.name == item:
+ return element
+ else:
+ raise NodeDoesNotExistError()
+
+ def create(self, path, directory=False, content=''):
+ if path == '':
+ raise NotAProperWayToCreateAFileSystemObjectError() from exc
+
+ try:
+ containing_dir(self, path)
+ except NodeDoesNotExistError as exc:
+ raise DestinationNodeDoesNotExistError()
+
+ if item_name(path) in names_in_given_dir(self,
+ containing_dir_name(path)):
+ raise DestinationNodeExistsError()
+
+ if directory is True:
+ new_directory = Directory(item_name(path))
+ node = new_directory
+
+ else:
+ new_file = File(item_name(path), content)
+ node = new_file
+
+ recursive_create(self, path, directory, node)
+
+ def remove(self, path, directory=False, force=True):
+ if path == '/':
+ raise NotAProperWayToDeleteFileSystemError()
+
+ node = self.get_node(path)
+
+ if node.is_directory is True and directory is False:
+ raise NonExplicitDirectoryDeletionError()
+ if node.is_directory is True and node.nodes != []:
+ if directory is True and force is False:
+ raise NonEmptyDirectoryDeletionError()
+
+ if node.symbolic_pointers != []:
+ for element in node.symbolic_pointers:
+ element.deleted_source = True
+
+ recursive_remove(self, path, node, directory, force)
+
+ def move(self, source, destination):
+ if source in destination:
+ raise EpicFailError()
+
+ try:
+ node = self.get_node(source)
+ except NodeDoesNotExistError as exc:
+ raise SourceNodeDoesNotExistError() from exc
+
+ try:
+ the_other_directory = self.get_node(destination)
+ except NodeDoesNotExistError as exc:
+ raise DestinationNodeDoesNotExistError() from exc
+
+ if the_other_directory.is_directory is False:
+ raise DestinationNotADirectoryError()
+
+ if node.name in names_in_given_dir(self, destination):
+ raise DestinationNodeExistsError()
+
+ node = self.get_node(source)
+ if node.is_directory is True:
+ directory = True
+ force = True
+ else:
+ directory = False
+ force = False
+
+ path = destination + '/' + item_name(source)
+
+ recursive_remove(self, source, node, directory, force)
+ recursive_create(self, path, directory, node)
+
+ def link(self, source, destination, symbolic=True):
+
+ try:
+ node = self.get_node(source)
+ except NodeDoesNotExistError:
+ if symbolic is True:
+ raise NodeDoesNotExistError()
+ else:
+ raise SourceNodeDoesNotExistError()
+
+ if symbolic is False:
+ if node is None:
+ raise SourceNodeDoesNotExistError()
+ if node.is_directory is True:
+ raise DirectoryHardLinkError()
+
+ if symbolic is False:
+ hard_link = File(item_name(destination), node.content)
+
+ a_dict = {}
+ k = 1
+ for element in node.hard_pointers:
+ a_dict[k] = element
+ k += 1
+
+ for element in a_dict.values():
+ element.hard_pointers.append(hard_link)
+ hard_link.hard_pointers.append(element)
+
+ recursive_create(self, destination, node.is_directory, hard_link)
+
+ if symbolic is True:
+ symbolic_link = SymbolicLink(item_name(destination), node)
+ node.symbolic_pointers.append(symbolic_link)
+
+ recursive_create(self, destination,
+ node.is_directory, symbolic_link)
+
+ def mount(self, file_system, path):
+ try:
+ node = self.get_node(path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError()
+
+ cd = containing_dir(self, path)
+
+ if node.is_directory is False:
+ raise MountPointNotADirectoryError()
+ if node.nodes != []:
+ raise MountPointNotEmptyError()
+
+ cd.directories.remove(node)
+ cd.nodes.remove(node)
+
+ the_path = path
+ system = self
+
+ indicator = 1
+ while indicator == 1:
+ for element in system.mounted_paths.keys():
+ if element in the_path:
+ system = system.mounted_paths[element]
+ the_path = the_path.split(element)[-1]
+ break
+ else:
+ indicator = 0
+
+ system.mounted_paths[the_path] = file_system
+
+ node = file_system.root
+ node.name = item_name(path)
+ node.is_file_system = True
+
+ cd.directories.append(node)
+ cd.nodes.append(node)
+
+ def unmount(self, path):
+ node = self.get_node(path)
+
+ try:
+ node.is_file_system is False
+ except AttributeError:
+ raise NotAMountpointError()
+
+ the_path = path
+ system = self
+
+ indicator = 1
+ while indicator == 1:
+ for element in system.mounted_paths.keys():
+ if element in the_path:
+ if path.split(element) == ['', '']:
+ indicator = 0
+ break
+ system = system.mounted_paths[element]
+ the_path = the_path.split(element)[-1]
+ break
+ else:
+ indicator = 0
+
+ del system.mounted_paths[the_path]
+
+ system.root.name = '/'
+ cd = containing_dir(system, the_path)
+
+ cd.directories.remove(node)
+ cd.nodes.remove(node)
+ del node.is_file_system
+
+ node = Directory(item_name(path))
+ cd.directories.append(node)
+ cd.nodes.append(node)