Решение на In-memory файлова система от Калоян Витанов

Обратно към всички решения

Към профила на Калоян Витанов

Резултати

  • 9 точки от тестове
  • 0 бонус точки
  • 9 точки общо
  • 14 успешни тест(а)
  • 4 неуспешни тест(а)

Код

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)
file_system.available_size += 1
else:
file_system.available_size += node.size
containing_dir(file_system, path, node, True)
if type(node) is SymbolicLink:
file_system.available_size += 1
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 type(node) is SymbolicLink and node.deleted_source is True:
if node.symbolic_pointers != []:
for element in node.symbolic_pointers:
element.deleted_source = True
recursive_remove(self, path, node, directory, force)
else:
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)

Лог от изпълнението

........E....E.EE.
======================================================================
ERROR: test_mounting (test.TestFileSystem)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 65, in thread
    raise TimeoutError
TimeoutError

======================================================================
ERROR: test_remove_empty_directory (test.TestFileSystem)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 65, in thread
    raise TimeoutError
TimeoutError

======================================================================
ERROR: test_remove_nonempty_directory (test.TestFileSystem)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 65, in thread
    raise TimeoutError
TimeoutError

======================================================================
ERROR: test_symlink_to_missing_file (test.TestFileSystem)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 65, in thread
    raise TimeoutError
TimeoutError

----------------------------------------------------------------------
Ran 18 tests in 8.185s

FAILED (errors=4)

История (2 версии и 0 коментара)

Калоян обнови решението на 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)

Калоян обнови решението на 30.04.2015 02:27 (преди почти 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)
+ file_system.available_size += 1
else:
file_system.available_size += node.size
containing_dir(file_system, path, node, True)
+ if type(node) is SymbolicLink:
+ file_system.available_size += 1
+ 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 type(node) is SymbolicLink and node.deleted_source is True:
+ if node.symbolic_pointers != []:
+ for element in node.symbolic_pointers:
+ element.deleted_source = True
+ recursive_remove(self, path, node, directory, force)
+ else:
+ 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
+ if node.symbolic_pointers != []:
+ for element in node.symbolic_pointers:
+ element.deleted_source = True
- recursive_remove(self, path, node, directory, force)
+ 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)