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

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

Към профила на Йоан Динков

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 15 успешни тест(а)
  • 3 неуспешни тест(а)

Код

class FileSystemError(Exception):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class LinkNotFound(FileSystemError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class LinkPathError(FileSystemError):
pass
class Node:
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def is_directory(self):
if self.is_link:
node_type = type(self.link_path)
else:
node_type = type(self)
return node_type is Directory
@property
def is_link(self):
return type(self) is Link
@property
def is_file(self):
if self.is_link:
node_type = type(self.link_path)
else:
node_type = type(self)
return node_type is File
class File(Node):
def __init__(self, name, content=''):
self._content = content
self._name = name
@property
def shared(self):
return self._shared
@property
def content(self):
return self._content
@content.setter
def content(self, content):
self._content = content
@property
def size(self):
return len(self._content) + 1
def append(self, text):
self._content = self._content + str(text)
def truncate(self, text):
self._content = str(text)
class Link(Node):
def __init__(self, name, node=None):
self._name = name
if node:
self._is_file = node.is_file
self._link_path = node
def __getattr__(self, attr):
if self._link_path and hasattr(self._link_path, attr):
return getattr(self._link_path, attr)
else:
raise LinkPathError
@property
def link_path(self):
return self._link_path
@property
def size(self):
return 1
class Directory(Node):
def __init__(self, name, file_system=False):
self._nodes = []
self._name = name
self._is_file_system = file_system
def __iter__(self):
for node in self._nodes:
yield node
@property
def is_empty(self):
return not self._nodes
@property
def directories(self):
return [item for item in self._nodes if item.is_directory]
@property
def files(self):
return [item for item in self._nodes if item.is_file]
@property
def nodes(self):
return self._nodes
@property
def nodes_dict(self):
return dict((item.name, item) for item in self._nodes)
@property
def is_file_system(self):
return self._is_file_system
@is_file_system.setter
def is_file_system(self, is_file_system):
self._is_file_system = is_file_system
@property
def size(self):
size = 1
contents = []
for node in self.nodes:
if node.is_file:
if node.content not in contents:
contents.append(node.content)
size += node.size
else:
size += 1
elif node.is_file_system:
size += 1
elif node.is_directory:
size += node.size
else:
size += 1
return size
class FileSystem:
def __init__(self, size):
self._size = size
self._root = Directory('/')
self._available_size = size - self._root.size
@property
def size(self):
return self._size
@property
def available_size(self):
return self._size - self._root.size
def get_node(self, path):
node_paths = filter(None, path.split('/'))
if '/' not in path and not path:
raise NodeDoesNotExistError
current_node = self._root
for node_path in node_paths:
if node_path in current_node.nodes_dict:
current_node = current_node.nodes_dict[node_path]
else:
raise NodeDoesNotExistError
return current_node
def create(self, path, directory=False, content=''):
destination, name = self._split_path(path)
try:
destination_directory = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if name in destination_directory.nodes_dict:
raise DestinationNodeExistsError
elif len(content) >= self.available_size:
raise NotEnoughSpaceError
if directory is True:
destination_directory.nodes.append(Directory(name))
else:
destination_directory.nodes.append(File(name, content))
def remove(self, path, directory=False, force=True):
destination, name = self._split_path(path)
node = self.get_node(path)
parent = self.get_node(destination)
size = node.size
if directory is False and node.is_directory:
raise NonExplicitDirectoryDeletionError
elif directory is True and force is False:
if node.is_empty is False:
raise NonEmptyDirectoryDeletionError
else:
parent.nodes.remove(node)
def move(self, source, destination):
source_destination, source_name = self._split_path(source)
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
try:
destination_node = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if destination_node.is_file:
raise DestinationNotADirectoryError
if source_name in destination_node.nodes_dict:
raise DestinationNodeExistsError
self.remove(source, node.is_directory, True)
destination_node.nodes.append(node)
def link(self, source, destination, symbolic=True):
parent_destination, name = self._split_path(destination)
parent = self.get_node(parent_destination)
if symbolic is True:
node = self.get_node(source)
parent.nodes.append(Link(name, node))
else:
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
if node.is_directory:
raise DirectoryHardLinkError
linked_node = Link(name, self.get_node(source))
parent.nodes.append(linked_node)
def mount(self, file_system, path):
destination, name = self._split_path(path)
parent = self.get_node(destination)
try:
destination = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if destination.is_directory is False:
raise MountPointNotADirectoryError
elif destination.is_empty is False:
raise MountPointNotEmptyError
parent.nodes.remove(destination)
directory = file_system.get_node('/')
directory.name = name
directory.is_file_system = True
parent.nodes.append(directory)
def unmount(self, path):
destination, name = self._split_path(path)
file_system = self.get_node(path)
parent = self.get_node(destination)
if not file_system.is_file_system:
raise NotAMountpointError
parent.nodes.remove(file_system)
parent.nodes.append(Directory(name))
def _split_path(self, path):
destination, name = tuple(path.rsplit('/', 1))
if not destination:
destination = '/'
return (destination, name)

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

.............E.EE.
======================================================================
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 6.234s

FAILED (errors=3)

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

Йоан обнови решението на 28.04.2015 22:48 (преди над 9 години)

+class FileSystemError(Exception):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeExistsError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNotADirectoryError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class SourceNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class FileSystemMountError(FileSystemError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class NotAMountpointError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class LinkNotFound(FileSystemError):
+ pass
+
+
+class DirectoryHardLinkError(FileSystemError):
+ pass
+
+
+class LinkPathError(FileSystemError):
+ pass
+
+
+class Node:
+ @property
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, name):
+ self._name = name
+
+ @property
+ def is_directory(self):
+ return type(self) is Directory
+
+ @property
+ def is_file(self):
+ return type(self) is File
+
+
+class File(Node):
+ def __init__(self, name, content=''):
+ self._content = content
+ self._name = name
+
+ @property
+ def content(self):
+ return self._content
+
+ @content.setter
+ def content(self, content):
+ self._content = content
+
+ @property
+ def size(self):
+ return len(self._content) + 1
+
+ def append(self, text):
+ self._content = self._content + str(text)
+
+ def truncate(self, text):
+ self._content = str(text)
+
+
+class Link(Node):
+ def __init__(self, name, node=None):
+ self._name = name
+
+ if node:
+ self._is_file = node.is_file
+ self._link_path = node
+
+ def __getattr__(self, attr):
+ if self._link_path and hasattr(self._link_path, attr):
+ return getattr(self._link_path, attr)
+ else:
+ raise LinkPathError
+
+ @property
+ def is_file(self):
+ return self._is_file
+
+ @property
+ def is_directory(self):
+ return not self._is_file
+
+ @property
+ def link_path(self):
+ return self._link_path
+
+ @property
+ def size(self):
+ return self._link_path.size
+
+
+class Directory(Node):
+ def __init__(self, name, file_system=False):
+ self._nodes = []
+ self._name = name
+ self._is_file_system = file_system
+
+ @property
+ def is_empty(self):
+ return not self._nodes
+
+ @property
+ def directories(self):
+ return [item for item in self._nodes if item.is_directory]
+
+ @property
+ def files(self):
+ return [item for item in self._nodes if item.is_file]
+
+ @property
+ def nodes(self):
+ return self._nodes
+
+ @property
+ def nodes_dict(self):
+ return dict((item.name, item) for item in self._nodes)
+
+ @property
+ def is_file_system(self):
+ return self._is_file_system
+
+ @is_file_system.setter
+ def is_file_system(self, is_file_system):
+ self._is_file_system = is_file_system
+
+ @property
+ def size(self):
+ size = 1
+
+ for node in self.nodes:
+ if type(node) is FileSystem:
+ size += 1
+ else:
+ size += node.size
+
+ return size
+
+
+class FileSystem:
+ def __init__(self, size):
+ self._size = size
+ self._root = Directory('/')
+ self._available_size = size - self._root.size
+
+ @property
+ def size(self):
+ return self._size
+
+ @property
+ def available_size(self):
+ return self._size - self._root.size
+
+ def get_node(self, path):
+ node_paths = filter(None, path.split('/'))
+
+ if '/' not in path and not path:
+ raise NodeDoesNotExistError
+
+ current_node = self._root
+
+ for node_path in node_paths:
+ if node_path in current_node.nodes_dict:
+ current_node = current_node.nodes_dict[node_path]
+ else:
+ raise NodeDoesNotExistError
+
+ return current_node
+
+ def create(self, path, directory=False, content=''):
+ destination, name = self._split_path(path)
+
+ try:
+ destination_directory = self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ if name in destination_directory.nodes_dict:
+ raise DestinationNodeExistsError
+ elif len(content) >= self.available_size:
+ raise NotEnoughSpaceError
+
+ if directory is True:
+ destination_directory.nodes.append(Directory(name))
+ else:
+ destination_directory.nodes.append(File(name, content))
+
+ def remove(self, path, directory=False, force=True):
+ destination, name = self._split_path(path)
+
+ node = self.get_node(path)
+ parent = self.get_node(destination)
+ size = node.size
+
+ if directory is False and node.is_directory:
+ raise NonExplicitDirectoryDeletionError
+ elif directory is True and force is False:
+ if node.is_empty is False:
+ raise NonEmptyDirectoryDeletionError
+ else:
+ parent.nodes.remove(node)
+
+ def move(self, source, destination):
+ source_destination, source_name = self._split_path(source)
+
+ try:
+ node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+
+ try:
+ destination_node = self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+
+ if destination_node.is_file:
+ raise DestinationNotADirectoryError
+
+ if source_name in destination_node.nodes_dict:
+ raise DestinationNodeExistsError
+
+ self.remove(source, node.is_directory, True)
+
+ destination_node.nodes.append(node)
+
+ def link(self, source, destination, symbolic=True):
+ parent_destination, name = self._split_path(destination)
+ parent = self.get_node(parent_destination)
+
+ if symbolic is True:
+ node = self.get_node(source)
+
+ parent.nodes.append(Link(name, node))
+ else:
+ try:
+ node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+
+ if node.is_directory:
+ raise DirectoryHardLinkError
+
+ linked_node = File(name)
+ linked_node.content = self.get_node(source).content
+
+ parent.nodes.append(linked_node)
+
+ def mount(self, file_system, path):
+ destination, name = self._split_path(path)
+
+ parent = self.get_node(destination)
+
+ try:
+ destination = self.get_node(path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError
+
+ if destination.is_directory is False:
+ raise MountPointNotADirectoryError
+ elif destination.is_empty is False:
+ raise MountPointNotEmptyError
+
+ parent.nodes.remove(destination)
+
+ directory = file_system.get_node('/')
+ directory.name = name
+ directory.is_file_system = True
+
+ parent.nodes.append(directory)
+
+ def unmount(self, path):
+ destination, name = self._split_path(path)
+ file_system = self.get_node(path)
+ parent = self.get_node(destination)
+
+ if not file_system.is_file_system:
+ raise NotAMountpointError
+
+ parent.nodes.remove(file_system)
+ parent.nodes.append(Directory(name))
+
+ def _split_path(self, path):
+ destination, name = tuple(path.rsplit('/', 1))
+
+ if not destination:
+ destination = '/'
+
+ return (destination, name)

Йоан обнови решението на 29.04.2015 01:25 (преди над 9 години)

+from copy import deepcopy
+
+
class FileSystemError(Exception):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class LinkNotFound(FileSystemError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class LinkPathError(FileSystemError):
pass
class Node:
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def is_directory(self):
return type(self) is Directory
@property
def is_file(self):
return type(self) is File
class File(Node):
def __init__(self, name, content=''):
self._content = content
self._name = name
@property
+ def shared(self):
+ return self._shared
+
+ @property
def content(self):
return self._content
@content.setter
def content(self, content):
self._content = content
@property
def size(self):
return len(self._content) + 1
def append(self, text):
self._content = self._content + str(text)
def truncate(self, text):
self._content = str(text)
class Link(Node):
def __init__(self, name, node=None):
self._name = name
if node:
self._is_file = node.is_file
self._link_path = node
def __getattr__(self, attr):
if self._link_path and hasattr(self._link_path, attr):
return getattr(self._link_path, attr)
else:
raise LinkPathError
@property
def is_file(self):
return self._is_file
@property
def is_directory(self):
return not self._is_file
@property
def link_path(self):
return self._link_path
@property
def size(self):
return self._link_path.size
class Directory(Node):
def __init__(self, name, file_system=False):
self._nodes = []
self._name = name
self._is_file_system = file_system
+ def __iter__(self):
+ for node in self._nodes:
+ yield node
+
@property
def is_empty(self):
return not self._nodes
@property
def directories(self):
return [item for item in self._nodes if item.is_directory]
@property
def files(self):
return [item for item in self._nodes if item.is_file]
@property
def nodes(self):
return self._nodes
@property
def nodes_dict(self):
return dict((item.name, item) for item in self._nodes)
@property
def is_file_system(self):
return self._is_file_system
@is_file_system.setter
def is_file_system(self, is_file_system):
self._is_file_system = is_file_system
@property
def size(self):
size = 1
+ contents = []
for node in self.nodes:
if type(node) is FileSystem:
size += 1
+ elif node.is_file:
+ if node.content not in contents:
+ contents.append(node.content)
+ size += node.size
+ else:
+ size += 1
else:
size += node.size
return size
class FileSystem:
def __init__(self, size):
self._size = size
self._root = Directory('/')
self._available_size = size - self._root.size
@property
def size(self):
return self._size
@property
def available_size(self):
return self._size - self._root.size
def get_node(self, path):
node_paths = filter(None, path.split('/'))
if '/' not in path and not path:
raise NodeDoesNotExistError
current_node = self._root
for node_path in node_paths:
if node_path in current_node.nodes_dict:
current_node = current_node.nodes_dict[node_path]
else:
raise NodeDoesNotExistError
return current_node
def create(self, path, directory=False, content=''):
destination, name = self._split_path(path)
try:
destination_directory = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if name in destination_directory.nodes_dict:
raise DestinationNodeExistsError
elif len(content) >= self.available_size:
raise NotEnoughSpaceError
if directory is True:
destination_directory.nodes.append(Directory(name))
else:
destination_directory.nodes.append(File(name, content))
def remove(self, path, directory=False, force=True):
destination, name = self._split_path(path)
node = self.get_node(path)
parent = self.get_node(destination)
size = node.size
if directory is False and node.is_directory:
raise NonExplicitDirectoryDeletionError
elif directory is True and force is False:
if node.is_empty is False:
raise NonEmptyDirectoryDeletionError
else:
parent.nodes.remove(node)
def move(self, source, destination):
source_destination, source_name = self._split_path(source)
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
try:
destination_node = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if destination_node.is_file:
raise DestinationNotADirectoryError
if source_name in destination_node.nodes_dict:
raise DestinationNodeExistsError
self.remove(source, node.is_directory, True)
destination_node.nodes.append(node)
def link(self, source, destination, symbolic=True):
parent_destination, name = self._split_path(destination)
parent = self.get_node(parent_destination)
if symbolic is True:
node = self.get_node(source)
parent.nodes.append(Link(name, node))
else:
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
if node.is_directory:
raise DirectoryHardLinkError
- linked_node = File(name)
- linked_node.content = self.get_node(source).content
+ linked_node = Link(name, self.get_node(source))
parent.nodes.append(linked_node)
def mount(self, file_system, path):
destination, name = self._split_path(path)
parent = self.get_node(destination)
try:
destination = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if destination.is_directory is False:
raise MountPointNotADirectoryError
elif destination.is_empty is False:
raise MountPointNotEmptyError
parent.nodes.remove(destination)
directory = file_system.get_node('/')
directory.name = name
directory.is_file_system = True
parent.nodes.append(directory)
def unmount(self, path):
destination, name = self._split_path(path)
file_system = self.get_node(path)
parent = self.get_node(destination)
if not file_system.is_file_system:
raise NotAMountpointError
parent.nodes.remove(file_system)
parent.nodes.append(Directory(name))
def _split_path(self, path):
destination, name = tuple(path.rsplit('/', 1))
if not destination:
destination = '/'
return (destination, name)

Йоан обнови решението на 29.04.2015 01:50 (преди над 9 години)

-from copy import deepcopy
-
-
class FileSystemError(Exception):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class LinkNotFound(FileSystemError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class LinkPathError(FileSystemError):
pass
class Node:
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def is_directory(self):
- return type(self) is Directory
+ if type(self) is Link:
+ return type(self.link_path) is Directory
+ else:
+ return type(self) is Directory
@property
+ def is_link(self):
+ return type(self) is Link
+
+ @property
def is_file(self):
- return type(self) is File
+ if type(self) is Link:
+ return type(self.link_path) is File
+ else:
+ return type(self) is File
class File(Node):
def __init__(self, name, content=''):
self._content = content
self._name = name
@property
def shared(self):
return self._shared
@property
def content(self):
return self._content
@content.setter
def content(self, content):
self._content = content
@property
def size(self):
return len(self._content) + 1
def append(self, text):
self._content = self._content + str(text)
def truncate(self, text):
self._content = str(text)
class Link(Node):
def __init__(self, name, node=None):
self._name = name
if node:
self._is_file = node.is_file
self._link_path = node
def __getattr__(self, attr):
if self._link_path and hasattr(self._link_path, attr):
return getattr(self._link_path, attr)
else:
raise LinkPathError
@property
- def is_file(self):
- return self._is_file
-
- @property
- def is_directory(self):
- return not self._is_file
-
- @property
def link_path(self):
return self._link_path
@property
def size(self):
- return self._link_path.size
+ return 1
class Directory(Node):
def __init__(self, name, file_system=False):
self._nodes = []
self._name = name
self._is_file_system = file_system
def __iter__(self):
for node in self._nodes:
yield node
@property
def is_empty(self):
return not self._nodes
@property
def directories(self):
return [item for item in self._nodes if item.is_directory]
@property
def files(self):
return [item for item in self._nodes if item.is_file]
@property
def nodes(self):
return self._nodes
@property
def nodes_dict(self):
return dict((item.name, item) for item in self._nodes)
@property
def is_file_system(self):
return self._is_file_system
@is_file_system.setter
def is_file_system(self, is_file_system):
self._is_file_system = is_file_system
@property
def size(self):
size = 1
contents = []
for node in self.nodes:
if type(node) is FileSystem:
size += 1
elif node.is_file:
if node.content not in contents:
contents.append(node.content)
size += node.size
else:
size += 1
- else:
+ elif node.is_directory:
size += node.size
+ else:
+ size += 1
return size
class FileSystem:
def __init__(self, size):
self._size = size
self._root = Directory('/')
self._available_size = size - self._root.size
@property
def size(self):
return self._size
@property
def available_size(self):
return self._size - self._root.size
def get_node(self, path):
node_paths = filter(None, path.split('/'))
if '/' not in path and not path:
raise NodeDoesNotExistError
current_node = self._root
for node_path in node_paths:
if node_path in current_node.nodes_dict:
current_node = current_node.nodes_dict[node_path]
else:
raise NodeDoesNotExistError
return current_node
def create(self, path, directory=False, content=''):
destination, name = self._split_path(path)
try:
destination_directory = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if name in destination_directory.nodes_dict:
raise DestinationNodeExistsError
elif len(content) >= self.available_size:
raise NotEnoughSpaceError
if directory is True:
destination_directory.nodes.append(Directory(name))
else:
destination_directory.nodes.append(File(name, content))
def remove(self, path, directory=False, force=True):
destination, name = self._split_path(path)
node = self.get_node(path)
parent = self.get_node(destination)
size = node.size
if directory is False and node.is_directory:
raise NonExplicitDirectoryDeletionError
elif directory is True and force is False:
if node.is_empty is False:
raise NonEmptyDirectoryDeletionError
else:
parent.nodes.remove(node)
def move(self, source, destination):
source_destination, source_name = self._split_path(source)
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
try:
destination_node = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if destination_node.is_file:
raise DestinationNotADirectoryError
if source_name in destination_node.nodes_dict:
raise DestinationNodeExistsError
self.remove(source, node.is_directory, True)
destination_node.nodes.append(node)
def link(self, source, destination, symbolic=True):
parent_destination, name = self._split_path(destination)
parent = self.get_node(parent_destination)
if symbolic is True:
node = self.get_node(source)
parent.nodes.append(Link(name, node))
else:
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
if node.is_directory:
raise DirectoryHardLinkError
linked_node = Link(name, self.get_node(source))
parent.nodes.append(linked_node)
def mount(self, file_system, path):
destination, name = self._split_path(path)
parent = self.get_node(destination)
try:
destination = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if destination.is_directory is False:
raise MountPointNotADirectoryError
elif destination.is_empty is False:
raise MountPointNotEmptyError
parent.nodes.remove(destination)
directory = file_system.get_node('/')
directory.name = name
directory.is_file_system = True
parent.nodes.append(directory)
def unmount(self, path):
destination, name = self._split_path(path)
file_system = self.get_node(path)
parent = self.get_node(destination)
if not file_system.is_file_system:
raise NotAMountpointError
parent.nodes.remove(file_system)
parent.nodes.append(Directory(name))
def _split_path(self, path):
destination, name = tuple(path.rsplit('/', 1))
if not destination:
destination = '/'
return (destination, name)

Йоан обнови решението на 29.04.2015 14:15 (преди над 9 години)

class FileSystemError(Exception):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class SourceNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class LinkNotFound(FileSystemError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class LinkPathError(FileSystemError):
pass
class Node:
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
@property
def is_directory(self):
- if type(self) is Link:
- return type(self.link_path) is Directory
+ if self.is_link:
+ node_type = type(self.link_path)
else:
- return type(self) is Directory
+ node_type = type(self)
+ return node_type is Directory
+
@property
def is_link(self):
return type(self) is Link
@property
def is_file(self):
- if type(self) is Link:
- return type(self.link_path) is File
+ if self.is_link:
+ node_type = type(self.link_path)
else:
- return type(self) is File
+ node_type = type(self)
+ return node_type is File
+
class File(Node):
def __init__(self, name, content=''):
self._content = content
self._name = name
@property
def shared(self):
return self._shared
@property
def content(self):
return self._content
@content.setter
def content(self, content):
self._content = content
@property
def size(self):
return len(self._content) + 1
def append(self, text):
self._content = self._content + str(text)
def truncate(self, text):
self._content = str(text)
class Link(Node):
def __init__(self, name, node=None):
self._name = name
if node:
self._is_file = node.is_file
self._link_path = node
def __getattr__(self, attr):
if self._link_path and hasattr(self._link_path, attr):
return getattr(self._link_path, attr)
else:
raise LinkPathError
@property
def link_path(self):
return self._link_path
@property
def size(self):
return 1
class Directory(Node):
def __init__(self, name, file_system=False):
self._nodes = []
self._name = name
self._is_file_system = file_system
def __iter__(self):
for node in self._nodes:
yield node
@property
def is_empty(self):
return not self._nodes
@property
def directories(self):
return [item for item in self._nodes if item.is_directory]
@property
def files(self):
return [item for item in self._nodes if item.is_file]
@property
def nodes(self):
return self._nodes
@property
def nodes_dict(self):
return dict((item.name, item) for item in self._nodes)
@property
def is_file_system(self):
return self._is_file_system
@is_file_system.setter
def is_file_system(self, is_file_system):
self._is_file_system = is_file_system
@property
def size(self):
size = 1
contents = []
for node in self.nodes:
- if type(node) is FileSystem:
- size += 1
- elif node.is_file:
+ if node.is_file:
if node.content not in contents:
contents.append(node.content)
size += node.size
else:
size += 1
+ elif node.is_file_system:
+ size += 1
elif node.is_directory:
size += node.size
else:
size += 1
return size
class FileSystem:
def __init__(self, size):
self._size = size
self._root = Directory('/')
self._available_size = size - self._root.size
@property
def size(self):
return self._size
@property
def available_size(self):
return self._size - self._root.size
def get_node(self, path):
node_paths = filter(None, path.split('/'))
if '/' not in path and not path:
raise NodeDoesNotExistError
current_node = self._root
for node_path in node_paths:
if node_path in current_node.nodes_dict:
current_node = current_node.nodes_dict[node_path]
else:
raise NodeDoesNotExistError
return current_node
def create(self, path, directory=False, content=''):
destination, name = self._split_path(path)
try:
destination_directory = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if name in destination_directory.nodes_dict:
raise DestinationNodeExistsError
elif len(content) >= self.available_size:
raise NotEnoughSpaceError
if directory is True:
destination_directory.nodes.append(Directory(name))
else:
destination_directory.nodes.append(File(name, content))
def remove(self, path, directory=False, force=True):
destination, name = self._split_path(path)
node = self.get_node(path)
parent = self.get_node(destination)
size = node.size
if directory is False and node.is_directory:
raise NonExplicitDirectoryDeletionError
elif directory is True and force is False:
if node.is_empty is False:
raise NonEmptyDirectoryDeletionError
else:
parent.nodes.remove(node)
def move(self, source, destination):
source_destination, source_name = self._split_path(source)
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
try:
destination_node = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if destination_node.is_file:
raise DestinationNotADirectoryError
if source_name in destination_node.nodes_dict:
raise DestinationNodeExistsError
self.remove(source, node.is_directory, True)
destination_node.nodes.append(node)
def link(self, source, destination, symbolic=True):
parent_destination, name = self._split_path(destination)
parent = self.get_node(parent_destination)
if symbolic is True:
node = self.get_node(source)
parent.nodes.append(Link(name, node))
else:
try:
node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
if node.is_directory:
raise DirectoryHardLinkError
linked_node = Link(name, self.get_node(source))
parent.nodes.append(linked_node)
def mount(self, file_system, path):
destination, name = self._split_path(path)
parent = self.get_node(destination)
try:
destination = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if destination.is_directory is False:
raise MountPointNotADirectoryError
elif destination.is_empty is False:
raise MountPointNotEmptyError
parent.nodes.remove(destination)
directory = file_system.get_node('/')
directory.name = name
directory.is_file_system = True
parent.nodes.append(directory)
def unmount(self, path):
destination, name = self._split_path(path)
file_system = self.get_node(path)
parent = self.get_node(destination)
if not file_system.is_file_system:
raise NotAMountpointError
parent.nodes.remove(file_system)
parent.nodes.append(Directory(name))
def _split_path(self, path):
destination, name = tuple(path.rsplit('/', 1))
if not destination:
destination = '/'
return (destination, name)