"""
File system directory oriented data store.
"""

import os
import shutil

from .base import BaseDataDirectory, BaseDataStream, MixInDataStoreFileSystem


def mkdirp(path):
    """Do ``mkdir -p {path}``"""
    if not os.path.isdir(path):
        os.makedirs(path)


class DataFile(MixInDataStoreFileSystem, BaseDataStream):

    def clear(self):
        self.stream = None
        os.remove(self.path)

    def exists(self):
        return os.path.exists(self.path)

    def open(self, *args, **kwds):
        self.stream = open(self.path, *args, **kwds)
        return self.stream


class DataDirectory(BaseDataDirectory):

    default_streamstore_type = DataFile

    def __init__(self, *args, **kwds):
        super(DataDirectory, self).__init__(*args, **kwds)
        mkdirp(self.path)

    def aspath(self, key):
        return os.path.join(self.path, key)

    def _listdir(self):
        return os.listdir(self.path)

    def __len__(self):
        return len(self._listdir())

    def __iter__(self):
        for key in self._listdir():
            if os.path.isdir(self.aspath(key)):
                yield key
            else:
                yield key

    def _del_store(self, key):
        path = self.aspath(key)
        if not os.path.exists(path):
            raise KeyError(
                'Key {0} (path: {1}) does not exist'.format(key, path))
        if os.path.isdir(path):
            shutil.rmtree(self.aspath(key))
        else:
            os.remove(path)

    def _get_store(self, key):
        path = self.aspath(key)
        if not os.path.exists(path):
            raise KeyError(key)
        if os.path.isdir(path):
            cls = self.default_substore_type or self.__class__
            return cls(path=path)
        else:
            return self.default_streamstore_type(path=path)

    def _set_store(self, key, value):
        path = self.aspath(key)
        if isinstance(value, BaseDataDirectory):
            mkdirp(path)
        elif isinstance(value, DataFile) and not os.path.exists(path):
            open(path, 'w').close()
        else:
            raise ValueError(
                'Value {0!r} is not supported data store type.'.format(value))

@@ -328,302 +328,1417 @@
     
-def clear(self):%0A        self.stream = None%0A        os.remove(self.path)%0A%0A    def exists(self):%0A        return os.path.exists(self.path)%0A%0A    def open(self, *args, **kwds):%0A        self.stream = open(self.path, *args, **kwds)%0A        return self.stream%0A%0A%0Aclass DataDirectory(BaseDataDirectory):
+%22%22%22%0A    File based stream data store.%0A%0A    %3E%3E%3E import tempfile%0A    %3E%3E%3E with tempfile.NamedTemporaryFile() as temp:%0A    ...     ds = DataFile(temp.name)%0A    ...     with ds.open('w') as f:%0A    ...         f.write('some data')%0A    ...     with ds.open() as f:%0A    ...         print f.read()%0A    some data%0A%0A    %22%22%22%0A%0A    def clear(self):%0A        self.stream = None%0A        os.remove(self.path)%0A%0A    def exists(self):%0A        return os.path.exists(self.path)%0A%0A    def open(self, *args, **kwds):%0A        self.stream = open(self.path, *args, **kwds)%0A        return self.stream%0A%0A%0Aclass DataDirectory(BaseDataDirectory):%0A%0A    %22%22%22%0A    Directory based nestable data store.%0A%0A    How to use file-type data store under :class:%60DataDirectory%60:%0A%0A    %3E%3E%3E from buildlet.utils.tempdir import TemporaryDirectory%0A    %3E%3E%3E with TemporaryDirectory() as tempdir:%0A    ...     ds = DataDirectory(tempdir)%0A    ...     ds_stream = ds.get_filestore('key')%0A    ...     with ds_stream.open('w') as f:%0A    ...         f.write('some data')%0A    ...     with ds_stream.open() as f:%0A    ...         print f.read()%0A    some data%0A%0A%0A    How to make nested data store:%0A%0A    %3E%3E%3E with TemporaryDirectory() as tempdir:%0A    ...     ds = DataDirectory(tempdir)%0A    ...     ds_nested = ds.get_substore('key')%0A    ...     print ds_nested                            # doctest: +ELLIPSIS%0A    %3Cbuildlet.datastore.directory.DataDirectory object at ...%3E%0A%0A    %22%22%22
 %0A%0A  

Add doctests for DataDirectory and DataFile