def test_it_doesnt_override_existing_non_default_values(self):
        contents = """
            { "a" : "stuff"
            , "b" : "things"
            , "c" : "and"
            , "d" : "shells"
            , "e-f" : "blah"
            , "g-h" : "other"
            }
        """
        with a_temp_file(contents) as filename:
            config_util = ConfigUtil()
            c_val = Default(21)
            config_util.use_options({'b':21, 'c':c_val, 'd':None, "g-h":"meh"})
            config_util.values |should| equal_to({'b':21, 'c':c_val, 'd':None, "g_h":"meh"})

            config_util.apply_config_file(filename)
            config_util.values |should| equal_to({"a":"stuff", "b":21, "c":"and", 'd':None, "e_f":"blah", "g_h":"meh"})
class Test_ConfigUtil_UsingOptions(object):
    '''Make sure it knows how to use options'''
    def setup(self):
        self.config_util = ConfigUtil()
        self.config_util.values |should| equal_to({})

    def test_it_puts_options_in_values(self):
        self.config_util.use_options({"a":1, "b":2})
        self.config_util.values |should| equal_to({"a":1, "b":2})

    def test_it_overrides_all_values(self):
        c_val = Default(3)
        self.config_util.use_options({"a":1, "b":2, "c":c_val})
        self.config_util.values |should| equal_to({"a":1, "b":2, "c":c_val})

        self.config_util.use_options({"b":4, "c":5, "d":6})
        self.config_util.values |should| equal_to({"a":1, "b":4, "c":5, "d":6})

    def test_it_normalises_keys(self):
        self.config_util.use_options({"a-b":1, "c_d":2, "e-f_g-h":3})
        self.config_util.values |should| equal_to({"a_b":1, "c_d":2, "e_f_g_h":3})

    def test_it_uses_extractor_if_provided(self):
        template = fudge.Fake("template")
        def extractor(templ, values):
            templ |should| be(template)
            for key, val in values.items():
                yield "e-{}".format(key), val + 1

        self.config_util.template = template
        self.config_util.use_options({"a":1, "b":2, "c":3}, extractor=extractor)
        self.config_util.values |should| equal_to({"e_a":2, "e_b":3, "e_c":4})

    def test_it_works_with_list_of_tuples(self):
        c_val = Default(3)
        self.config_util.use_options([("a",1), ("b",2), ("c",c_val)])
        self.config_util.values |should| equal_to({"a":1, "b":2, "c":c_val})

    def test_it_doesnt_complain_if_extractor_returns_none(self):
        '''It's valid for the extractor to say there are no values'''
        template = fudge.Fake("template")
        def extractor(templ, values):
            templ |should| be(template)
            return None

        self.config_util.template = template
        self.config_util.use_options({"a":1, "b":2, "c":3}, extractor=extractor)
        self.config_util.values |should| equal_to({})