import autopath
from py.test import raises

from config import *
from option import *

def make_description():
    gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
    gcdummy = BoolOption('dummy', 'dummy', default=False)
    objspaceoption = ChoiceOption('objspace', 'Object space',
                                ['std', 'thunk'], 'std')
    booloption = BoolOption('bool', 'Test boolean option', default=True)
    intoption = IntOption('int', 'Test int option', default=0)
    floatoption = FloatOption('float', 'Test float option', default=2.3)
    stroption = StrOption('str', 'Test string option', default="abc")
    boolop = BoolOption('boolop', 'Test boolean option op', default=True)
    wantref_option = BoolOption('wantref', 'Test requires', default=False,
                                    requires=['boolop'])
    wantframework_option = BoolOption('wantframework', 'Test requires',
                                      default=False,
                                      requires=['boolop'])
    gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
    descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
                                           wantref_option, stroption,
                                           wantframework_option,
                                           intoption, boolop])
    return descr

def make_description_duplicates():
    gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
    ## dummy 1
    gcdummy = BoolOption('dummy', 'dummy', default=False)
    objspaceoption = ChoiceOption('objspace', 'Object space',
                                ['std', 'thunk'], 'std')
    booloption = BoolOption('bool', 'Test boolean option', default=True)
    intoption = IntOption('int', 'Test int option', default=0)
    floatoption = FloatOption('float', 'Test float option', default=2.3)
    stroption = StrOption('str', 'Test string option', default="abc")
    boolop = BoolOption('boolop', 'Test boolean option op', default=True)
    wantref_option = BoolOption('wantref', 'Test requires', default=False,
                                    requires=['boolop'])
    wantframework_option = BoolOption('wantframework', 'Test requires',
                                      default=False,
                                      requires=['boolop'])
    # dummy2 (same name)
    gcdummy2  = BoolOption('dummy', 'dummy2', default=True)
    gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, gcdummy2, floatoption])
    descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
                                           wantref_option, stroption,
                                           wantframework_option,
                                           intoption, boolop])
    return descr

def test_identical_names():
    """If in the schema (the option description) there is something that 
    have the same name, an exection is raised
    """    
    descr = make_description_duplicates()
    raises(ConflictConfigError, "cfg = Config(descr)")

def make_description2():
    gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
    gcdummy = BoolOption('dummy', 'dummy', default=False)

    floatoption = FloatOption('float', 'Test float option', default=2.3)
    
    objspaceoption = ChoiceOption('objspace', 'Object space',
                                ['std', 'thunk'], 'std')
    booloption = BoolOption('bool', 'Test boolean option', default=True)
    intoption = IntOption('int', 'Test int option', default=0)
    stroption = StrOption('str', 'Test string option', default="abc")
    # first multi
    boolop = BoolOption('boolop', 'Test boolean option op', default=True)
    boolop.enable_multi()
    wantref_option = BoolOption('wantref', 'Test requires', default=False,
                                    requires=['boolop'])
    # second multi
    wantframework_option = BoolOption('wantframework', 'Test requires',
                                      default=False,
                                      requires=['boolop'])
    wantframework_option.enable_multi()
    
    gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
    descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
                                           wantref_option, stroption,
                                           wantframework_option,
                                           intoption, boolop])
    return descr

# FIXME: XXX would you mind putting the multi validations anywhere else 
# than in the requires !!! 
#def test_multi_constraints():
#    "a multi in a constraint has to have the same length"
#    descr = make_description2()
#    cfg = Config(descr)
#    cfg.boolop = [True, True, False]
#    cfg.wantframework = [False, False, True]
#    
#def test_multi_raise():
#    "a multi in a constraint has to have the same length"
#    # FIXME fusionner les deux tests, MAIS PROBLEME :
#    # il ne devrait pas etre necessaire de refaire une config
#    # si la valeur est modifiee une deuxieme fois -> 
#    #raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
#    #   ExceptionFailure: 'DID NOT RAISE'
#    descr = make_description2()
#    cfg = Config(descr)
#    cfg.boolop = [True]
#    raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
# ____________________________________________________________
# adding dynamically new options description schema
def test_newoption_add_in_descr():
    descr = make_description()
    newoption = BoolOption('newoption', 'dummy twoo', default=False)
    descr.add_child(newoption)
    config = Config(descr)
    assert config.newoption == False

def test_newoption_add_in_subdescr():
    descr = make_description()
    newoption = BoolOption('newoption', 'dummy twoo', default=False)
    descr.gc.add_child(newoption)
    config = Config(descr, bool=False)
    assert config.gc.newoption == False

def test_newoption_add_in_config():
    descr = make_description()
    config = Config(descr, bool=False)
    newoption = BoolOption('newoption', 'dummy twoo', default=False)
    descr.add_child(newoption)
    config.cfgimpl_update()
    assert config.newoption == False
# ____________________________________________________________
def make_description_requires():
    gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
    gcdummy = BoolOption('dummy', 'dummy', default=False)

    floatoption = FloatOption('float', 'Test float option', default=2.3)
    
    objspaceoption = ChoiceOption('objspace', 'Object space',
                                ['std', 'thunk'], 'std')
    booloption = BoolOption('bool', 'Test boolean option', default=True)
    intoption = IntOption('int', 'Test int option', default=0)
    stroption = StrOption('str', 'Test string option', default="abc", 
                          requires=[('int', 1, 'hide')])
    
    gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
    descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
                                           stroption, intoption])
    return descr

def test_hidden_if_in():
    descr = make_description_requires()
    cfg = Config(descr)
    intoption = cfg.unwrap_from_path('int')
    stroption = cfg.unwrap_from_path('str')
    assert not stroption._is_hidden()
    cfg.int = 1
    raises(HiddenOptionError, "cfg.str")
    raises(HiddenOptionError, 'cfg.str= "uvw"')
    assert stroption._is_hidden()

def test_hidden_if_in_with_group():
    gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
    gcdummy = BoolOption('dummy', 'dummy', default=False)

    floatoption = FloatOption('float', 'Test float option', default=2.3)
    
    objspaceoption = ChoiceOption('objspace', 'Object space',
                                ['std', 'thunk'], 'std')
    booloption = BoolOption('bool', 'Test boolean option', default=True)
    intoption = IntOption('int', 'Test int option', default=0)
    stroption = StrOption('str', 'Test string option', default="abc")
    gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], 
                                                  requires=[('int', 1, 'hide')])
    descr = OptionDescription('constraints', '', [gcgroup, booloption, 
                                          objspaceoption, stroption, intoption])
    cfg = Config(descr)
    assert not gcgroup._is_hidden()
    cfg.int = 1
    raises(HiddenOptionError, "cfg.gc.name")
#    raises(HiddenOptionError, 'cfg.gc= "uvw"')
    assert gcgroup._is_hidden()

def test_disabled_with_group():
    gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
    gcdummy = BoolOption('dummy', 'dummy', default=False)

    floatoption = FloatOption('float', 'Test float option', default=2.3)
    
    objspaceoption = ChoiceOption('objspace', 'Object space',
                                ['std', 'thunk'], 'std')
    booloption = BoolOption('bool', 'Test boolean option', default=True)
    intoption = IntOption('int', 'Test int option', default=0)
    stroption = StrOption('str', 'Test string option', default="abc")
    gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], 
                                                  requires=[('int', 1, 'disable')])
    descr = OptionDescription('constraints', '', [gcgroup, booloption, 
                                          objspaceoption, stroption, intoption])
    cfg = Config(descr)
    assert not gcgroup._is_disabled()
    cfg.int = 1
    raises(DisabledOptionError, "cfg.gc.name")
#    raises(HiddenOptionError, 'cfg.gc= "uvw"')
    assert gcgroup._is_disabled()