class PfTestBase(object):
    """Base class for generated sql and non-sql test cases."""
    pass class BaseData(object):
    """Base class for handling processed data.

    In general, specialised subclasses of BaseData will be used
    to handle processed data rather than BaseData itself.

    Usage: ..........
    """
    __metaclass__ = MetaMethods

    def __init__(self):
        self.meta = PfMetaData()
        self.history = "%s > New %s" %(datetime.now(), self.__class__.__name__)
        if not hasattr(self, 'channels'):
            self.channels = ChannelList()
        
    def save(self):
        if pyfusion.orm_manager.IS_ACTIVE:
            # this may be inefficient: get it working, then get it fast
            self.channels.save()
            session = pyfusion.orm_manager.Session()
            session.add(self)
            session.commit()
            session.close() class BaseAcquisition(object):
    """Base class for datasystem specific acquisition classes.

    :param   config_name:  name   of  acquisition   as  specified in\
    configuration file.

    On  instantiation,  the pyfusion  configuration  is  searched for  a
    ``[Acquisition:config_name]``   section.    The   contents  of   the
    configuration  section are  loaded into  the object  namespace.  For
    example, a configuration section::

      [Acquisition:my_custom_acq]
      acq_class = pyfusion.acquisition.base.BaseAcquisition
      server = my.dataserver.com
 
    will result in the following behaviour::

     >>> from pyfusion.acquisition.base import BaseAcquisition
     >>> my_acq = BaseAcquisition('my_custom_acq')
     >>> print(my_acq.server)
     my.dataserver.com

    The configuration entries can be overridden with keyword arguments::

     >>> my_other_acq = BaseAcquisition('my_custom_acq', server='your.data.net')
     >>> print(my_other_acq.server)
     your.data.net

    """
    def __init__(self, config_name=None, **kwargs):
        if config_name != None:
            self.__dict__.update(get_config_as_dict('Acquisition', config_name))
        self.__dict__.update(kwargs)

    def getdata(self, shot, config_name=None, **kwargs):
        """Get the data and return prescribed subclass of BaseData.
        
        :param shot: shot number
        :param config_name: name of a fetcher class in the configuration file
        :returns: an instance of a subclass of \
        :py:class:`~pyfusion.data.base.BaseData` or \
        :py:class:`~pyfusion.data.base.BaseDataSet`

        This method needs to know which  data fetcher class to use, if a
        config_name      argument     is      supplied      then     the
        ``[Diagnostic:config_name]``   section   must   exist   in   the
        configuration   file  and   contain  a   ``data_fetcher``  class
        specification, for example::

         [Diagnostic:H1_mirnov_array_1_coil_1]
         data_fetcher = pyfusion.acquisition.H1.fetch.H1DataFetcher
         mds_path = \h1data::top.operations.mirnov:a14_14:input_1
         coords_cylindrical = 1.114, 0.7732, 0.355
         coord_transform = H1_mirnov

        If a ``data_fetcher`` keyword argument is supplied, it overrides
        the configuration file specification.

        The  fetcher  class  is  instantiated,  including  any  supplied
        keyword arguments, and the result of the ``fetch`` method of the
        fetcher class is returned.
        """
        from pyfusion import config
        # if there is a data_fetcher arg, use that, otherwise get from config
        if kwargs.has_key('data_fetcher'):
            fetcher_class_name = kwargs['data_fetcher']
        else:
            fetcher_class_name = config.pf_get('Diagnostic',
                                               config_name,
                                               'data_fetcher')
        fetcher_class = import_from_str(fetcher_class_name)
        return fetcher_class(self, shot,
                             config_name=config_name, **kwargs).fetch() def get_config_as_dict(component_type, component_name):
    config_option_list = pyfusion.config.pf_options(component_type, component_name)
    config_map = lambda x: (x, pyfusion.config.pf_get(component_type, component_name, x))
    return dict(map(config_map, config_option_list)) def import_from_str(string_value):
    # TODO: make shortcuts for loading from within pyfusion
    split_val = string_value.split('.')
    val_module = __import__('.'.join(split_val[:-1]),
                            globals(), locals(),
                            [split_val[-1]])
    return val_module.__dict__[split_val[-1]] def equal_except_for(a, b, except_arg=None):
    """Compare objects via __dict__. allow for ignored attributes.

    (Ugly code - but it works)
    """
    a_dict = a.__dict__.copy()
    b_dict = b.__dict__.copy()
    if except_arg != None:
        if hasattr(except_arg, '__iter__'):
            for arg in except_arg:
                for dict_i in [a_dict, b_dict]:
                    if dict_i.has_key(arg):
                        dict_i.pop(arg)
        else:
            for dict_i in [a_dict, b_dict]:
                if dict_i.has_key(except_arg):
                    dict_i.pop(except_arg)
            
    return a_dict == b_dict def getAcquisition(acq_name):
    """Return  the an  instance of  the acquisition  class  specified by
    `acq_class`   in  the   `[Acquisition:acq_name]`   section  of   the
    configuration file.

    :param acq_name: name of the acquisition configuration section.
    :returns: instance of the acquisition class specified by \
    `acq_class` in the `[Acquisition:acq_name]` section of the \
    configuration file
    """
    acq_class = get_acq_from_config(acq_name)
    return acq_class(acq_name) class FakeDataAcquisition(BaseAcquisition):
    """Acquisition class for generating fake data for testing purposes."""
    pass class BaseDataFetcher(object):
    """Base  class  providing  interface   for  fetching  data  from  an
    experimental database.
    
    :param acq: in instance of a subclass of :py:class:`BaseAcquisition`
    :param shot: shot number
    :param config_name: name of a Diagnostic configuration section.
    
    It is expected that subclasses of BaseDataFetcher will be called via
    the :py:meth:`~BaseAcquisition.getdata` method, which calls the data
    fetcher's :py:meth:`fetch` method.
    """
    def __init__(self, acq, shot, config_name=None, **kwargs):
        self.shot = shot
        self.acq = acq
        if config_name != None:
            self.__dict__.update(get_config_as_dict('Diagnostic', config_name))
        self.__dict__.update(kwargs)
    def setup(self):
        """Called by :py:meth:`fetch` before retrieving the data."""
        pass
    def do_fetch(self):
        """Actually fetches  the data, using  the environment set  up by
        :py:meth:`setup`

        :returns: an instance of a subclass of \
        :py:class:`~pyfusion.data.base.BaseData` or \
        :py:class:`~pyfusion.data.base.BaseDataSet`

        Although :py:meth:`BaseDataFetcher.do_fetch` does not return any
        data object itself, it is expected that a `do_fetch()` method on
        a subclass of :py:class:`BaseDataFetcher` will.
        """
        pass
    def pulldown(self):
        """Called by :py:meth:`fetch` after retrieving the data."""
        pass
    def fetch(self):
        """Always use  this to fetch the data,  so that :py:meth:`setup`
        and  :py:meth:`pulldown` are  used to  setup and  pull  down the
        environmet used by :py:meth:`do_fetch`.
        
        :returns: the instance of a subclass of \
        :py:class:`~pyfusion.data.base.BaseData` or \
        :py:class:`~pyfusion.data.base.BaseDataSet` returned by \
        :py:meth:`do_fetch`
        """        
        self.setup()
        data = self.do_fetch()
        data.meta.update({'shot':self.shot})
        # Coords shouldn't be fetched for BaseData (they are required
        # for TimeSeries)
        #data.coords.load_from_config(**self.__dict__)
        self.pulldown()
        return data class PfTestBase(object):
    """Base class for generated sql and non-sql test cases."""
    pass
from pyfusion.test.tests import PfTestBase
from pyfusion.data.base import BaseData
from pyfusion.acquisition.base import BaseAcquisition
from pyfusion.conf.utils import get_config_as_dict, import_from_str
from pyfusion.utils.debug import equal_except_for
from pyfusion.acquisition.utils import getAcquisition
from pyfusion.acquisition.FakeData.acq import FakeDataAcquisition
from pyfusion.acquisition.base import BaseDataFetcher
from pyfusion.test.tests import PfTestBase
"""Test code for data acquisition."""


# Add new acquisition modules here for basic module structure test
acquisition_modules = ['FakeData']


class CheckAcquisitionArgs(PfTestBase):
    """Make sure we get the same result if we use config or kwargs"""

    def testEqualityConfigOrArgs(self):
        """Check that config  and kwarg instantiated Acquisition classes
        are same."""
        acq_from_config = BaseAcquisition('test_baseacq')
        # create a BaseAcquisition instance with keyword args
        config_dict = get_config_as_dict('Acquisition', 'test_baseacq')
        acq_from_kwargs = BaseAcquisition(**config_dict)
        # Acquistion   instantiated  only   from  keywords   won't  have
        # config_name set but should otherwise be equal
        self.assertTrue(equal_except_for(acq_from_config,
                                         acq_from_kwargs, 'config_name'))

    def testAcqAttrsConfig(self):
        """Check that config, kwarg attributes are correctly attached to
        object.
        
        If config is supplied, load config before kwargs.
        """
        config_dict = get_config_as_dict('Acquisition', 'test_baseacq')
        test_acq = BaseAcquisition('test_baseacq')
        for config_arg in config_dict.keys():
            self.assertTrue(hasattr(test_acq, config_arg))
        
    def testAcqAttrsConfigKwargs(self):
        """Check that config, kwarg attributes are correctly attached to
        object.
        
        If config is supplied, load config before kwargs.
        """
        config_dict = get_config_as_dict('Acquisition', 'test_baseacq')
        test_acq = BaseAcquisition('test_baseacq', dummy_var_1 = 5)
        self.assertEqual(test_acq.dummy_var_1, 5)

    def testAcqAttrsKwargs(self):
        """Check that config, kwarg attributes are correctly attached to
        object.
        
        If config is supplied, load config before kwargs.
        """
        test_acq = BaseAcquisition(dummy_var_1 = 5)
        self.assertEqual(test_acq.dummy_var_1, 5)


class CheckGetAcquisition(PfTestBase):
    """test getAcquisition function."""

    def test_get_acquistion(self):

        test_acq_1 = getAcquisition('test_fakedata')