Решение на In-memory файлова система от Михаил Здравков

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

Към профила на Михаил Здравков

Резултати

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

Код

"""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 HardLink:
def __init__(self, fs, address):
self.fs = fs
self.address = address
def append(self, text):
self.fs.link_targets[self.address][0].append(text)
def truncate(self, text):
self.fs.link_targets[self.address][0].truncate(text)
def __getattribute__(self, attr):
if attr == 'content':
return self.fs.link_targets[self.address][0].content
else:
return object.__getattribute__(self, attr)
class FileSystem:
def __init__(self, size):
self.size = size
self.paths = Dir([('', Dir())])
self.available_size = size - 1
self.link_targets = []
def __traverse(self, path, exception=NodeDoesNotExistError):
current = self.paths
for i in path:
try:
if isinstance(current[i], str):
current = self.get_node(current[i])
else:
current = current[i]
except KeyError:
raise exception
except TypeError:
raise NotADirectoryError
return current
def get_node(self, path):
path = check_path(path)
return self.__traverse(path)
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.__traverse(path[:-1], DestinationNodeDoesNotExistError)
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.__traverse(path[:-1])
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]], HardLink):
self.available_size += 1
if self.link_targets[current[path[-1]].address] < 2:
size = self.link_targets[current[path[-1]].address].size
del self.link_targets[current[path[-1]].address]
self.available_size += size
else:
a, c = self.link_targets[current[path[-1]].address]
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.__traverse(source[:-1], SourceNodeDoesNotExistError)
if source[-1] not in source_path:
raise SourceNodeDoesNotExistError
exception = DestinationNodeDoesNotExistError
dest_path = self.__traverse(destination, exception)
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)
exception = NodeDoesNotExistError
if not symbolic:
exception = SourceNodeDoesNotExistError
source_path = self.__traverse(source[:-1], exception)
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
exception = DestinationNodeDoesNotExistError
dest_path = self.__traverse(destination[:-1], exception)
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]] = HardLink(self, address)
source_path[source[-1]] = HardLink(self, address)
self.available_size -= 1
def mount(self, file_system, path):
path = check_path(path)
current = self.__traverse(path[:-1], MountPointDoesNotExistError)
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.__traverse(path[:-1])
if path[-1] not in current:
raise MountPointDoesNotExistError
if not hasattr(current[path[-1]], 'mount_point'):
raise NotAMountpointError
current[path[-1]] = Dir()

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

........E....E.EEE
======================================================================
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

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

----------------------------------------------------------------------
Ran 18 tests in 10.215s

FAILED (errors=5)

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

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

Михаил обнови решението на 30.04.2015 16:43 (преди почти 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 HardLink:
+
+ def __init__(self, fs, address):
+ self.fs = fs
+ self.address = address
+
+ def append(self, text):
+ self.fs.link_targets[self.address][0].append(text)
+
+ def truncate(self, text):
+ self.fs.link_targets[self.address][0].truncate(text)
+
+ def __getattribute__(self, attr):
+ if attr == 'content':
+ return self.fs.link_targets[self.address][0].content
+ else:
+ return object.__getattribute__(self, attr)
+
+
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]
+ # if isinstance(current, HardLink):
+ # 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):
+ if isinstance(current[path[-1]], HardLink):
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]]]
+ if self.link_targets[current[path[-1]].address] < 2:
+ size = self.link_targets[current[path[-1]].address].size
+ del self.link_targets[current[path[-1]].address]
self.available_size += size
else:
- a, c = self.link_targets[current[path[-1]]]
+ a, c = self.link_targets[current[path[-1]].address]
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
+ dest_path[destination[-1]] = HardLink(self, address)
+ source_path[source[-1]] = HardLink(self, 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()

Михаил обнови решението на 30.04.2015 16:57 (преди почти 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 HardLink:
def __init__(self, fs, address):
self.fs = fs
self.address = address
def append(self, text):
self.fs.link_targets[self.address][0].append(text)
def truncate(self, text):
self.fs.link_targets[self.address][0].truncate(text)
def __getattribute__(self, attr):
if attr == 'content':
return self.fs.link_targets[self.address][0].content
else:
return object.__getattribute__(self, attr)
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)
-
+ def __traverse(self, path, exception=NodeDoesNotExistError):
current = self.paths
for i in path:
try:
if isinstance(current[i], str):
current = self.get_node(current[i])
else:
current = current[i]
except KeyError:
- raise NodeDoesNotExistError
+ raise exception
except TypeError:
raise NotADirectoryError
- # if isinstance(current, HardLink):
- # return self.link_targets[current][0]
return current
+ def get_node(self, path):
+ path = check_path(path)
+
+ return self.__traverse(path)
+
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
+ current = self.__traverse(path[:-1], DestinationNodeDoesNotExistError)
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
+ current = self.__traverse(path[:-1])
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]], HardLink):
self.available_size += 1
if self.link_targets[current[path[-1]].address] < 2:
size = self.link_targets[current[path[-1]].address].size
del self.link_targets[current[path[-1]].address]
self.available_size += size
else:
a, c = self.link_targets[current[path[-1]].address]
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
+ source_path = self.__traverse(source[:-1], SourceNodeDoesNotExistError)
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
+ exception = DestinationNodeDoesNotExistError
+ dest_path = self.__traverse(destination, exception)
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
+ exception = NodeDoesNotExistError
+ if not symbolic:
+ exception = SourceNodeDoesNotExistError
+ source_path = self.__traverse(source[:-1], exception)
+
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
+ exception = DestinationNodeDoesNotExistError
+ dest_path = self.__traverse(destination[:-1], exception)
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]] = HardLink(self, address)
source_path[source[-1]] = HardLink(self, 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
+ current = self.__traverse(path[:-1], MountPointDoesNotExistError)
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
+ current = self.__traverse(path[:-1])
if path[-1] not in current:
raise MountPointDoesNotExistError
if not hasattr(current[path[-1]], 'mount_point'):
raise NotAMountpointError
current[path[-1]] = Dir()