def test_extra_sections_when_lines_dict_with_nested_lines_dicts(self): """Test parser.is_valid in dict of nested dict lists.""" class MySchema(Schema): foo = ListOption( item=DictOption( item=ListOption(item=DictOption()))) config = StringIO(""" [__main__] foo = dict1 dict2 [dict1] bar = dict3 dict4 [dict2] baz = dict5 dict6 [dict3] wham = 1 [dict4] whaz = 2 [dict5] whoosh = 3 [dict6] swoosh = 4 """) parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertEqual(parser.values(), {'__main__': {'foo': [ {'bar': [{'wham': '1'}, {'whaz': '2'}]}, {'baz': [{'whoosh': '3'}, {'swoosh': '4'}]}]}}) self.assertTrue(parser.is_valid())
def test_noschema_section(self): config = StringIO( "[__main__]\nfoo=%(bar)s\n[__noschema__]\nbar=hello") parser = SchemaConfigParser(self.schema) parser.readfp(config) parser.parse_all() self.assertTrue(parser.is_valid())
def test_extra_sections(self): """Test parser.is_valid with extra sections.""" class MySchema(Schema): foo = DictOption(spec={'bar': IntOption()}) config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=1") parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertTrue(parser.is_valid())
def test_extra_sections(self): """Test extra_sections.""" class MySchema(Schema): foo = DictOption(spec={'bar': IntOption()}) config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=1") parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() expected_sections = set(['mydict']) extra_sections = parser.extra_sections self.assertEqual(expected_sections, extra_sections)
def test_multiple_extra_sections(self): """Test parser.is_valid with multiple extra sections.""" class MySchema(Schema): foo = ListOption( item=DictOption(spec={'bar': IntOption()})) config = StringIO('[__main__]\nfoo=d1\n d2\n d3\n' '[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3') parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertTrue(parser.is_valid())
def test_set_non_string(self): """Test parser.set with a non-string value.""" class MySchema(Schema): foo = IntOption() bar = BoolOption() parser = SchemaConfigParser(MySchema()) parser.parse_all() parser.set('__main__', 'foo', 2) parser.set('__main__', 'bar', False) self.assertEqual(parser.get('__main__', 'foo'), 2) self.assertEqual(parser._sections['__main__']['foo'], '2') self.assertEqual(parser.get('__main__', 'bar'), False) self.assertEqual(parser._sections['__main__']['bar'], 'False')
def test_extra_sections_missing_section(self): """Test parse dict with missing referenced section.""" class MySchema(Schema): foo = DictOption() config = StringIO(textwrap.dedent(""" [__main__] foo = dict1 """)) parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertEqual(parser.extra_sections, set(['dict1']))
def test_multiple_extra_sections(self): """Test parsing multiple extra sections.""" class MySchema(Schema): foo = ListOption( item=DictOption(spec={'bar': IntOption()})) config = StringIO('[__main__]\nfoo=d1\n d2\n d3\n' '[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3') parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() expected_sections = set(['d1', 'd2', 'd3']) extra_sections = parser.extra_sections self.assertEqual(expected_sections, extra_sections)
def test_extra_sections_with_missing_section(self): """Test parser.is_valid with dict referencing missing section.""" class MySchema(Schema): foo = DictOption() config = StringIO(textwrap.dedent(""" [__main__] foo = dict1 """)) parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertRaises(NoSectionError, parser.values) # config is not valid self.assertFalse(parser.is_valid())
def test_missing_schema_sections(self): class MySchema(Schema): class foo(Section): bar = IntOption() class bar(Section): baz = BoolOption() config = StringIO(textwrap.dedent(""" [foo] bar = 3 """)) parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertTrue(parser.is_valid())
def test_extra_sections_with_nested_dicts_strict(self): """Test parser.is_valid w/ extra sections in a nested dict (strict).""" class MySchema(Schema): foo = DictOption(spec={'bar': DictOption()}, strict=True) config = StringIO(""" [__main__] foo=dict1 [dict1] bar=dict2 [dict2] baz=42 """) parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertEqual(parser.values(), {'__main__': {'foo': {'bar': {'baz': '42'}}}}) self.assertTrue(parser.is_valid())
def test_is_not_valid_parser_error(self): """Test parser.is_valid when parser errors.""" class MySchema(Schema): foo = IntOption() def mock_parse_all(self): assert False schema = MySchema() config = StringIO("[__main__]\nfoo = 5") parser = SchemaConfigParser(schema) parser.parse_all = mock_parse_all parser.readfp(config) self.assertFalse(parser.is_valid())
class TestSchemaConfigParser(unittest.TestCase): def setUp(self): class MySchema(Schema): foo = StringOption() self.schema = MySchema() self.parser = SchemaConfigParser(self.schema) self.config = StringIO("[__main__]\nfoo = bar") def test_init_no_args(self): self.assertRaises(TypeError, SchemaConfigParser) def test_init_valid_schema(self): self.assertEqual(self.parser.schema, self.schema) def test_init_invalid_schema(self): class MyInvalidSchema(Schema): class __main__(Section): pass self.assertRaises(SchemaValidationError, SchemaConfigParser, MyInvalidSchema()) def test_items(self): self.parser.readfp(self.config) items = self.parser.items('__main__') self.assertEqual(set(items), set([('foo', 'bar')])) def test_items_no_section(self): self.assertRaises(NoSectionError, self.parser.items, '__main__') def test_items_raw(self): config = StringIO('[__main__]\nfoo=%(baz)s') self.parser.readfp(config) items = self.parser.items('__main__', raw=True) self.assertEqual(set(items), set([('foo', '%(baz)s')])) def test_items_vars(self): config = StringIO('[__main__]\nfoo=%(baz)s') self.parser.readfp(config) items = self.parser.items('__main__', vars={'baz': '42'}) self.assertEqual(set(items), set([('foo', '42'), ('baz', '42')])) def test_items_interpolate(self): """Test parser.items with interpolated values.""" class MySchema(Schema): foo = StringOption() class baz(Section): bar = StringOption() parser = SchemaConfigParser(MySchema()) config = StringIO('[__main__]\nfoo=%(bar)s\n[baz]\nbar=42') parser.readfp(config) # test interpolate items = parser.items('baz') self.assertEqual(items, {'bar': '42'}.items()) def test_items_interpolate_error(self): config = StringIO('[__main__]\nfoo=%(bar)s') self.parser.readfp(config) self.assertRaises(InterpolationMissingOptionError, self.parser.items, '__main__') def test_values_empty_parser(self): values = self.parser.values() self.assertEqual(values, {'__main__': {'foo': ''}}) def test_values_full_parser(self): expected_values = {'__main__': {'foo': 'bar'}} self.parser.readfp(self.config) values = self.parser.values() self.assertEqual(expected_values, values) values = self.parser.values(section='__main__') self.assertEqual(expected_values['__main__'], values) def test_values_many_sections_same_option(self): """Test parser.values for many section with the same option.""" class MySchema(Schema): class foo(Section): bar = IntOption() class baz(Section): bar = IntOption() config = StringIO("[foo]\nbar=3\n[baz]\nbar=4") expected_values = {'foo': {'bar': 3}, 'baz': {'bar': 4}} schema = MySchema() parser = SchemaConfigParser(schema) parser.readfp(config) values = parser.values() self.assertEqual(values, expected_values) def test_values_many_sections_different_options(self): """Test parser.values for many sections with different options.""" class MySchema(Schema): class foo(Section): bar = IntOption() class bar(Section): baz = IntOption() config = StringIO("[foo]\nbar=3\n[bar]\nbaz=4") expected_values = {'foo': {'bar': 3}, 'bar': {'baz': 4}} schema = MySchema() parser = SchemaConfigParser(schema) parser.readfp(config) values = parser.values() self.assertEqual(values, expected_values) def test_parse_option(self): """Test parser parses option.""" class MyOtherSchema(Schema): class foo(Section): bar = StringOption() expected_value = 'baz' config = StringIO("[foo]\nbar = baz") parser = SchemaConfigParser(MyOtherSchema()) parser.readfp(config) value = parser.get('foo', 'bar') self.assertEqual(value, expected_value) def test_parse_invalid_section(self): self.assertRaises(NoSectionError, self.parser.parse, 'bar', 'baz', '1') def test_default_values(self): """Test parser reads default option values.""" class MySchema(Schema): foo = BoolOption(default=True) class bar(Section): baz = IntOption() bla = StringOption(default='hello') schema = MySchema() config = StringIO("[bar]\nbaz=123") expected_values = {'__main__': {'foo': True}, 'bar': {'baz': 123, 'bla': 'hello'}} parser = SchemaConfigParser(schema) parser.readfp(config) self.assertEquals(expected_values, parser.values()) config = StringIO("[bar]\nbla=123") expected = { '__main__': {'foo': True}, 'bar': {'baz': 0, 'bla': '123'}} parser = SchemaConfigParser(schema) parser.readfp(config) self.assertEquals(expected, parser.values()) def test_fatal_options(self): """Test parsing non-provided options marked as fatal.""" class MySchema(Schema): foo = IntOption(fatal=True) bar = IntOption() schema = MySchema() config = StringIO("[__main__]\nfoo=123") expected = {'__main__': {'foo': 123, 'bar': 0}} parser = SchemaConfigParser(schema) parser.readfp(config) self.assertEquals(expected, parser.values()) config = StringIO("[__main__]\nbar=123") parser = SchemaConfigParser(schema) parser.readfp(config) self.assertRaises(NoOptionError, parser.values) def test_extra_sections(self): """Test extra_sections.""" class MySchema(Schema): foo = DictOption(spec={'bar': IntOption()}) config = StringIO("[__main__]\nfoo=mydict\n[mydict]\nbar=1") parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() expected_sections = set(['mydict']) extra_sections = parser.extra_sections self.assertEqual(expected_sections, extra_sections) def test_extra_sections_dict_default_value(self): """Test parse dict with default value.""" class MySchema(Schema): foo = DictOption(spec={ 'bar': IntOption(), 'baz': BoolOption()}) parser = SchemaConfigParser(MySchema()) self.assertEqual(parser.get('__main__', 'foo'), {'bar': 0, 'baz': False}) self.assertEqual(parser.extra_sections, set([])) def test_extra_sections_missing_section(self): """Test parse dict with missing referenced section.""" class MySchema(Schema): foo = DictOption() config = StringIO(textwrap.dedent(""" [__main__] foo = dict1 """)) parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() self.assertEqual(parser.extra_sections, set(['dict1'])) def test_multiple_extra_sections(self): """Test parsing multiple extra sections.""" class MySchema(Schema): foo = ListOption( item=DictOption(spec={'bar': IntOption()})) config = StringIO('[__main__]\nfoo=d1\n d2\n d3\n' '[d1]\nbar=1\n[d2]\nbar=2\n[d3]\nbar=3') parser = SchemaConfigParser(MySchema()) parser.readfp(config) parser.parse_all() expected_sections = set(['d1', 'd2', 'd3']) extra_sections = parser.extra_sections self.assertEqual(expected_sections, extra_sections) def test_get_default(self): config = StringIO("[__main__]\n") expected = '' self.parser.readfp(config) default = self.parser._get_default('__main__', 'foo') self.assertEqual(default, expected) def test_get_default_noschema(self): config = StringIO("[__noschema__]\nbar=1\n[__main__]\n") expected = '1' self.parser.readfp(config) default = self.parser._get_default('__noschema__', 'bar') self.assertEqual(default, expected) def test_get_default_from_section(self): """Test parser._get_default for a section/option pair.""" class MySchema(Schema): class foo(Section): bar = IntOption() config = StringIO("[__main__]\n") expected = 0 parser = SchemaConfigParser(MySchema()) parser.readfp(config) default = parser._get_default('foo', 'bar') self.assertEqual(default, expected) def test_get_default_no_option(self): self.assertRaises(NoOptionError, self.parser._get_default, '__main__', 'bar') def test_get_default_no_section(self): self.assertRaises(NoSectionError, self.parser._get_default, 'foo', 'bar') def test_multi_file_dict_config(self): """Test parsing a dict option spanning multiple files.""" class MySchema(Schema): foo = DictOption(spec={ 'bar': IntOption(), 'baz': IntOption(), }, strict=True) config1 = StringIO('[__main__]\nfoo=mydict\n[mydict]\nbar=1\nbaz=1') config2 = StringIO('[mydict]\nbaz=2') expected_values = {'__main__': {'foo': {'bar': 1, 'baz': 2}}} parser = SchemaConfigParser(MySchema()) parser.readfp(config1) parser.readfp(config2) self.assertEqual(parser.values(), expected_values) def test_multi_file_dict_list_config(self): """Test parsing a list of dicts option spanning multiple files.""" class MySchema(Schema): foo = ListOption( item=DictOption(spec={ 'bar': IntOption(), 'baz': IntOption(), }, strict=True)) config1 = StringIO('[__main__]\nfoo=mydict\n[mydict]\nbar=1\nbaz=1') expected_values = {'__main__': {'foo': [{'bar': 1, 'baz': 1}]}} parser = SchemaConfigParser(MySchema()) parser.readfp(config1) self.assertEqual(parser.values(), expected_values) # override used dictionaries config2 = StringIO('[__main__]\nfoo=otherdict\n[otherdict]\nbar=2') expected_values = {'__main__': {'foo': [{'bar': 2, 'baz': 0}]}} parser.readfp(config2) self.assertEqual(parser.values(), expected_values) # override existing dictionaries config3 = StringIO('[otherdict]\nbaz=3') expected_values = {'__main__': {'foo': [{'bar': 2, 'baz': 3}]}} parser.readfp(config3) self.assertEqual(parser.values(), expected_values) # reuse existing dict config4 = StringIO('[__main__]\nfoo=mydict\n otherdict') expected_values = {'__main__': {'foo': [{'bar': 1, 'baz': 1}, {'bar': 2, 'baz': 3}]}} parser.readfp(config4) self.assertEqual(parser.values(), expected_values) def test_read_multiple_files(self): def setup_config(): folder = tempfile.mkdtemp() f = open("%s/first.cfg" % folder, 'w') f.write("[__main__]\nfoo=foo") f.close() f = open("%s/second.cfg" % folder, 'w') f.write("[__main__]\nfoo=bar") f.close() files = ["%s/first.cfg" % folder, "%s/second.cfg" % folder] return files, folder files, folder = setup_config() self.parser.read(files) self.assertEqual(self.parser.values(), {'__main__': {'foo': 'bar'}}) # silently remove any created files try: shutil.rmtree(folder) except: pass def test_read_utf8_encoded_file(self): # create config file fp, filename = tempfile.mkstemp() try: f = open(filename, 'w') f.write(u'[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING)) f.close() self.parser.read(filename) self.assertEqual(self.parser.values(), {'__main__': {'foo': u'€'}}) finally: # destroy config file os.remove(filename) def test_readfp_with_utf8_encoded_text(self): config = StringIO(u'[__main__]\nfoo=€'.encode(CONFIG_FILE_ENCODING)) self.parser.readfp(config) self.assertEqual(self.parser.values(), {'__main__': {'foo': u'€'}}) def test_set(self): with tempfile.NamedTemporaryFile() as f: f.write('[__main__]\nfoo=1') f.flush() self.parser.read(f.name) self.assertEqual(self.parser._dirty, {}) self.assertEqual(self.parser.get('__main__', 'foo'), '1') self.parser.set('__main__', 'foo', '2') self.assertEqual(self.parser.get('__main__', 'foo'), '2') self.assertEqual(self.parser._dirty, {f.name: {'__main__': {'foo': '2'}}}) def test_set_non_string(self): """Test parser.set with a non-string value.""" class MySchema(Schema): foo = IntOption() bar = BoolOption() parser = SchemaConfigParser(MySchema()) parser.parse_all() parser.set('__main__', 'foo', 2) parser.set('__main__', 'bar', False) self.assertEqual(parser.get('__main__', 'foo'), 2) self.assertEqual(parser._sections['__main__']['foo'], '2') self.assertEqual(parser.get('__main__', 'bar'), False) self.assertEqual(parser._sections['__main__']['bar'], 'False') def test_set_invalid_type(self): self.parser.parse_all() self.assertRaises(TypeError, self.parser.set, '__main__', 'foo', 2) def test_write(self): """Test parser write config to a file.""" class MySchema(Schema): foo = StringOption() class DEFAULTSECT(Section): pass parser = SchemaConfigParser(MySchema()) expected = u"[{0}]\nbaz = 2\n\n[__main__]\nfoo = bar".format( DEFAULTSECT) config = StringIO(expected) parser.readfp(config) # create config file fp, filename = tempfile.mkstemp() try: parser.write(open(filename, 'w')) result = open(filename, 'r').read().strip() self.assertEqual(result, expected) finally: # remove the file os.unlink(filename) def test_write_prefill_parser(self): """Test parser write config to a file.""" class MySchema(Schema): foo = IntOption() parser = SchemaConfigParser(MySchema()) expected = u"[__main__]\nfoo = 0" # create config file fp, filename = tempfile.mkstemp() try: parser.write(open(filename, 'w')) result = open(filename, 'r').read().strip() self.assertEqual(result, expected) finally: # remove the file os.unlink(filename) def test_save_config(self): expected = u'[__main__]\nfoo = 42' self._check_save_file(expected) def test_save_config_non_ascii(self): expected = u'[__main__]\nfoo = fóobâr' self._check_save_file(expected) def _check_save_file(self, expected, read_config=True): config = StringIO(expected.encode(CONFIG_FILE_ENCODING)) if read_config: self.parser.readfp(config) # create config file fp, filename = tempfile.mkstemp() try: self.parser.save(open(filename, 'w')) result = open(filename, 'r').read().strip() self.assertEqual(result.decode(CONFIG_FILE_ENCODING), expected) self.parser.save(filename) result = open(filename, 'r').read().strip() self.assertEqual(result.decode(CONFIG_FILE_ENCODING), expected) finally: # remove the file os.unlink(filename) def test_save_config_prefill_parser(self): """Test parser save config when no config files read.""" expected = u'[__main__]\nfoo =' self._check_save_file(expected, read_config=False) def test_save_no_config_same_files(self): class MySchema(Schema): foo = IntOption() parser = SchemaConfigParser(MySchema()) parser.set('__main__', 'foo', 2) self.assertRaises(ValueError, parser.save) def test_save_config_same_files(self): """Test parser save config values to original files.""" def setup_config(): folder = tempfile.mkdtemp() f = open("%s/first.cfg" % folder, 'w') f.write("[__main__]\nfoo=1") f.close() f = open("%s/second.cfg" % folder, 'w') f.write("[__main__]\nbar=2") f.close() files = ["%s/first.cfg" % folder, "%s/second.cfg" % folder] return files, folder class MySchema(Schema): foo = StringOption() bar = StringOption() baz = IntOption() self.parser = SchemaConfigParser(MySchema()) files, folder = setup_config() self.parser.read(files) self.parser.set('__main__', 'foo', '42') self.parser.set('__main__', 'bar', '42') self.parser.set('__main__', 'baz', 42) self.parser.save() # test the changes were correctly saved data = open("%s/first.cfg" % folder).read() self.assertTrue('foo = 42' in data) self.assertFalse('bar = 42' in data) # new value goes into last read config file self.assertFalse('baz = 42' in data) data = open("%s/second.cfg" % folder).read() self.assertFalse('foo = 42' in data) self.assertTrue('bar = 42' in data) # new value goes into last read config file self.assertTrue('baz = 42' in data) # silently remove any created files try: shutil.rmtree(folder) except: pass def test_save_config_last_location_nested_includes(self): def setup_config(): folder = tempfile.mkdtemp() f = open("%s/first.cfg" % folder, 'w') f.write("[__main__]\nfoo=1") f.close() f = open("%s/second.cfg" % folder, 'w') f.write("[__main__]\nbar=2\nincludes = third.cfg") f.close() f = open("%s/third.cfg" % folder, 'w') f.write("[__main__]\nfoo=3") f.close() files = ["%s/first.cfg" % folder, "%s/second.cfg" % folder] return files, folder class MySchema(Schema): foo = StringOption() bar = StringOption() baz = IntOption() self.parser = SchemaConfigParser(MySchema()) files, folder = setup_config() self.parser.read(files) self.parser.set('__main__', 'foo', '42') self.parser.set('__main__', 'bar', '42') self.parser.set('__main__', 'baz', 42) self.parser.save() # test the changes were correctly saved data = open("%s/first.cfg" % folder).read() self.assertEqual(data.strip(), '[__main__]\nfoo=1') data = open("%s/third.cfg" % folder).read() self.assertEqual(data.strip(), '[__main__]\nfoo = 42') data = open("%s/second.cfg" % folder).read() self.assertTrue('bar = 42' in data) # new value goes into last read config file # not in the last included config file self.assertTrue('baz = 42' in data) # silently remove any created files try: shutil.rmtree(folder) except: pass