# Path: msaf/configparser.py
# def AddConfigVar(name, doc, configparam, root=config):
#     """Add a new variable to msaf.config
# 
#     Parameters
#     ----------
#     name: str
#         String of the form "[section0.[section1.[etc]]]option", containing the
#         full name for this configuration variable.
#     string: str
#         What does this variable specify?
#     configparam: `ConfigParam`
#         An object for getting and setting this configuration parameter.
#     root: object
#         Used for recursive calls -- do not provide an argument for this
#         parameter.
#     """
# 
#     # This method also performs some of the work of initializing ConfigParam
#     # instances
# 
#     if root is config:
#         # only set the name in the first call, not the recursive ones
#         configparam.fullname = name
#     sections = name.split('.')
#     if len(sections) > 1:
#         # set up a subobject
#         if not hasattr(root, sections[0]):
#             # every internal node in the config tree is an instance of its own
#             # unique class
#             class SubObj(object):
#                 _i_am_a_config_class = True
#             setattr(root.__class__, sections[0], SubObj())
#         newroot = getattr(root, sections[0])
#         if (not getattr(newroot, '_i_am_a_config_class', False) or
#                 isinstance(newroot, type)):
#             raise TypeError(
#                 'Internal config nodes must be config class instances',
#                 newroot)
#         return AddConfigVar('.'.join(sections[1:]), doc, configparam,
#                             root=newroot)
#     else:
#         if hasattr(root, name):
#             raise AttributeError('This name is already taken',
#                                  configparam.fullname)
#         configparam.doc = doc
#         # Trigger a read of the value from config files and env vars
#         # This allow to filter wrong value from the user.
#         if not callable(configparam.default):
#             configparam.__get__(root, type(root), delete_key=True)
#         else:
#             # We do not want to evaluate now the default value
#             # when it is a callable.
#             try:
#                 fetch_val_for_key(configparam.fullname)
#                 # The user provided a value, filter it now.
#                 configparam.__get__(root, type(root), delete_key=True)
#             except KeyError:
#                 pass
#         setattr(root.__class__, sections[0], configparam)
#         _config_var_list.append(configparam)
# 
# def BoolParam(default, is_valid=None, allow_override=True):
#     # see comment at the beginning of this file.
# 
#     def booltype(s):
#         if s in ['False', 'false', '0', False]:
#             return False
#         elif s in ['True', 'true', '1', True]:
#             return True
# 
#     def is_valid_bool(s):
#         if s in ['False', 'false', '0', 'True', 'true', '1', False, True]:
#             return True
#         else:
#             return False
# 
#     if is_valid is None:
#         is_valid = is_valid_bool
# 
#     return TypedParam(default, booltype, is_valid,
#                       allow_override=allow_override)
# 
# class EnumStr(ConfigParam):
#     def __init__(self, default, *options, **kwargs):
#         self.default = default
#         self.all = (default,) + options
# 
#         # All options should be strings
#         for val in self.all:
#             if not isinstance(val, string_types) and val is not None:
#                 raise ValueError('Valid values for an EnumStr parameter '
#                                  'should be strings or `None`', val, type(val))
# 
#         convert = kwargs.get("convert", None)
# 
#         def filter(val):
#             # uri: We want to keep None values
#             if val is None:
#                 return val
# 
#             if convert:
#                 val = convert(val)
#             if val in self.all:
#                 return val
#             else:
#                 raise ValueError((
#                     'Invalid value ("%s") for configuration variable "%s". '
#                     'Valid options are %s'
#                     % (val, self.fullname, self.all)))
#         over = kwargs.get("allow_override", True)
#         super(EnumStr, self).__init__(default, filter, over)
# 
#     def __str__(self):
#         return '%s (%s) ' % (self.fullname, self.all)
# 
# def IntParam(default, is_valid=None, allow_override=True):
#     return TypedParam(default, int, is_valid, allow_override=allow_override)
# 
# def StrParam(default, is_valid=None, allow_override=True):
#     return TypedParam(default, str, is_valid, allow_override=allow_override)
# 
# class ListParam(ConfigParam):
#     def __init__(self, default, *options, **kwargs):
#         self.default = default
#         try:
#             assert len(default) > 0
#         except AssertionError:
#             raise ValueError("List is empty")
#         except TypeError:
#             raise ValueError("The parameter is not a list.")
# 
#         over = kwargs.get("allow_override", True)
#         super(ListParam, self).__init__(default, None, over)
# 
#     def __str__(self):
#         return '%s (%s) ' % (self.fullname, self.default)


import matplotlib
import msaf
from nose.tools import raises
from collections import namedtuple
from msaf.configparser import (AddConfigVar, BoolParam, EnumStr,
                               IntParam, StrParam, ListParam)
    assert msaf.config.new_var3 == "merda"


@raises(ValueError)
def test_invalid_enumstr():
    """Tests invalid enumstrings."""
    AddConfigVar('new_var4', "doc", EnumStr("caca", 42, "merda"))


def test_false_boolparam():
    """Tests a false boolean param."""
    AddConfigVar('new_var4', "doc", BoolParam("false"))
    assert not msaf.config.new_var4


@raises(ValueError)
def test_wrong_boolparam():
    """Tests a wrong boolean param."""
    AddConfigVar('new_var5', "doc", BoolParam("falsitto"))


@raises(ValueError)
def test_empty_list_param():
    """Tests an empty list param."""
    AddConfigVar('new_var6', "doc", ListParam([]))


@raises(ValueError)
def test_wrong_list_param():
    """Tests a wrong list param."""

# Path: msaf/configparser.py
# def AddConfigVar(name, doc, configparam, root=config):
#     """Add a new variable to msaf.config
# 
#     Parameters
#     ----------
#     name: str
#         String of the form "[section0.[section1.[etc]]]option", containing the
#         full name for this configuration variable.
#     string: str
#         What does this variable specify?
#     configparam: `ConfigParam`
#         An object for getting and setting this configuration parameter.
#     root: object
#         Used for recursive calls -- do not provide an argument for this
#         parameter.
#     """
# 
#     # This method also performs some of the work of initializing ConfigParam
#     # instances
# 
#     if root is config:
#         # only set the name in the first call, not the recursive ones
#         configparam.fullname = name
#     sections = name.split('.')
#     if len(sections) > 1:
#         # set up a subobject
#         if not hasattr(root, sections[0]):
#             # every internal node in the config tree is an instance of its own
#             # unique class
#             class SubObj(object):
#                 _i_am_a_config_class = True
#             setattr(root.__class__, sections[0], SubObj())
#         newroot = getattr(root, sections[0])
#         if (not getattr(newroot, '_i_am_a_config_class', False) or
#                 isinstance(newroot, type)):
#             raise TypeError(
#                 'Internal config nodes must be config class instances',
#                 newroot)
#         return AddConfigVar('.'.join(sections[1:]), doc, configparam,
#                             root=newroot)
#     else:
#         if hasattr(root, name):
#             raise AttributeError('This name is already taken',
#                                  configparam.fullname)
#         configparam.doc = doc
#         # Trigger a read of the value from config files and env vars
#         # This allow to filter wrong value from the user.
#         if not callable(configparam.default):
#             configparam.__get__(root, type(root), delete_key=True)
#         else:
#             # We do not want to evaluate now the default value
#             # when it is a callable.
#             try:
#                 fetch_val_for_key(configparam.fullname)
#                 # The user provided a value, filter it now.
#                 configparam.__get__(root, type(root), delete_key=True)
#             except KeyError:
#                 pass
#         setattr(root.__class__, sections[0], configparam)
#         _config_var_list.append(configparam)
# 
# def BoolParam(default, is_valid=None, allow_override=True):
#     # see comment at the beginning of this file.
# 
#     def booltype(s):
#         if s in ['False', 'false', '0', False]:
#             return False
#         elif s in ['True', 'true', '1', True]:
#             return True
# 
#     def is_valid_bool(s):
#         if s in ['False', 'false', '0', 'True', 'true', '1', False, True]:
#             return True
#         else:
#             return False
# 
#     if is_valid is None:
#         is_valid = is_valid_bool
# 
#     return TypedParam(default, booltype, is_valid,
#                       allow_override=allow_override)
# 
# class EnumStr(ConfigParam):
#     def __init__(self, default, *options, **kwargs):
#         self.default = default
#         self.all = (default,) + options
# 
#         # All options should be strings
#         for val in self.all:
#             if not isinstance(val, string_types) and val is not None:
#                 raise ValueError('Valid values for an EnumStr parameter '
#                                  'should be strings or `None`', val, type(val))
# 
#         convert = kwargs.get("convert", None)
# 
#         def filter(val):
#             # uri: We want to keep None values
#             if val is None:
#                 return val
# 
#             if convert:
#                 val = convert(val)
#             if val in self.all:
#                 return val
#             else:
#                 raise ValueError((
#                     'Invalid value ("%s") for configuration variable "%s". '
#                     'Valid options are %s'
#                     % (val, self.fullname, self.all)))
#         over = kwargs.get("allow_override", True)
#         super(EnumStr, self).__init__(default, filter, over)
# 
#     def __str__(self):
#         return '%s (%s) ' % (self.fullname, self.all)
# 
# def IntParam(default, is_valid=None, allow_override=True):
#     return TypedParam(default, int, is_valid, allow_override=allow_override)
# 
# def StrParam(default, is_valid=None, allow_override=True):
#     return TypedParam(default, str, is_valid, allow_override=allow_override)
# 
# class ListParam(ConfigParam):
#     def __init__(self, default, *options, **kwargs):
#         self.default = default
#         try:
#             assert len(default) > 0
#         except AssertionError:
#             raise ValueError("List is empty")
#         except TypeError:
#             raise ValueError("The parameter is not a list.")
# 
#         over = kwargs.get("allow_override", True)
#         super(ListParam, self).__init__(default, None, over)
# 
#     def __str__(self):
#         return '%s (%s) ' % (self.fullname, self.default)


# Path: tests/test_config.py
import matplotlib
import msaf
from nose.tools import raises
from collections import namedtuple
from msaf.configparser import (AddConfigVar, BoolParam, EnumStr,
                               IntParam, StrParam, ListParam)

    assert msaf.config.new_var3 == "merda"


@raises(ValueError)
def test_invalid_enumstr():
    """Tests invalid enumstrings."""
    AddConfigVar('new_var4', "doc", EnumStr("caca", 42, "merda"))


def test_false_boolparam():
    """Tests a false boolean param."""
    AddConfigVar('new_var4', "doc", BoolParam("false"))
    assert not msaf.config.new_var4


@raises(ValueError)
def test_wrong_boolparam():
    """Tests a wrong boolean param."""
    AddConfigVar('new_var5', "doc", BoolParam("falsitto"))


@raises(ValueError)
def test_empty_list_param():
    """Tests an empty list param."""
    AddConfigVar('new_var6', "doc", ListParam([]))


@raises(ValueError)
def test_wrong_list_param():
    """Tests a wrong list param."""

    AddConfigVar('new_var7', "doc", ListParam(42))