# Path: neurotools/datastore/interface.py
# class AbstractDataStore(object):
#     """
#     Abstract base class for a persistent data store.
#     """
#     
#     def retrieve(self, component, attribute_name):
#         """
#         Retrieve data belonging to a component.
#         
#         The component must have the following attributes:
#           `parameters`: a `neurotools` `ParameterSet` object
#           `input`: another component, or None
#           `full_type`: the object class and module
#           `version`: the source-code version
#         """
#         # construct a way to get the data if it exists
#         # e.g. create a unique key, an SQL query
#         # this will involve getting a key or something
#         # for the input object
#         # try to get the data
#         # if the data exists,
#         #  return it
#         # else
#         #  return None
#         raise NotImplemented()
# 
#     def store(self, component, attribute_name, data):
#         """
#         Store data belonging to a component.
#         
#         The component must have the following attributes:
#           `parameters`: a `neurotools` `ParameterSet` object
#           `input`: another component, or None
#           `full_type`: the object class and module
#           `version`: the source-code version
#         """
#         # check we know how to handle the data type
#         # construct a way to store the data, e.g. create a unique key,
#         # an SQL query, etc
#         # store the data
#         # possibly we could check if data already exists, and raise an Exception if
#         # it is different to the new data (should probably be a flag to control this,
#         # because it might be heavyweight
#         raise NotImplemented()


from neurotools.datastore.interface import AbstractDataStore
from neurotools.datastore.keygenerators import join_with_underscores
import os.path, shelve
import logging
    def __init__(self, root_dir, key_generator=join_with_underscores):
        """
        `root_dir` is a filesystem directory below which all shelve files
        will be saved.
        `key_generator` is a function that accepts a mapping and returns a string.
        """
        if os.path.exists(root_dir):
            if not os.path.isdir(root_dir): # should also test if the directory is readable/writeable
                raise Exception("The supplied root_dir exists but is not a directory.")
        else:
            os.mkdir(root_dir)
        self._root_dir = root_dir
        self._generate_key = key_generator
    
    def retrieve(self, component, attribute_name):
        __doc__ = AbstractDataStore.retrieve.__doc__
        storage_key = self._generate_key(component)
        path = os.path.join(self._root_dir, storage_key+".shelf")
        if os.path.exists(path):
            shelf = shelve.open(path, flag='r') # 'r' means read-only
            if attribute_name in shelf:
                data = shelf[attribute_name]
            else:
                data = None
            shelf.close()
            return data
        else:
            return None

    def store(self, component, attribute_name, data):

# Path: neurotools/datastore/interface.py
# class AbstractDataStore(object):
#     """
#     Abstract base class for a persistent data store.
#     """
#     
#     def retrieve(self, component, attribute_name):
#         """
#         Retrieve data belonging to a component.
#         
#         The component must have the following attributes:
#           `parameters`: a `neurotools` `ParameterSet` object
#           `input`: another component, or None
#           `full_type`: the object class and module
#           `version`: the source-code version
#         """
#         # construct a way to get the data if it exists
#         # e.g. create a unique key, an SQL query
#         # this will involve getting a key or something
#         # for the input object
#         # try to get the data
#         # if the data exists,
#         #  return it
#         # else
#         #  return None
#         raise NotImplemented()
# 
#     def store(self, component, attribute_name, data):
#         """
#         Store data belonging to a component.
#         
#         The component must have the following attributes:
#           `parameters`: a `neurotools` `ParameterSet` object
#           `input`: another component, or None
#           `full_type`: the object class and module
#           `version`: the source-code version
#         """
#         # check we know how to handle the data type
#         # construct a way to store the data, e.g. create a unique key,
#         # an SQL query, etc
#         # store the data
#         # possibly we could check if data already exists, and raise an Exception if
#         # it is different to the new data (should probably be a flag to control this,
#         # because it might be heavyweight
#         raise NotImplemented()


# Path: neurotools/datastore/shelve_ds.py
from neurotools.datastore.interface import AbstractDataStore
from neurotools.datastore.keygenerators import join_with_underscores
import os.path, shelve
import logging

    def __init__(self, root_dir, key_generator=join_with_underscores):
        """
        `root_dir` is a filesystem directory below which all shelve files
        will be saved.
        `key_generator` is a function that accepts a mapping and returns a string.
        """
        if os.path.exists(root_dir):
            if not os.path.isdir(root_dir): # should also test if the directory is readable/writeable
                raise Exception("The supplied root_dir exists but is not a directory.")
        else:
            os.mkdir(root_dir)
        self._root_dir = root_dir
        self._generate_key = key_generator
    
    def retrieve(self, component, attribute_name):
        __doc__ = AbstractDataStore.retrieve.__doc__
        storage_key = self._generate_key(component)
        path = os.path.join(self._root_dir, storage_key+".shelf")
        if os.path.exists(path):
            shelf = shelve.open(path, flag='r') # 'r' means read-only
            if attribute_name in shelf:
                data = shelf[attribute_name]
            else:
                data = None
            shelf.close()
            return data
        else:
            return None

    def store(self, component, attribute_name, data):

        __doc__ = AbstractDataStore.store.__doc__