# Path: featureflow/data.py
# class UuidProvider(IdProvider):
#     def __init__(self):
#         super(UuidProvider, self).__init__()
# 
#     def new_id(self, **kwargs):
#         return uuid4().hex
# 
# class StringDelimitedKeyBuilder(KeyBuilder):
#     def __init__(self, seperator=':'):
#         super(StringDelimitedKeyBuilder, self).__init__()
#         self._seperator = seperator
# 
#     def build(self, *args):
#         return self._seperator.join(str(x) for x in args)
# 
#     def decompose(self, composed):
#         return composed.split(self._seperator)
# 
# class InMemoryDatabase(Database):
#     def __init__(self, key_builder=None):
#         super(InMemoryDatabase, self).__init__(key_builder=key_builder)
#         self._dict = dict()
# 
#     def write_stream(self, key, content_type):
#         bio = BytesIO()
#         self._dict[key] = bio
# 
#         def hijacked_close():
#             bio.seek(0)
#             self._dict[key] = bio.read()
#             bio._old_close()
# 
#         bio._old_close = bio.close
#         bio.close = hijacked_close
#         return bio
# 
#     def read_stream(self, key):
#         return IOWithLength(self._dict[key])
# 
#     def size(self, key):
#         return len(self._dict[key])
# 
#     def iter_ids(self):
#         seen = set()
#         for key in list(self._dict.keys()):
#             _id, _, _ = self.key_builder.decompose(key)
#             if _id in seen:
#                 continue
#             yield _id
#             seen.add(_id)
# 
#     def __contains__(self, key):
#         return key in self._dict
# 
#     def __delitem__(self, key):
#         del self._dict[key]


from .data import UuidProvider, StringDelimitedKeyBuilder, InMemoryDatabase


class PersistenceSettings(object):
    id_provider = UuidProvider()
    key_builder = StringDelimitedKeyBuilder()
    database = InMemoryDatabase(key_builder=key_builder)

    @classmethod
    def clone(cls, id_provider=None, key_builder=None, database=None):
        ip = id_provider
        kb = key_builder
        db = database

        class Settings(PersistenceSettings):
            id_provider = ip or cls.id_provider
            key_builder = kb or cls.key_builder
            database = db or cls.database

        return Settings


def simple_in_memory_settings(cls):
    """
    Decorator that returns a class that "persists" data in-memory.  Mostly
     useful for testing
    :param cls: the class whose features should be persisted in-memory
    :return: A new class that will persist features in memory
    """

    class Settings(PersistenceSettings):

# Path: featureflow/data.py
# class UuidProvider(IdProvider):
#     def __init__(self):
#         super(UuidProvider, self).__init__()
# 
#     def new_id(self, **kwargs):
#         return uuid4().hex
# 
# class StringDelimitedKeyBuilder(KeyBuilder):
#     def __init__(self, seperator=':'):
#         super(StringDelimitedKeyBuilder, self).__init__()
#         self._seperator = seperator
# 
#     def build(self, *args):
#         return self._seperator.join(str(x) for x in args)
# 
#     def decompose(self, composed):
#         return composed.split(self._seperator)
# 
# class InMemoryDatabase(Database):
#     def __init__(self, key_builder=None):
#         super(InMemoryDatabase, self).__init__(key_builder=key_builder)
#         self._dict = dict()
# 
#     def write_stream(self, key, content_type):
#         bio = BytesIO()
#         self._dict[key] = bio
# 
#         def hijacked_close():
#             bio.seek(0)
#             self._dict[key] = bio.read()
#             bio._old_close()
# 
#         bio._old_close = bio.close
#         bio.close = hijacked_close
#         return bio
# 
#     def read_stream(self, key):
#         return IOWithLength(self._dict[key])
# 
#     def size(self, key):
#         return len(self._dict[key])
# 
#     def iter_ids(self):
#         seen = set()
#         for key in list(self._dict.keys()):
#             _id, _, _ = self.key_builder.decompose(key)
#             if _id in seen:
#                 continue
#             yield _id
#             seen.add(_id)
# 
#     def __contains__(self, key):
#         return key in self._dict
# 
#     def __delitem__(self, key):
#         del self._dict[key]


# Path: featureflow/persistence.py
from .data import UuidProvider, StringDelimitedKeyBuilder, InMemoryDatabase



class PersistenceSettings(object):
    id_provider = UuidProvider()
    key_builder = StringDelimitedKeyBuilder()
    database = InMemoryDatabase(key_builder=key_builder)

    @classmethod
    def clone(cls, id_provider=None, key_builder=None, database=None):
        ip = id_provider
        kb = key_builder
        db = database

        class Settings(PersistenceSettings):
            id_provider = ip or cls.id_provider
            key_builder = kb or cls.key_builder
            database = db or cls.database

        return Settings


def simple_in_memory_settings(cls):
    """
    Decorator that returns a class that "persists" data in-memory.  Mostly
     useful for testing
    :param cls: the class whose features should be persisted in-memory
    :return: A new class that will persist features in memory
    """

    class Settings(PersistenceSettings):

        id_provider = UuidProvider()