Решение на In-memory файлова система от Павел Димитров

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

Към профила на Павел Димитров

Резултати

  • 8 точки от тестове
  • 0 бонус точки
  • 8 точки общо
  • 12 успешни тест(а)
  • 6 неуспешни тест(а)

Код

class FileSystem():
class SoftLinkFile():
def __init__(self, name, link_path):
self.name = name
self.link_path = link_path
self.size = 1
@property
def content(self):
try:
self.link_path.content
except AttributeError:
raise LinkPathError
return self.link_path.content
@property
def directories(self):
try:
self.link_path.directories
except AttributeError:
raise LinkPathError
return self.link_path.directories
@property
def files(self):
try:
self.link_path.files
except AttributeError:
raise LinkPathError
return self.link_path.files
@property
def nodes(self):
try:
self.link_path.nodes
except AttributeError:
raise LinkPathError
return self.link_path.nodes
class SimpleFile():
def __init__(self, name, content):
self.name = name
self.is_directory = False
self.content = content
self.size = len(content) + 1
def append(self, text):
self.content += text
self._size_update_file()
def truncate(self, text):
self.content = text
self._size_update_file()
def _size_update_file(self):
self.size = len(self.content) + 1
class SimpleDirectory():
def __init__(self, name):
self.size = 1
self.name = name
self.is_directory = True
self.directories = list()
self.files = list()
self.nodes = list()
def __init__(self, size):
self.size = size
self.available_size = size - 1
self.root = self.SimpleDirectory("/")
self.mounted_file_systems = {}
def _size_update(self, path, bits_added):
self.available_size -= bits_added
if path == "/":
self.get_node("/").size += bits_added
else:
self.get_node("/").size += bits_added
path = path.split("/")
del path[0]
current_node_path = ""
for node_name in path:
current_node_path += "/" + node_name
self.get_node(current_node_path).size += bits_added
def get_node(self, path):
if path in self.mounted_file_systems.keys():
return self.mounted_file_systems[path]
if path == "/":
return self.root
path = path.split("/")
del path[0]
current_dir = self.root
for index, current_node in enumerate(iter(path)):
sub_dir_names = [sub_dir_name.name for
sub_dir_name in current_dir.directories]
sub_node_names = [sub_node_name.name for
sub_node_name in current_dir.nodes]
if current_node in sub_dir_names and index != (len(path) - 1):
index_next_dir = sub_dir_names.index(current_node)
current_dir = current_dir.directories[index_next_dir]
continue
elif current_node in sub_node_names and index == (len(path) - 1):
for node in current_dir.nodes:
if node.name == current_node:
return node
elif current_node not in sub_node_names:
raise NodeDoesNotExistError
def create(self, path, directory=False, content=""):
is_directory = directory
bits_to_be_added = 1 + len(content)
path = path.split("/")
new_node_name = path[-1]
del path[-1]
del path[0]
path = "/" + "/".join(path)
try:
self.get_node(path)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if self.available_size < bits_to_be_added:
raise NotEnoughSpaceError
current_node = self.get_node(path)
sub_node_names = [sub_node_name.name for
sub_node_name in current_node.nodes]
if new_node_name in sub_node_names:
raise DestinationNodeExistsError
if is_directory:
new_directory = self.SimpleDirectory(new_node_name)
current_node.nodes.append(new_directory)
current_node.directories.append(new_directory)
else:
new_file = self.SimpleFile(new_node_name, content)
current_node.nodes.append(new_file)
current_node.files.append(new_file)
self._size_update(path, bits_to_be_added)
def remove(self, path, directory=False, force=True):
original_node_is_directory = self.get_node(path).is_directory
node_to_be_removed = self.get_node(path)
is_directory = directory
del_with_force = force
if node_to_be_removed.is_directory and not is_directory:
raise NonExplicitDirectoryDeletionError
if is_directory and node_to_be_removed.nodes != [] \
and not del_with_force:
raise NonEmptyDirectoryDeletionError
parent_path = self._get_parent_path(path)[0]
bits_to_be_removed = self.get_node(path).size
parent_of_node_to_be_removed = self.get_node(parent_path)
if original_node_is_directory:
parent_of_node_to_be_removed.directories.remove(node_to_be_removed)
parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
else:
parent_of_node_to_be_removed.files.remove(node_to_be_removed)
parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
self._size_update(parent_path, -bits_to_be_removed)
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
source_name = self.get_node(source).name
destination_node = self.get_node(destination)
for node in destination_node.nodes:
if node.name == source_name:
raise DestinationNodeExistsError
node_to_be_moved = self.get_node(source)
if node_to_be_moved.is_directory:
self.remove(source, True, True)
destination_node.directories.append(node_to_be_moved)
destination_node.nodes.append(node_to_be_moved)
else:
self.remove(source, False)
destination_node.files.append(node_to_be_moved)
destination_node.nodes.append(node_to_be_moved)
self._size_update(destination, node_to_be_moved.size)
def link(self, source, destination, symbolic=True):
destination_parent_path = self._get_parent_path(destination)[0]
link_name = self._get_parent_path(destination)[1]
try:
self.get_node(source)
except NodeDoesNotExistError:
if symbolic:
raise NodeDoesNotExistError
else:
raise SourceNodeDoesNotExistError
if self.get_node(source).is_directory and not symbolic:
raise DirectoryHardLinkError
if symbolic:
new_soft_link_file = self.SoftLinkFile(link_name,
self.get_node(source))
self.get_node(destination_parent_path).\
files.append(new_soft_link_file)
self.get_node(destination_parent_path).\
nodes.append(new_soft_link_file)
self.available_size -= 1
else:
hard_link_file = self.SimpleFile(link_name, "content")
hard_link_file.content = self.get_node(source).content
self.get_node(destination_parent_path).\
files.append(hard_link_file)
self.get_node(destination_parent_path).\
nodes.append(hard_link_file)
self.available_size -= 1
def mount(self, file_system, path):
parent_path = self._get_parent_path(path)[0]
# mount_name = self._get_parent_path(path)[1]
try:
self.get_node(parent_path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if not self.get_node(parent_path).is_directory:
raise MountPointNotADirectoryError
if self.get_node(parent_path).nodes != []:
raise MountPointNotEmptyError
self.mounted_file_systems[path] = file_system.root
self.available_size -= 1
def unmount(self, path):
if path not in self.mounted_file_systems.keys():
raise NotAMountpointError
else:
del self.mounted_file_systems[path]
self.available_size += 1
def _get_parent_path(self, path):
parent_path = path.split("/")
if len(parent_path) > 2:
del parent_path[0]
last_node_name = parent_path[-1]
del parent_path[-1]
parent_path = "/" + "/".join(parent_path)
else:
last_node_name = parent_path[-1]
parent_path = "/"
return parent_path, last_node_name
class FileSystemError(Exception):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class SourceNodeDoesNotExistError (NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class DirectoryHardLinkError(FileExistsError):
pass
class LinkPathError(FileSystemError):
pass
class NotAMountpointError(FileSystemMountError):
pass

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

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

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

======================================================================
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 12.181s

FAILED (errors=6)

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

Павел обнови решението на 26.04.2015 12:41 (преди почти 9 години)

+class FileSystem():
+
+ class SimpleFile():
+
+ def __init__(self, name, content):
+ self.name = name
+ self.is_directory = False
+ self.content = content
+ self.size = len(content) + 1
+
+ def append(self, text):
+ self.content += text
+ self._size_update_file()
+
+ def truncate(self, text):
+ self.content = text
+ self._size_update_file()
+
+ def _size_update_file(self):
+ self.size = len(self.content) + 1
+
+ class SimpleDirectory():
+
+ def __init__(self, name):
+ self.size = 1
+ self.name = name
+ self.is_directory = True
+ self.directories = list()
+ self.files = list()
+ self.nodes = list()
+
+ def __init__(self, size):
+ self.size = size
+ self.available_size = size - 1
+ self.root = self.SimpleDirectory("/")
+
+ def _size_update(self, path, bits_added):
+
+ self.available_size -= bits_added
+ if path == "/":
+ self.get_node("/").size += bits_added
+ else:
+ self.get_node("/").size += bits_added
+ path = path.split("/")
+ del path[0]
+ current_node_path = ""
+ for node_name in path:
+ current_node_path += "/" + node_name
+ self.get_node(current_node_path).size += bits_added
+
+ def get_node(self, path):
+ if path == "/":
+ return self.root
+ path = path.split("/")
+ del path[0]
+ current_dir = self.root
+ for index, current_node in enumerate(iter(path)):
+
+ sub_dir_names = [sub_dir_name.name for
+ sub_dir_name in current_dir.directories]
+
+ sub_node_names = [sub_node_name.name for
+ sub_node_name in current_dir.nodes]
+
+ if current_node in sub_dir_names and index != (len(path) - 1):
+ index_next_dir = sub_dir_names.index(current_node)
+ current_dir = current_dir.directories[index_next_dir]
+ continue
+
+ elif current_node in sub_node_names and index == (len(path) - 1):
+ for node in current_dir.nodes:
+ if node.name == current_node:
+ return node
+
+ elif current_node not in sub_node_names:
+ raise NodeDoesNotExistError
+
+ def create(self, path, directory=False, content=""):
+
+ is_directory = directory
+ bits_to_be_added = 1 + len(content)
+
+ path = path.split("/")
+ new_node_name = path[-1]
+ del path[-1]
+ del path[0]
+
+ path = "/" + "/".join(path)
+
+ try:
+ self.get_node(path)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ if self.available_size < bits_to_be_added:
+ raise NotEnoughSpaceError
+
+ current_node = self.get_node(path)
+
+ sub_node_names = [sub_node_name.name for
+ sub_node_name in current_node.nodes]
+
+ if new_node_name in sub_node_names:
+ raise DestinationNodeExistsError
+
+ if is_directory:
+ new_directory = self.SimpleDirectory(new_node_name)
+ current_node.nodes.append(new_directory)
+ current_node.directories.append(new_directory)
+ else:
+
+ new_file = self.SimpleFile(new_node_name, content)
+ current_node.nodes.append(new_file)
+ current_node.files.append(new_file)
+
+ self._size_update(path, bits_to_be_added)
+
+ def remove(self, path, directory=False, force=True):
+ original_node_is_directory = self.get_node(path).is_directory
+ node_to_be_removed = self.get_node(path)
+ is_directory = directory
+ del_with_force = force
+ if node_to_be_removed.is_directory and not is_directory:
+ raise NonExplicitDirectoryDeletionError
+
+ if is_directory and node_to_be_removed.nodes != [] \
+ and not del_with_force:
+ raise NonEmptyDirectoryDeletionError
+
+ parent_path = path.split("/")
+
+ if len(parent_path) > 2:
+ del parent_path[0]
+ del parent_path[-1]
+ parent_path = "/" + "/".join(parent_path)
+ else:
+ parent_path = "/"
+
+ bits_to_be_removed = self.get_node(path).size
+ parent_of_node_to_be_removed = self.get_node(parent_path)
+
+ # if is_directory:
+ if original_node_is_directory:
+ parent_of_node_to_be_removed.directories.remove(node_to_be_removed)
+ parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
+ else:
+ parent_of_node_to_be_removed.files.remove(node_to_be_removed)
+ parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
+
+ self._size_update(parent_path, -bits_to_be_removed)
+
+ 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
+
+ source_name = self.get_node(source).name
+ destination_node = self.get_node(destination)
+
+ for node in destination_node.nodes:
+ if node.name == source_name:
+ raise DestinationNodeExistsError
+
+ node_to_be_moved = self.get_node(source)
+
+ if node_to_be_moved.is_directory:
+ self.remove(source, True, True)
+ destination_node.directories.append(node_to_be_moved)
+ destination_node.nodes.append(node_to_be_moved)
+ else:
+ self.remove(source, False)
+ destination_node.files.append(node_to_be_moved)
+ destination_node.nodes.append(node_to_be_moved)
+
+ self._size_update(destination, node_to_be_moved.size)
+
+ def link(self, source, destination, symbolic=True):
+ pass
+
+ def mount(self, file_system, path):
+ pass
+
+ def unmount(self, path):
+ pass
+
+
+class FileSystemError(Exception):
+ pass
+
+
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class FileSystemMountError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError (NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class DestinationNodeExistsError(FileSystemError):
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ pass

Павел обнови решението на 28.04.2015 13:57 (преди почти 9 години)

+
class FileSystem():
+ class SoftLinkFile():
+
+ def __init__(self, name, link_path):
+ self.name = name
+ self.link_path = link_path
+
+ @property
+ def content(self):
+ try:
+ self.link_path.content
+ except AttributeError:
+ raise LinkPathError
+
+ return self.link_path.content
+
+ @property
+ def directories(self):
+ try:
+ self.link_path.directories
+ except AttributeError:
+ raise LinkPathError
+
+ return self.link_path.directories
+
+ @property
+ def files(self):
+ try:
+ self.link_path.files
+ except AttributeError:
+ raise LinkPathError
+
+ return self.link_path.files
+
+ @property
+ def nodes(self):
+ try:
+ self.link_path.nodes
+ except AttributeError:
+ raise LinkPathError
+
+ return self.link_path.nodes
+
class SimpleFile():
def __init__(self, name, content):
self.name = name
self.is_directory = False
self.content = content
self.size = len(content) + 1
def append(self, text):
self.content += text
self._size_update_file()
def truncate(self, text):
self.content = text
self._size_update_file()
def _size_update_file(self):
self.size = len(self.content) + 1
class SimpleDirectory():
def __init__(self, name):
self.size = 1
self.name = name
self.is_directory = True
self.directories = list()
self.files = list()
self.nodes = list()
def __init__(self, size):
self.size = size
self.available_size = size - 1
self.root = self.SimpleDirectory("/")
+ self.mounted_file_systems = {}
def _size_update(self, path, bits_added):
self.available_size -= bits_added
if path == "/":
self.get_node("/").size += bits_added
else:
self.get_node("/").size += bits_added
path = path.split("/")
del path[0]
current_node_path = ""
for node_name in path:
current_node_path += "/" + node_name
self.get_node(current_node_path).size += bits_added
def get_node(self, path):
+
+ if path in self.mounted_file_systems.keys():
+ return self.mounted_file_systems[path]
+
if path == "/":
return self.root
path = path.split("/")
del path[0]
current_dir = self.root
for index, current_node in enumerate(iter(path)):
sub_dir_names = [sub_dir_name.name for
sub_dir_name in current_dir.directories]
sub_node_names = [sub_node_name.name for
sub_node_name in current_dir.nodes]
if current_node in sub_dir_names and index != (len(path) - 1):
index_next_dir = sub_dir_names.index(current_node)
current_dir = current_dir.directories[index_next_dir]
continue
elif current_node in sub_node_names and index == (len(path) - 1):
for node in current_dir.nodes:
if node.name == current_node:
return node
elif current_node not in sub_node_names:
raise NodeDoesNotExistError
def create(self, path, directory=False, content=""):
is_directory = directory
bits_to_be_added = 1 + len(content)
path = path.split("/")
new_node_name = path[-1]
del path[-1]
del path[0]
path = "/" + "/".join(path)
try:
self.get_node(path)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if self.available_size < bits_to_be_added:
raise NotEnoughSpaceError
current_node = self.get_node(path)
sub_node_names = [sub_node_name.name for
sub_node_name in current_node.nodes]
if new_node_name in sub_node_names:
raise DestinationNodeExistsError
if is_directory:
new_directory = self.SimpleDirectory(new_node_name)
current_node.nodes.append(new_directory)
current_node.directories.append(new_directory)
else:
new_file = self.SimpleFile(new_node_name, content)
current_node.nodes.append(new_file)
current_node.files.append(new_file)
self._size_update(path, bits_to_be_added)
def remove(self, path, directory=False, force=True):
original_node_is_directory = self.get_node(path).is_directory
node_to_be_removed = self.get_node(path)
is_directory = directory
del_with_force = force
if node_to_be_removed.is_directory and not is_directory:
raise NonExplicitDirectoryDeletionError
if is_directory and node_to_be_removed.nodes != [] \
and not del_with_force:
raise NonEmptyDirectoryDeletionError
- parent_path = path.split("/")
+ parent_path = self._get_parent_path(path)[0]
- if len(parent_path) > 2:
- del parent_path[0]
- del parent_path[-1]
- parent_path = "/" + "/".join(parent_path)
- else:
- parent_path = "/"
-
bits_to_be_removed = self.get_node(path).size
parent_of_node_to_be_removed = self.get_node(parent_path)
- # if is_directory:
if original_node_is_directory:
parent_of_node_to_be_removed.directories.remove(node_to_be_removed)
parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
else:
parent_of_node_to_be_removed.files.remove(node_to_be_removed)
parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
self._size_update(parent_path, -bits_to_be_removed)
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
source_name = self.get_node(source).name
destination_node = self.get_node(destination)
for node in destination_node.nodes:
if node.name == source_name:
raise DestinationNodeExistsError
node_to_be_moved = self.get_node(source)
if node_to_be_moved.is_directory:
self.remove(source, True, True)
destination_node.directories.append(node_to_be_moved)
destination_node.nodes.append(node_to_be_moved)
else:
self.remove(source, False)
destination_node.files.append(node_to_be_moved)
destination_node.nodes.append(node_to_be_moved)
self._size_update(destination, node_to_be_moved.size)
def link(self, source, destination, symbolic=True):
- pass
+ destination_parent_path = self._get_parent_path(destination)[0]
+ link_name = self._get_parent_path(destination)[1]
+
+ try:
+ self.get_node(source)
+ except NodeDoesNotExistError:
+ if symbolic:
+ raise NodeDoesNotExistError
+ else:
+ raise SourceNodeDoesNotExistError
+
+ if self.get_node(source).is_directory and not symbolic:
+ raise DirectoryHardLinkError
+
+ if symbolic:
+ new_soft_link_file = self.SoftLinkFile(link_name,
+ self.get_node(source))
+ self.get_node(destination_parent_path).\
+ files.append(new_soft_link_file)
+ self.get_node(destination_parent_path).\
+ nodes.append(new_soft_link_file)
+ else:
+ hard_link_file = self.SimpleFile(link_name, "content")
+ hard_link_file.content = self.get_node(source).content
+
+ self.get_node(destination_parent_path).\
+ files.append(hard_link_file)
+ self.get_node(destination_parent_path).\
+ nodes.append(hard_link_file)
+
def mount(self, file_system, path):
- pass
+ parent_path = self._get_parent_path(path)[0]
+ # mount_name = self._get_parent_path(path)[1]
+
+ try:
+ self.get_node(parent_path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError
+
+ if not self.get_node(parent_path).is_directory:
+ raise MountPointNotADirectoryError
+
+ if self.get_node(parent_path).nodes != []:
+ raise MountPointNotEmptyError
+
+ self.mounted_file_systems[path] = file_system.root
+
def unmount(self, path):
- pass
+ if path not in self.mounted_file_systems.keys():
+ raise NotAMountpointError
+ else:
+ del self.mounted_file_systems[path]
+ def _get_parent_path(self, path):
+ parent_path = path.split("/")
+
+ if len(parent_path) > 2:
+ del parent_path[0]
+ last_node_name = parent_path[-1]
+ del parent_path[-1]
+ parent_path = "/" + "/".join(parent_path)
+ else:
+ last_node_name = parent_path[-1]
+ parent_path = "/"
+
+ return parent_path, last_node_name
+
+
class FileSystemError(Exception):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class SourceNodeDoesNotExistError (NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileExistsError):
+ pass
+
+
+class LinkPathError(FileSystemError):
+ pass
+
+
+class NotAMountpointError(FileSystemMountError):
pass

Павел обнови решението на 30.04.2015 09:27 (преди почти 9 години)

-
class FileSystem():
class SoftLinkFile():
def __init__(self, name, link_path):
self.name = name
self.link_path = link_path
+ self.size = 1
@property
def content(self):
try:
self.link_path.content
except AttributeError:
raise LinkPathError
return self.link_path.content
@property
def directories(self):
try:
self.link_path.directories
except AttributeError:
raise LinkPathError
return self.link_path.directories
@property
def files(self):
try:
self.link_path.files
except AttributeError:
raise LinkPathError
return self.link_path.files
@property
def nodes(self):
try:
self.link_path.nodes
except AttributeError:
raise LinkPathError
return self.link_path.nodes
class SimpleFile():
def __init__(self, name, content):
self.name = name
self.is_directory = False
self.content = content
self.size = len(content) + 1
def append(self, text):
self.content += text
self._size_update_file()
def truncate(self, text):
self.content = text
self._size_update_file()
def _size_update_file(self):
self.size = len(self.content) + 1
class SimpleDirectory():
def __init__(self, name):
self.size = 1
self.name = name
self.is_directory = True
self.directories = list()
self.files = list()
self.nodes = list()
def __init__(self, size):
self.size = size
self.available_size = size - 1
self.root = self.SimpleDirectory("/")
self.mounted_file_systems = {}
def _size_update(self, path, bits_added):
self.available_size -= bits_added
if path == "/":
self.get_node("/").size += bits_added
else:
self.get_node("/").size += bits_added
path = path.split("/")
del path[0]
current_node_path = ""
for node_name in path:
current_node_path += "/" + node_name
self.get_node(current_node_path).size += bits_added
def get_node(self, path):
if path in self.mounted_file_systems.keys():
return self.mounted_file_systems[path]
if path == "/":
return self.root
path = path.split("/")
del path[0]
current_dir = self.root
for index, current_node in enumerate(iter(path)):
sub_dir_names = [sub_dir_name.name for
sub_dir_name in current_dir.directories]
sub_node_names = [sub_node_name.name for
sub_node_name in current_dir.nodes]
if current_node in sub_dir_names and index != (len(path) - 1):
index_next_dir = sub_dir_names.index(current_node)
current_dir = current_dir.directories[index_next_dir]
continue
elif current_node in sub_node_names and index == (len(path) - 1):
for node in current_dir.nodes:
if node.name == current_node:
return node
elif current_node not in sub_node_names:
raise NodeDoesNotExistError
def create(self, path, directory=False, content=""):
is_directory = directory
bits_to_be_added = 1 + len(content)
path = path.split("/")
new_node_name = path[-1]
del path[-1]
del path[0]
path = "/" + "/".join(path)
try:
self.get_node(path)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if self.available_size < bits_to_be_added:
raise NotEnoughSpaceError
current_node = self.get_node(path)
sub_node_names = [sub_node_name.name for
sub_node_name in current_node.nodes]
if new_node_name in sub_node_names:
raise DestinationNodeExistsError
if is_directory:
new_directory = self.SimpleDirectory(new_node_name)
current_node.nodes.append(new_directory)
current_node.directories.append(new_directory)
else:
new_file = self.SimpleFile(new_node_name, content)
current_node.nodes.append(new_file)
current_node.files.append(new_file)
self._size_update(path, bits_to_be_added)
def remove(self, path, directory=False, force=True):
original_node_is_directory = self.get_node(path).is_directory
node_to_be_removed = self.get_node(path)
is_directory = directory
del_with_force = force
if node_to_be_removed.is_directory and not is_directory:
raise NonExplicitDirectoryDeletionError
if is_directory and node_to_be_removed.nodes != [] \
and not del_with_force:
raise NonEmptyDirectoryDeletionError
parent_path = self._get_parent_path(path)[0]
bits_to_be_removed = self.get_node(path).size
parent_of_node_to_be_removed = self.get_node(parent_path)
if original_node_is_directory:
parent_of_node_to_be_removed.directories.remove(node_to_be_removed)
parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
else:
parent_of_node_to_be_removed.files.remove(node_to_be_removed)
parent_of_node_to_be_removed.nodes.remove(node_to_be_removed)
self._size_update(parent_path, -bits_to_be_removed)
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
source_name = self.get_node(source).name
destination_node = self.get_node(destination)
for node in destination_node.nodes:
if node.name == source_name:
raise DestinationNodeExistsError
node_to_be_moved = self.get_node(source)
if node_to_be_moved.is_directory:
self.remove(source, True, True)
destination_node.directories.append(node_to_be_moved)
destination_node.nodes.append(node_to_be_moved)
else:
self.remove(source, False)
destination_node.files.append(node_to_be_moved)
destination_node.nodes.append(node_to_be_moved)
self._size_update(destination, node_to_be_moved.size)
def link(self, source, destination, symbolic=True):
destination_parent_path = self._get_parent_path(destination)[0]
link_name = self._get_parent_path(destination)[1]
try:
self.get_node(source)
except NodeDoesNotExistError:
if symbolic:
raise NodeDoesNotExistError
else:
raise SourceNodeDoesNotExistError
if self.get_node(source).is_directory and not symbolic:
raise DirectoryHardLinkError
if symbolic:
new_soft_link_file = self.SoftLinkFile(link_name,
self.get_node(source))
self.get_node(destination_parent_path).\
files.append(new_soft_link_file)
self.get_node(destination_parent_path).\
nodes.append(new_soft_link_file)
+ self.available_size -= 1
else:
hard_link_file = self.SimpleFile(link_name, "content")
hard_link_file.content = self.get_node(source).content
self.get_node(destination_parent_path).\
files.append(hard_link_file)
self.get_node(destination_parent_path).\
nodes.append(hard_link_file)
+ self.available_size -= 1
def mount(self, file_system, path):
parent_path = self._get_parent_path(path)[0]
# mount_name = self._get_parent_path(path)[1]
try:
self.get_node(parent_path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if not self.get_node(parent_path).is_directory:
raise MountPointNotADirectoryError
if self.get_node(parent_path).nodes != []:
raise MountPointNotEmptyError
self.mounted_file_systems[path] = file_system.root
+ self.available_size -= 1
def unmount(self, path):
if path not in self.mounted_file_systems.keys():
- raise NotAMountpointError
+ raise NotAMountpointError
else:
del self.mounted_file_systems[path]
+ self.available_size += 1
def _get_parent_path(self, path):
parent_path = path.split("/")
if len(parent_path) > 2:
del parent_path[0]
last_node_name = parent_path[-1]
del parent_path[-1]
parent_path = "/" + "/".join(parent_path)
else:
last_node_name = parent_path[-1]
parent_path = "/"
return parent_path, last_node_name
class FileSystemError(Exception):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class SourceNodeDoesNotExistError (NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class DirectoryHardLinkError(FileExistsError):
pass
class LinkPathError(FileSystemError):
pass
class NotAMountpointError(FileSystemMountError):
pass