typing and refactoring on the way
diff --git a/wally/storage.py b/wally/storage.py
new file mode 100644
index 0000000..5212f4a
--- /dev/null
+++ b/wally/storage.py
@@ -0,0 +1,122 @@
+"""
+This module contains interfaces for storage classes
+"""
+
+import abc
+from typing import Any, Iterable, TypeVar, Type, IO
+
+
+class IStorable(metaclass=abc.ABCMeta):
+ """Interface for type, which can be stored"""
+ @abc.abstractmethod
+ def __getstate__(self) -> Any:
+ pass
+
+ @abc.abstractmethod
+ def __setstate__(self, Any):
+ pass
+
+
+# all builtin types can be stored
+IStorable.register(list) # type: ignore
+IStorable.register(dict) # type: ignore
+IStorable.register(tuple) # type: ignore
+IStorable.register(set) # type: ignore
+IStorable.register(None) # type: ignore
+IStorable.register(int) # type: ignore
+IStorable.register(str) # type: ignore
+IStorable.register(bytes) # type: ignore
+IStorable.register(bool) # type: ignore
+
+
+ObjClass = TypeVar('ObjClass')
+
+
+class IStorage(metaclass=abc.ABCMeta):
+ """interface for storage"""
+ @abc.abstractmethod
+ def __init__(self, path: str, existing_storage: bool = False) -> None:
+ pass
+
+ @abc.abstractmethod
+ def __setitem__(self, path: str, value: IStorable) -> None:
+ pass
+
+ @abc.abstractmethod
+ def __getitem__(self, path: str) -> IStorable:
+ pass
+
+ @abc.abstractmethod
+ def __contains__(self, path: str) -> bool:
+ pass
+
+ @abc.abstractmethod
+ def list(self, path: str) -> Iterable[str]:
+ pass
+
+ @abc.abstractmethod
+ def load(self, path: str, obj_class: Type[ObjClass]) -> ObjClass:
+ pass
+
+ @abc.abstractmethod
+ def get_stream(self, path: str) -> IO:
+ pass
+
+
+class ISimpleStorage(metaclass=abc.ABCMeta):
+ """interface for low-level storage, which doesn't support serialization
+ and can operate only on bytes"""
+
+ @abc.abstractmethod
+ def __init__(self, path: str) -> None:
+ pass
+
+ @abc.abstractmethod
+ def __setitem__(self, path: str, value: bytes) -> None:
+ pass
+
+ @abc.abstractmethod
+ def __getitem__(self, path: str) -> bytes:
+ pass
+
+ @abc.abstractmethod
+ def __contains__(self, path: str) -> bool:
+ pass
+
+ @abc.abstractmethod
+ def list(self, path: str) -> Iterable[str]:
+ pass
+
+ @abc.abstractmethod
+ def get_stream(self, path: str) -> IO:
+ pass
+
+
+class ISerializer(metaclass=abc.ABCMeta):
+ """Interface for serialization class"""
+ @abc.abstractmethod
+ def pack(self, value: IStorable) -> bytes:
+ pass
+
+ @abc.abstractmethod
+ def unpack(self, data: bytes) -> IStorable:
+ pass
+
+
+# TODO(koder): this is concrete storage and serializer classes to be implemented
+class FSStorage(IStorage):
+ """Store all data in files on FS"""
+
+ @abc.abstractmethod
+ def __init__(self, root_path: str, serializer: ISerializer, existing: bool = False) -> None:
+ pass
+
+
+class YAMLSerializer(ISerializer):
+ """Serialize data to yaml"""
+ pass
+
+
+def make_storage(url: str, existing: bool = False) -> IStorage:
+ return FSStorage(url, YAMLSerializer(), existing)
+