Source code for norfs.fs.memory

import traceback

from collections import deque
from typing import (
    Dict,
    Iterable,
    List,
    Optional,
)

from norfs.fs.base import (
    BaseFileSystem,
    FSObjectPath,
    FSObjectType,
    FileSystemOperationError,
    NotAFileError,
    Path,
)
from norfs.permissions import Policy


[docs]class MemoryDirectory: _subdirs: Dict[str, 'MemoryDirectory'] _files: Dict[str, 'MemoryFile'] def __init__(self) -> None: self._subdirs = {} self._files = {}
[docs] def list_dirs(self) -> List[str]: return list(self._subdirs.keys())
[docs] def list_files(self) -> List[str]: return list(self._files.keys())
[docs] def put_dir(self, name: str, dir_: 'MemoryDirectory') -> None: self._subdirs[name] = dir_
[docs] def put_file(self, name: str, file_: 'MemoryFile') -> None: self._files[name] = file_
[docs] def get_dir(self, name: str) -> 'MemoryDirectory': try: return self._subdirs[name] except KeyError: raise NotADirectoryError()
[docs] def get_file(self, name: str) -> 'MemoryFile': try: return self._files[name] except KeyError: raise NotAFileError()
[docs] def remove_dir(self, name: str) -> None: try: del self._subdirs[name] except KeyError: raise NotADirectoryError()
[docs] def remove_file(self, name: str) -> None: try: del self._files[name] except KeyError: raise NotADirectoryError()
[docs]class MemoryFile: _contents: bytes def __init__(self, contents: bytes) -> None: self._contents = contents @property def contents(self) -> bytes: return self._contents
[docs]class MemoryFileSystem(BaseFileSystem): _root: MemoryDirectory _separator: str def __init__(self, root: MemoryDirectory, *, separator: str="/") -> None: self._root = root self._separator = separator def _get_dir(self, path: Path) -> MemoryDirectory: current_dir: MemoryDirectory = self._root for dir_name in path.tail: current_dir = current_dir.get_dir(dir_name) return current_dir # General operations
[docs] def parse_path(self, path: str) -> Path: tail: List[str] = path.split(self._separator) return Path("", *tail)
[docs] def path_exists(self, path: Path) -> bool: try: parent_dir: MemoryDirectory = self._get_dir(path.parent) except NotADirectoryError: return False else: return path.basename in (parent_dir.list_dirs() + parent_dir.list_files())
[docs] def path_to_string(self, path: Path) -> str: return self._separator.join(path.tail)
[docs] def path_to_uri(self, path: Path) -> str: return f"memory://{self.path_to_string(path)}"
# File operations
[docs] def file_read(self, path: Path) -> bytes: parent_dir: MemoryDirectory try: parent_dir = self._get_dir(path.parent) return parent_dir.get_file(path.basename).contents except (NotADirectoryError, NotAFileError): raise FileSystemOperationError(traceback.format_exc())
[docs] def file_write(self, path: Path, content: bytes) -> None: parent_dir: MemoryDirectory = self._root dir_name: str new_dir: MemoryDirectory queue = deque(path.parent.tail) while queue: dir_name = queue.popleft() try: parent_dir = parent_dir.get_dir(dir_name) except NotADirectoryError: new_dir = MemoryDirectory() parent_dir.put_dir(dir_name, new_dir) parent_dir = new_dir break while queue: dir_name = queue.popleft() new_dir = MemoryDirectory() parent_dir.put_dir(dir_name, new_dir) parent_dir = new_dir parent_dir.put_file(path.basename, MemoryFile(content))
[docs] def file_remove(self, path: Path) -> None: try: parent_dir: MemoryDirectory = self._get_dir(path.parent) parent_dir.remove_file(path.basename) except (NotADirectoryError, NotAFileError): raise FileSystemOperationError(traceback.format_exc())
[docs] def file_set_perms(self, path: Path, policies: List[Policy]) -> None: """ Has no effect. MemoryFileSystem has no concept of permissions. """ ...
[docs] def file_set_properties(self, path: Path, content_type: Optional[str] = None, tags: Optional[Dict[str, str]] = None, metadata: Optional[Dict[str, str]] = None) -> None: """ Has no effect. """ ...
# Directory operations
[docs] def dir_list(self, path: Path) -> Iterable[FSObjectPath]: files: List[Path] dirs: List[Path] current_dir: MemoryDirectory try: current_dir = self._get_dir(path) except NotADirectoryError: pass else: for file_ in current_dir.list_files(): yield FSObjectPath(FSObjectType.FILE, path.child(file_)) for dir_ in current_dir.list_dirs(): yield FSObjectPath(FSObjectType.DIR, path.child(dir_))
[docs] def dir_remove(self, path: Path) -> None: try: current_dir: MemoryDirectory = self._get_dir(path.parent) current_dir.remove_dir(path.basename) except NotADirectoryError: raise FileSystemOperationError(traceback.format_exc())
def __repr__(self) -> str: return f"{self.__class__.__name__}(root={self._root})"