Решение на In-memory файлова система от Екатерина Горанова

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

Към профила на Екатерина Горанова

Резултати

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

Код

import re
class FileSystemError(Exception):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class LinkPathError(FileSystemError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class FileSystem(object):
def __init__(self, size):
self.size = size
self.root = FSDirectory()
def _parse_path(self, path):
list_path = re.sub(r'/+', r'/', path).split('/')
return [node for node in list_path if node]
def _containing_directory(self, path):
return self.get_node('/' + '/'.join(self._parse_path(path)[:-1]))
def _get_name(self, path):
return self._parse_path(path)[-1]
@property
def available_size(self):
return self.size - self.root.size
def get_node(self, path):
if path == '' or path[0] != '/':
raise NodeDoesNotExistError()
list_path = self._parse_path(path)
current_node = self.root
for node_name in list_path:
if node_name in current_node._nodes:
current_node = current_node._nodes[node_name]
else:
raise NodeDoesNotExistError()
return current_node
def create(self, path, directory=False, content=''):
try:
containing_directory = self._containing_directory(path)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError()
name = self._get_name(path)
if name in containing_directory._nodes:
raise DestinationNodeExistsError()
new_node = FSDirectory() if directory else FSFile(content)
if new_node.size > self.available_size:
raise NotEnoughSpaceError()
containing_directory.add_node(name, new_node)
def remove(self, path, directory=False, force=True):
node = self.get_node(path)
if node.is_directory:
if directory:
if not((node.nodes and force) or node.nodes == []):
raise NonEmptyDirectoryDeletionError()
else:
raise NonExplicitDirectoryDeletionError()
containing_directory = self._containing_directory(path)
containing_directory.remove_node(self._get_name(path))
def move(self, source, destination):
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError()
try:
destination_node = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError()
if not destination_node.is_directory:
raise DestinationNotADirectoryError()
source_name = self._get_name(source)
if source_name in destination_node._nodes:
raise DestinationNodeExistsError()
containing_directory = self._containing_directory(source)
destination_node.add_node(source_name, source_node)
containing_directory.remove_node(source_name)
def link(self, source, destination, symbolic=True):
if symbolic:
source_node = self.get_node(source)
else:
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError()
if source_node.is_directory:
raise DirectoryHardLinkError()
containing_directory = self._containing_directory(destination)
link = FSSymbolicLink(destination, source_node) if symbolic \
else FSHardLink(source_node)
containing_directory.add_node(self._get_name(destination), link)
def mount(self, file_system, path):
try:
mount_node = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError()
if not mount_node.is_directory:
raise MountPointNotADirectoryError()
if mount_node.nodes:
raise MountPointNotEmptyError()
file_system.root._is_mount_point = True
containing_directory = self._containing_directory(path)
containing_directory.add_node(self._get_name(path), file_system.root)
def unmount(self, path):
unmount_node = self.get_node(path)
if not unmount_node._is_mount_point:
raise NotAMountpointError()
unmount_node._is_mount_point = False
containing_directory = self._containing_directory(path)
name = self._get_name(path)
containing_directory.remove_node(name)
containing_directory.add_node(name, FSDirectory())
class FileSystemObject(object):
@property
def is_directory(self):
return isinstance(self, FSDirectory)
@property
def size(self):
return 1
class FSFile(FileSystemObject):
def __init__(self, content=''):
self._content = [content]
def append(self, text):
self._content.append(text)
def truncate(self, text):
del self._content[:]
self._content.append(text)
@property
def content(self):
return ''.join(self._content)
@property
def size(self):
return len(self.content) + 1
class FSDirectory(FileSystemObject):
def __init__(self):
self._nodes = {}
self._is_mount_point = False
def add_node(self, name, node):
self._nodes[name] = node
def remove_node(self, name):
del self._nodes[name]
@property
def nodes(self):
return list(self._nodes.values())
@property
def directories(self):
return [n for n in self.nodes if isinstance(n, FSDirectory) or
(hasattr(n, 'source') and isinstance(n.source, FSDirectory))]
@property
def files(self):
return [n for n in self.nodes if isinstance(n, FSFile) or
(hasattr(n, 'source') and isinstance(n.source, FSFile))]
@property
def size(self):
return sum([node.size for node in self.nodes]) + 1
class FSSymbolicLink(FileSystemObject):
def __init__(self, path, source):
self.link_path = path
self.source = source
def __getattr__(self, attr):
if hasattr(self.source, attr):
return getattr(self.source, attr)
raise LinkPathError()
@property
def size(self):
return super(FSSymbolicLink, self).size
class FSHardLink(FSFile):
def __init__(self, source):
self._content = source._content
@property
def size(self):
return super(FSFile, self).size

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

........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.191s

FAILED (errors=4)

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

Екатерина обнови решението на 30.04.2015 11:41 (преди почти 9 години)

+import re
+
+
+class FileSystemError(Exception):
+ pass
+
+
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeExistsError(FileSystemError):
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class LinkPathError(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileSystemError):
+ pass
+
+
+class FileSystemMountError(FileSystemError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class NotAMountpointError(FileSystemMountError):
+ pass
+
+
+class FileSystem(object):
+
+ def __init__(self, size):
+ self.size = size
+ self.root = FSDirectory()
+
+ def _parse_path(self, path):
+ list_path = re.sub(r'/+', r'/', path).split('/')
+ return [node for node in list_path if node]
+
+ def _containing_directory(self, path):
+ return self.get_node('/' + '/'.join(self._parse_path(path)[:-1]))
+
+ def _get_name(self, path):
+ return self._parse_path(path)[-1]
+
+ @property
+ def available_size(self):
+ return self.size - self.root.size
+
+ def get_node(self, path):
+ if path == '' or path[0] != '/':
+ raise NodeDoesNotExistError()
+
+ list_path = self._parse_path(path)
+ current_node = self.root
+ for node_name in list_path:
+ if node_name in current_node._nodes:
+ current_node = current_node._nodes[node_name]
+ else:
+ raise NodeDoesNotExistError()
+ return current_node
+
+ def create(self, path, directory=False, content=''):
+ try:
+ containing_directory = self._containing_directory(path)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError()
+
+ name = self._get_name(path)
+ if name in containing_directory._nodes:
+ raise DestinationNodeExistsError()
+
+ new_node = FSDirectory() if directory else FSFile(content)
+ if new_node.size > self.available_size:
+ raise NotEnoughSpaceError()
+
+ containing_directory.add_node(name, new_node)
+
+ def remove(self, path, directory=False, force=True):
+ node = self.get_node(path)
+ if node.is_directory:
+ if directory:
+ if not((node.nodes and force) or node.nodes == []):
+ raise NonEmptyDirectoryDeletionError()
+ else:
+ raise NonExplicitDirectoryDeletionError()
+ containing_directory = self._containing_directory(path)
+ containing_directory.remove_node(self._get_name(path))
+
+ def move(self, source, destination):
+ try:
+ source_node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError()
+
+ try:
+ destination_node = self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError()
+
+ if not destination_node.is_directory:
+ raise DestinationNotADirectoryError()
+
+ source_name = self._get_name(source)
+ if source_name in destination_node._nodes:
+ raise DestinationNodeExistsError()
+
+ containing_directory = self._containing_directory(source)
+ destination_node.add_node(source_name, source_node)
+ containing_directory.remove_node(source_name)
+
+ def link(self, source, destination, symbolic=True):
+ if symbolic:
+ source_node = self.get_node(source)
+ else:
+ try:
+ source_node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError()
+
+ if source_node.is_directory:
+ raise DirectoryHardLinkError()
+
+ containing_directory = self._containing_directory(destination)
+ link = FSSymbolicLink(destination, source_node) if symbolic \
+ else FSHardLink(source_node)
+ containing_directory.add_node(self._get_name(destination), link)
+
+ def mount(self, file_system, path):
+ try:
+ mount_node = self.get_node(path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError()
+
+ if not mount_node.is_directory:
+ raise MountPointNotADirectoryError()
+
+ if mount_node.nodes:
+ raise MountPointNotEmptyError()
+
+ file_system.root._is_mount_point = True
+ containing_directory = self._containing_directory(path)
+ containing_directory.add_node(self._get_name(path), file_system.root)
+
+ def unmount(self, path):
+ unmount_node = self.get_node(path)
+ if not unmount_node._is_mount_point:
+ raise NotAMountpointError()
+ unmount_node._is_mount_point = False
+
+ containing_directory = self._containing_directory(path)
+ name = self._get_name(path)
+ containing_directory.remove_node(name)
+ containing_directory.add_node(name, FSDirectory())
+
+
+class FileSystemObject(object):
+
+ @property
+ def is_directory(self):
+ return isinstance(self, FSDirectory)
+
+ @property
+ def size(self):
+ return 1
+
+
+class FSFile(FileSystemObject):
+
+ def __init__(self, content=''):
+ self._content = [content]
+
+ def append(self, text):
+ self._content.append(text)
+
+ def truncate(self, text):
+ del self._content[:]
+ self._content.append(text)
+
+ @property
+ def content(self):
+ return ''.join(self._content)
+
+ @property
+ def size(self):
+ return len(self.content) + 1
+
+
+class FSDirectory(FileSystemObject):
+
+ def __init__(self):
+ self._nodes = {}
+ self._is_mount_point = False
+
+ def add_node(self, name, node):
+ self._nodes[name] = node
+
+ def remove_node(self, name):
+ del self._nodes[name]
+
+ @property
+ def nodes(self):
+ return list(self._nodes.values())
+
+ @property
+ def directories(self):
+ return [n for n in self.nodes if isinstance(n, FSDirectory) or
+ (hasattr(n, 'source') and isinstance(n.source, FSDirectory))]
+
+ @property
+ def files(self):
+ return [n for n in self.nodes if isinstance(n, FSFile) or
+ (hasattr(n, 'source') and isinstance(n.source, FSFile))]
+
+ @property
+ def size(self):
+ return sum([node.size for node in self.nodes]) + 1
+
+
+class FSSymbolicLink(FileSystemObject):
+
+ def __init__(self, path, source):
+ self.link_path = path
+ self.source = source
+
+ def __getattr__(self, attr):
+ if hasattr(self.source, attr):
+ return getattr(self.source, attr)
+ raise LinkPathError()
+
+ @property
+ def size(self):
+ return super(FSSymbolicLink, self).size
+
+
+class FSHardLink(FSFile):
+
+ def __init__(self, source):
+ self._content = source._content
+
+ @property
+ def size(self):
+ return super(FSFile, self).size