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

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

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

Резултати

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

Код

class FileSystemError(RuntimeError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class SourceNodeDoesNotExistError(FileSystemError):
pass
class DestinationNodeDoesNotExistError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NotADirectoryError(FileSystemError):
pass
hard_links = {}
class Node:
def __init__(self, name, content='',
link_path=None, filesystem=None):
self.data = content
self.name = name
self.link_path = link_path
self.filesystem = filesystem
@property
def content(self):
if self.link_path:
return self.filesystem.get_node(self.link_path).content
else:
return self.data
@property
def directories(self):
if self.link_path:
try:
link_node = self.filesystem.get_node(self.link_path)
except NodeDoesNotExistError:
raise LinkPathError
return link_node.directories
else:
return self.child_directories
@property
def files(self):
if self.link_path:
try:
link_node = self.filesystem.get_node(self.link_path)
except NodeDoesNotExistError:
raise LinkPathError
return link_node.files
else:
return self.child_files
@property
def nodes(self):
return self.directories + self.files
class File(Node):
is_directory = False
def __init__(self, name, content='', link_path=None, filesystem=None):
Node.__init__(self, name, content, link_path, filesystem=filesystem)
def size(self):
return len(self.content) + 1
class Directory(Node):
is_directory = True
mounted = None
def __init__(self, name, filesystem=None):
Node.__init__(self, name, filesystem=filesystem)
self.child_directories = []
self.child_files = []
def find_by_path(self, path):
if '/' in path:
parent_dir = path.split('/', 1)[0]
basename = path.split('/', 1)[1]
for dir in self.directories:
if dir.name == parent_dir:
if dir.mounted:
return dir.mounted.root.find_by_path(basename)
else:
return dir.find_by_path(basename)
else:
for node in self.nodes:
if node.name == path:
if node.is_directory and node.mounted:
return node.mounted.root
else:
return node
raise NodeDoesNotExistError
def find_by_name(self, name):
for node in self.nodes:
if node.name == name:
return node
return None
def delete(self, name):
node = self.find_by_name(name)
if node.is_directory:
self.child_directories.remove(node)
else:
self.child_files.remove(node)
def measure_size(self):
size = 0
for node in self.nodes:
if node.is_directory:
size += 1 + node.measure_size()
else:
size += node.size()
return size
class FileSystem:
def __init__(self, size):
self.size, self.available_size = size, size - 1
self.root = Directory('/')
def get_node(self, path):
if path == '/' or not path:
return self.root
else:
return self.root.find_by_path(path[1:])
def create(self, path, directory=False, content=''):
parent_dir, name = path.rsplit('/', 1)
size = len(content) + 1
try:
if(parent_dir):
node = self.get_node(parent_dir)
else:
node = self.root
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if node.is_directory:
if node.find_by_name(name):
raise DestinationNodeExistsError
else:
if self.available_size < size:
raise NotEnoughSpaceError
else:
if(directory):
node.child_directories.append(
Directory(name, filesystem=self))
else:
node.child_files.append(
File(name, content, filesystem=self))
self.available_size -= size
else:
raise NotADirectoryError
def remove(self, path, directory=False, force=True):
node = self.get_node(path)
parent_dir, name = path.rsplit('/', 1)
if(node.is_directory):
if not directory:
raise NonExplicitDirectoryDeletionError
else:
if node.nodes:
if force:
dir = self.get_node(parent_dir)
self.available_size += dir.measure_size()
dir.delete(name)
else:
raise NonEmptyDirectoryDeletionError
else:
self.available_size += 1
self.get_node(parent_dir).delete(name)
else:
if(hard_links[node] > 0):
self.available_size += 1
hard_links[node] -= 1
else:
self.available_size += node.size()
self.get_node(parent_dir).delete(name)
def move(self, source, destination):
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
source_parent, node_name = source.rsplit('/', 1)
try:
destination_dir = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if not destination_dir.is_directory:
raise DestinationNotADirectoryError
if destination_dir.find_by_name(node_name):
raise DestinationNodeExistsError
if source_node.is_directory:
destination_dir.child_directories.append(source_node)
self.get_node(
source_parent
).child_directories.remove(source_node)
else:
destination_dir.files.append(source_node)
self.get_node(source_parent).child_files.remove(source_node)
def link(self, source, destination, symbolic=True):
if symbolic:
source_node = self.get_node(source)
self.create(destination)
self.get_node(destination).link_path = source
else:
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
if source_node.is_directory:
raise DirectoryHardLinkError
if self.available_size > 0:
content = source_node.content
parent, name = destination.rsplit('/', 1)
parent_node = self.get_node(parent)
parent_node.child_files.append(File(
name, content=content, filesystem=self))
hard_links[content] += 1
available_size -= 1
else:
raise NotEnoughSpaceError
def mount(self, file_system, path):
try:
path_node = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if not path_node.is_directory:
raise MountPointNotADirectoryError
if path_node.nodes:
raise MountPointNotEmptyError
path_node.mounted = file_system
def unmount(self, path):
self.get_node(path)
parent, name = path.rsplit('/', 1)
path_node = self.get_node(parent)
for node in path_node.nodes:
if node.name == name:
if not node.mounted:
raise NotAMountpointError
else:
node.mounted = None

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

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

======================================================================
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_hard_link_space_consumption (test.TestFileSystem)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib/language/python/runner.py", line 65, in thread
    raise TimeoutError
TimeoutError

======================================================================
ERROR: test_hard_link_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_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_file (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 18.215s

FAILED (errors=9)

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

Диана обнови решението на 29.04.2015 16:33 (преди почти 9 години)

+class FileSystemError(RuntimeError):
+ pass
+
+
+class NodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class SourceDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
+ pass
+
+
+class DestinationNodeExistsError(FileSystemError):
+ pass
+
+
+class FileSystemMountError(FileSystemError):
+ pass
+
+
+class MountPointDoesNotExistError(FileSystemMountError):
+ pass
+
+
+class MountPointNotADirectoryError(FileSystemMountError):
+ pass
+
+
+class MountPointNotEmptyError(FileSystemMountError):
+ pass
+
+
+class NotEnoughSpaceError(FileSystemError):
+ pass
+
+
+class NonEmptyDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NonExplicitDirectoryDeletionError(FileSystemError):
+ pass
+
+
+class NotDirectoryError(FileSystemError):
+ pass
+
+
+class Node:
+ def __init__(self, name, content=''):
+ self.content = content
+ self.name = name
+
+
+class File(Node):
+ is_directory = False
+
+ def __init__(self, name, content=''):
+ Node.__init__(self, name, content)
+
+
+class Directory(Node):
+ is_directory = True
+
+ def __init__(self, name):
+ Node.__init__(self, name)
+ self.directories = []
+ self.files = []
+
+ def find_by_path(self, path):
+ if '/' in path:
+ parent_dir = path.split('/', 1)[0]
+ basename = path.split('/', 1)[1]
+ for dir in self.directories:
+ if dir.name == parent_dir:
+ return dir.find_by_path(basename)
+ else:
+ for node in self.nodes:
+ if node.name == path:
+ return node
+ raise NodeDoesNotExistError
+
+ def find_by_name(self, name):
+ for node in self.nodes:
+ if node.name == name:
+ return node
+ return None
+
+ def delete(self, name):
+ node = self.find_by_name(name)
+ if node.is_directory:
+ self.directories.remove(node)
+ else:
+ self.files.remove(node)
+
+ @property
+ def nodes(self):
+ return self.directories + self.files
+
+
+class FileSystem:
+ def __init__(self, size):
+ self.size, self.available_size = size, size - 1
+ self.root = Directory('/')
+
+ def get_node(self, path):
+ if path:
+ return self.root.find_by_path(path[1:])
+ else:
+ return self.root
+
+ def create(self, path, directory=False, content=''):
+ parent_dir = path.rsplit('/', 1)[0]
+ name = path.rsplit('/', 1)[1]
+ size = len(content) + 1
+ try:
+ if(parent_dir):
+ node = self.get_node(parent_dir)
+ else:
+ node = self.root
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+ if node.is_directory:
+ if node.find_by_name(name):
+ raise DestinationNodeExistsError
+ else:
+ if self.available_size < size:
+ raise NotEnoughSpaceError
+ else:
+ if(directory):
+ node.directories.append(Directory(name))
+ else:
+ node.files.append(File(name, content))
+ self.available_size -= size
+ else:
+ raise NotDirectoryError
+
+ def remove(self, path, directory=False, force=True):
+ node = self.get_node(path)
+ parent_dir = path.rsplit('/', 1)[0]
+ name = path.rsplit('/', 1)[1]
+ if(node.is_directory):
+ if not directory:
+ raise NonExplicitDirectoryDeletionError
+ else:
+ if node.nodes:
+ if force:
+ self.get_node(parent_dir).delete(name)
+ else:
+ raise NonEmptyDirectoryDeletionError
+ else:
+ self.get_node(parent_dir).delete(name)
+
+ else:
+ self.get_node(parent_dir).delete(name)

Диана обнови решението на 29.04.2015 17:48 (преди почти 9 години)

class FileSystemError(RuntimeError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
+class SourceNodeDoesNotExistError(FileSystemError):
+ pass
+
+
+class DestinationNodeDoesNotExistError(FileSystemError):
+ pass
+
+
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
-class NotDirectoryError(FileSystemError):
+class DestinationNotADirectoryError(FileSystemError):
pass
+class NotADirectoryError(FileSystemError):
+ pass
+
+
class Node:
def __init__(self, name, content=''):
self.content = content
self.name = name
class File(Node):
is_directory = False
def __init__(self, name, content=''):
Node.__init__(self, name, content)
+ def size(self):
+ return len(self.content) + 1
+
class Directory(Node):
is_directory = True
def __init__(self, name):
Node.__init__(self, name)
self.directories = []
self.files = []
def find_by_path(self, path):
if '/' in path:
parent_dir = path.split('/', 1)[0]
basename = path.split('/', 1)[1]
for dir in self.directories:
if dir.name == parent_dir:
return dir.find_by_path(basename)
else:
for node in self.nodes:
if node.name == path:
return node
raise NodeDoesNotExistError
def find_by_name(self, name):
for node in self.nodes:
if node.name == name:
return node
return None
def delete(self, name):
node = self.find_by_name(name)
if node.is_directory:
self.directories.remove(node)
else:
self.files.remove(node)
+ def measure_size(self):
+ size = 0
+ for node in self.nodes:
+ if node.is_directory:
+ size += 1 + node.measure_size()
+ else:
+ size += node.size()
+ return size
+
@property
def nodes(self):
return self.directories + self.files
class FileSystem:
def __init__(self, size):
self.size, self.available_size = size, size - 1
self.root = Directory('/')
def get_node(self, path):
if path:
return self.root.find_by_path(path[1:])
else:
return self.root
def create(self, path, directory=False, content=''):
- parent_dir = path.rsplit('/', 1)[0]
- name = path.rsplit('/', 1)[1]
+ parent_dir, name = path.rsplit('/', 1)
size = len(content) + 1
try:
if(parent_dir):
node = self.get_node(parent_dir)
else:
node = self.root
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if node.is_directory:
if node.find_by_name(name):
raise DestinationNodeExistsError
else:
if self.available_size < size:
raise NotEnoughSpaceError
else:
if(directory):
node.directories.append(Directory(name))
else:
node.files.append(File(name, content))
self.available_size -= size
else:
- raise NotDirectoryError
+ raise NotADirectoryError
def remove(self, path, directory=False, force=True):
node = self.get_node(path)
- parent_dir = path.rsplit('/', 1)[0]
- name = path.rsplit('/', 1)[1]
+ parent_dir, name = path.rsplit('/', 1)
if(node.is_directory):
if not directory:
raise NonExplicitDirectoryDeletionError
else:
if node.nodes:
if force:
- self.get_node(parent_dir).delete(name)
+ dir = self.get_node(parent_dir)
+ self.available_size += dir.measure_size()
+ dir.delete(name)
else:
raise NonEmptyDirectoryDeletionError
else:
+ self.available_size += 1
self.get_node(parent_dir).delete(name)
else:
+ self.available_size += node.size()
self.get_node(parent_dir).delete(name)
+
+ def move(self, source, destination):
+ try:
+ source_node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+ source_parent, node_name = source.rsplit('/', 1)
+ try:
+ destination_dir = self.get_node(destination)
+ except NodeDoesNotExistError:
+ raise DestinationNodeDoesNotExistError
+ if not destination_dir.is_directory:
+ raise DestinationNotADirectoryError
+ if destination_dir.find_by_name(node_name):
+ raise DestinationNodeExistsError
+ if source_node.is_directory:
+ destination_dir.directories.append(source_node)
+ self.get_node(source_parent).directories.remove(source_node)
+
+ else:
+ destination_dir.files.append(source_node)
+ self.get_node(source_parent).files.remove(source_node)

Диана обнови решението на 30.04.2015 15:24 (преди почти 9 години)

class FileSystemError(RuntimeError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
+class NotAMountpointError(FileSystemMountError):
+ pass
+
+
class MountPointNotEmptyError(FileSystemMountError):
pass
+class DirectoryHardLinkError(FileSystemError):
+ pass
+
+
class NotEnoughSpaceError(FileSystemError):
pass
class SourceNodeDoesNotExistError(FileSystemError):
pass
class DestinationNodeDoesNotExistError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NotADirectoryError(FileSystemError):
pass
class Node:
- def __init__(self, name, content=''):
- self.content = content
+ def __init__(self, name, content='',
+ link_path=None, filesystem=None):
+ self.data = content
self.name = name
+ self.link_path = link_path
+ self.filesystem = filesystem
+ @property
+ def content(self):
+ if self.link_path:
+ return self.filesystem.get_node(self.link_path).content
+ else:
+ return self.data
+ @property
+ def directories(self):
+ if self.link_path:
+ try:
+ link_node = self.filesystem.get_node(self.link_path)
+ except NodeDoesNotExistError:
+ raise LinkPathError
+ return link_node.directories
+ else:
+ return self.child_directories
+
+ @property
+ def files(self):
+ if self.link_path:
+ try:
+ link_node = self.filesystem.get_node(self.link_path)
+ except NodeDoesNotExistError:
+ raise LinkPathError
+ return link_node.files
+ else:
+ return self.child_files
+
+ @property
+ def nodes(self):
+ return self.directories + self.files
+
+
class File(Node):
is_directory = False
- def __init__(self, name, content=''):
- Node.__init__(self, name, content)
+ def __init__(self, name, content='', link_path=None, filesystem=None):
+ Node.__init__(self, name, content, link_path, filesystem=filesystem)
def size(self):
return len(self.content) + 1
class Directory(Node):
is_directory = True
+ mounted = None
- def __init__(self, name):
- Node.__init__(self, name)
- self.directories = []
- self.files = []
+ def __init__(self, name, filesystem=None):
+ Node.__init__(self, name, filesystem=filesystem)
+ self.child_directories = []
+ self.child_files = []
def find_by_path(self, path):
if '/' in path:
parent_dir = path.split('/', 1)[0]
basename = path.split('/', 1)[1]
for dir in self.directories:
if dir.name == parent_dir:
- return dir.find_by_path(basename)
+ if dir.mounted:
+ return dir.mounted.root.find_by_path(basename)
+ else:
+ return dir.find_by_path(basename)
else:
for node in self.nodes:
if node.name == path:
- return node
+ if node.is_directory and node.mounted:
+ return node.mounted.root
+ else:
+ return node
raise NodeDoesNotExistError
def find_by_name(self, name):
for node in self.nodes:
if node.name == name:
return node
return None
def delete(self, name):
node = self.find_by_name(name)
if node.is_directory:
- self.directories.remove(node)
+ self.child_directories.remove(node)
else:
- self.files.remove(node)
+ self.child_files.remove(node)
def measure_size(self):
size = 0
for node in self.nodes:
if node.is_directory:
size += 1 + node.measure_size()
else:
size += node.size()
return size
- @property
- def nodes(self):
- return self.directories + self.files
-
class FileSystem:
def __init__(self, size):
self.size, self.available_size = size, size - 1
self.root = Directory('/')
def get_node(self, path):
- if path:
- return self.root.find_by_path(path[1:])
- else:
+ if path == '/' or not path:
return self.root
+ else:
+ return self.root.find_by_path(path[1:])
def create(self, path, directory=False, content=''):
parent_dir, name = path.rsplit('/', 1)
size = len(content) + 1
try:
if(parent_dir):
node = self.get_node(parent_dir)
else:
node = self.root
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if node.is_directory:
if node.find_by_name(name):
raise DestinationNodeExistsError
else:
if self.available_size < size:
raise NotEnoughSpaceError
else:
if(directory):
- node.directories.append(Directory(name))
+ node.child_directories.append(
+ Directory(name, filesystem=self))
else:
- node.files.append(File(name, content))
+ node.child_files.append(
+ File(name, content, filesystem=self))
self.available_size -= size
else:
raise NotADirectoryError
def remove(self, path, directory=False, force=True):
node = self.get_node(path)
parent_dir, name = path.rsplit('/', 1)
if(node.is_directory):
if not directory:
raise NonExplicitDirectoryDeletionError
else:
if node.nodes:
if force:
dir = self.get_node(parent_dir)
self.available_size += dir.measure_size()
dir.delete(name)
else:
raise NonEmptyDirectoryDeletionError
else:
self.available_size += 1
self.get_node(parent_dir).delete(name)
else:
self.available_size += node.size()
self.get_node(parent_dir).delete(name)
def move(self, source, destination):
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
source_parent, node_name = source.rsplit('/', 1)
try:
destination_dir = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if not destination_dir.is_directory:
raise DestinationNotADirectoryError
if destination_dir.find_by_name(node_name):
raise DestinationNodeExistsError
if source_node.is_directory:
- destination_dir.directories.append(source_node)
- self.get_node(source_parent).directories.remove(source_node)
+ destination_dir.child_directories.append(source_node)
+ self.get_node(
+ source_parent
+ ).child_directories.remove(source_node)
else:
destination_dir.files.append(source_node)
- self.get_node(source_parent).files.remove(source_node)
+ self.get_node(source_parent).child_files.remove(source_node)
+
+ def link(self, source, destination, symbolic=True):
+ if symbolic:
+ source_node = self.get_node(source)
+ self.create(destination)
+ self.get_node(destination).link_path = source
+ else:
+ try:
+ source_node = self.get_node(source)
+ except NodeDoesNotExistError:
+ raise SourceNodeDoesNotExistError
+ if source_node.is_directory:
+ raise DirectoryHardLinkError
+
+ def mount(self, file_system, path):
+ try:
+ path_node = self.get_node(path)
+ except NodeDoesNotExistError:
+ raise MountPointDoesNotExistError
+ if not path_node.is_directory:
+ raise MountPointNotADirectoryError
+ if path_node.nodes:
+ raise MountPointNotEmptyError
+ path_node.mounted = file_system
+
+ def unmount(self, path):
+ self.get_node(path)
+ parent, name = path.rsplit('/', 1)
+ path_node = self.get_node(parent)
+ for node in path_node.nodes:
+ if node.name == name:
+ if not node.mounted:
+ raise NotAMountpointError
+ else:
+ node.mounted = None

Диана обнови решението на 30.04.2015 16:57 (преди почти 9 години)

class FileSystemError(RuntimeError):
pass
class NodeDoesNotExistError(FileSystemError):
pass
class SourceDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeDoesNotExistError(NodeDoesNotExistError):
pass
class DestinationNodeExistsError(FileSystemError):
pass
class FileSystemMountError(FileSystemError):
pass
class MountPointDoesNotExistError(FileSystemMountError):
pass
class MountPointNotADirectoryError(FileSystemMountError):
pass
class NotAMountpointError(FileSystemMountError):
pass
class MountPointNotEmptyError(FileSystemMountError):
pass
class DirectoryHardLinkError(FileSystemError):
pass
class NotEnoughSpaceError(FileSystemError):
pass
class SourceNodeDoesNotExistError(FileSystemError):
pass
class DestinationNodeDoesNotExistError(FileSystemError):
pass
class NonEmptyDirectoryDeletionError(FileSystemError):
pass
class NonExplicitDirectoryDeletionError(FileSystemError):
pass
class DestinationNotADirectoryError(FileSystemError):
pass
class NotADirectoryError(FileSystemError):
pass
+hard_links = {}
class Node:
def __init__(self, name, content='',
link_path=None, filesystem=None):
self.data = content
self.name = name
self.link_path = link_path
self.filesystem = filesystem
@property
def content(self):
if self.link_path:
return self.filesystem.get_node(self.link_path).content
else:
return self.data
@property
def directories(self):
if self.link_path:
try:
link_node = self.filesystem.get_node(self.link_path)
except NodeDoesNotExistError:
raise LinkPathError
return link_node.directories
else:
return self.child_directories
@property
def files(self):
if self.link_path:
try:
link_node = self.filesystem.get_node(self.link_path)
except NodeDoesNotExistError:
raise LinkPathError
return link_node.files
else:
return self.child_files
@property
def nodes(self):
return self.directories + self.files
class File(Node):
is_directory = False
def __init__(self, name, content='', link_path=None, filesystem=None):
Node.__init__(self, name, content, link_path, filesystem=filesystem)
def size(self):
return len(self.content) + 1
class Directory(Node):
is_directory = True
mounted = None
def __init__(self, name, filesystem=None):
Node.__init__(self, name, filesystem=filesystem)
self.child_directories = []
self.child_files = []
def find_by_path(self, path):
if '/' in path:
parent_dir = path.split('/', 1)[0]
basename = path.split('/', 1)[1]
for dir in self.directories:
if dir.name == parent_dir:
if dir.mounted:
return dir.mounted.root.find_by_path(basename)
else:
return dir.find_by_path(basename)
else:
for node in self.nodes:
if node.name == path:
if node.is_directory and node.mounted:
return node.mounted.root
else:
return node
raise NodeDoesNotExistError
def find_by_name(self, name):
for node in self.nodes:
if node.name == name:
return node
return None
def delete(self, name):
node = self.find_by_name(name)
if node.is_directory:
self.child_directories.remove(node)
else:
self.child_files.remove(node)
def measure_size(self):
size = 0
for node in self.nodes:
if node.is_directory:
size += 1 + node.measure_size()
else:
size += node.size()
return size
class FileSystem:
def __init__(self, size):
self.size, self.available_size = size, size - 1
self.root = Directory('/')
def get_node(self, path):
if path == '/' or not path:
return self.root
else:
return self.root.find_by_path(path[1:])
def create(self, path, directory=False, content=''):
parent_dir, name = path.rsplit('/', 1)
size = len(content) + 1
try:
if(parent_dir):
node = self.get_node(parent_dir)
else:
node = self.root
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if node.is_directory:
if node.find_by_name(name):
raise DestinationNodeExistsError
else:
if self.available_size < size:
raise NotEnoughSpaceError
else:
if(directory):
node.child_directories.append(
Directory(name, filesystem=self))
else:
node.child_files.append(
File(name, content, filesystem=self))
self.available_size -= size
else:
raise NotADirectoryError
def remove(self, path, directory=False, force=True):
node = self.get_node(path)
parent_dir, name = path.rsplit('/', 1)
if(node.is_directory):
if not directory:
raise NonExplicitDirectoryDeletionError
else:
if node.nodes:
if force:
dir = self.get_node(parent_dir)
self.available_size += dir.measure_size()
dir.delete(name)
else:
raise NonEmptyDirectoryDeletionError
else:
self.available_size += 1
self.get_node(parent_dir).delete(name)
else:
- self.available_size += node.size()
+ if(hard_links[node] > 0):
+ self.available_size += 1
+ hard_links[node] -= 1
+ else:
+ self.available_size += node.size()
self.get_node(parent_dir).delete(name)
def move(self, source, destination):
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
source_parent, node_name = source.rsplit('/', 1)
try:
destination_dir = self.get_node(destination)
except NodeDoesNotExistError:
raise DestinationNodeDoesNotExistError
if not destination_dir.is_directory:
raise DestinationNotADirectoryError
if destination_dir.find_by_name(node_name):
raise DestinationNodeExistsError
if source_node.is_directory:
destination_dir.child_directories.append(source_node)
self.get_node(
source_parent
).child_directories.remove(source_node)
else:
destination_dir.files.append(source_node)
self.get_node(source_parent).child_files.remove(source_node)
def link(self, source, destination, symbolic=True):
if symbolic:
source_node = self.get_node(source)
self.create(destination)
self.get_node(destination).link_path = source
else:
try:
source_node = self.get_node(source)
except NodeDoesNotExistError:
raise SourceNodeDoesNotExistError
if source_node.is_directory:
raise DirectoryHardLinkError
+ if self.available_size > 0:
+ content = source_node.content
+ parent, name = destination.rsplit('/', 1)
+ parent_node = self.get_node(parent)
+ parent_node.child_files.append(File(
+ name, content=content, filesystem=self))
+ hard_links[content] += 1
+ available_size -= 1
+ else:
+ raise NotEnoughSpaceError
def mount(self, file_system, path):
try:
path_node = self.get_node(path)
except NodeDoesNotExistError:
raise MountPointDoesNotExistError
if not path_node.is_directory:
raise MountPointNotADirectoryError
if path_node.nodes:
raise MountPointNotEmptyError
path_node.mounted = file_system
def unmount(self, path):
self.get_node(path)
parent, name = path.rsplit('/', 1)
path_node = self.get_node(parent)
for node in path_node.nodes:
if node.name == name:
if not node.mounted:
raise NotAMountpointError
else:
node.mounted = None