17db96d56Sopenharmony_ciimport collections 27db96d56Sopenharmony_ciimport configparser 37db96d56Sopenharmony_ciimport io 47db96d56Sopenharmony_ciimport os 57db96d56Sopenharmony_ciimport pathlib 67db96d56Sopenharmony_ciimport textwrap 77db96d56Sopenharmony_ciimport unittest 87db96d56Sopenharmony_ciimport warnings 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_cifrom test import support 117db96d56Sopenharmony_cifrom test.support import os_helper 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ciclass SortedDict(collections.UserDict): 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci def items(self): 177db96d56Sopenharmony_ci return sorted(self.data.items()) 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci def keys(self): 207db96d56Sopenharmony_ci return sorted(self.data.keys()) 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ci def values(self): 237db96d56Sopenharmony_ci return [i[1] for i in self.items()] 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci def iteritems(self): 267db96d56Sopenharmony_ci return iter(self.items()) 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ci def iterkeys(self): 297db96d56Sopenharmony_ci return iter(self.keys()) 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci def itervalues(self): 327db96d56Sopenharmony_ci return iter(self.values()) 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci __iter__ = iterkeys 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ciclass CfgParserTestCaseClass: 387db96d56Sopenharmony_ci allow_no_value = False 397db96d56Sopenharmony_ci delimiters = ('=', ':') 407db96d56Sopenharmony_ci comment_prefixes = (';', '#') 417db96d56Sopenharmony_ci inline_comment_prefixes = (';', '#') 427db96d56Sopenharmony_ci empty_lines_in_values = True 437db96d56Sopenharmony_ci dict_type = configparser._default_dict 447db96d56Sopenharmony_ci strict = False 457db96d56Sopenharmony_ci default_section = configparser.DEFAULTSECT 467db96d56Sopenharmony_ci interpolation = configparser._UNSET 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci def newconfig(self, defaults=None): 497db96d56Sopenharmony_ci arguments = dict( 507db96d56Sopenharmony_ci defaults=defaults, 517db96d56Sopenharmony_ci allow_no_value=self.allow_no_value, 527db96d56Sopenharmony_ci delimiters=self.delimiters, 537db96d56Sopenharmony_ci comment_prefixes=self.comment_prefixes, 547db96d56Sopenharmony_ci inline_comment_prefixes=self.inline_comment_prefixes, 557db96d56Sopenharmony_ci empty_lines_in_values=self.empty_lines_in_values, 567db96d56Sopenharmony_ci dict_type=self.dict_type, 577db96d56Sopenharmony_ci strict=self.strict, 587db96d56Sopenharmony_ci default_section=self.default_section, 597db96d56Sopenharmony_ci interpolation=self.interpolation, 607db96d56Sopenharmony_ci ) 617db96d56Sopenharmony_ci instance = self.config_class(**arguments) 627db96d56Sopenharmony_ci return instance 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci def fromstring(self, string, defaults=None): 657db96d56Sopenharmony_ci cf = self.newconfig(defaults) 667db96d56Sopenharmony_ci cf.read_string(string) 677db96d56Sopenharmony_ci return cf 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ciclass BasicTestCase(CfgParserTestCaseClass): 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci def basic_test(self, cf): 737db96d56Sopenharmony_ci E = ['Commented Bar', 747db96d56Sopenharmony_ci 'Foo Bar', 757db96d56Sopenharmony_ci 'Internationalized Stuff', 767db96d56Sopenharmony_ci 'Long Line', 777db96d56Sopenharmony_ci 'Section\\with$weird%characters[\t', 787db96d56Sopenharmony_ci 'Spaces', 797db96d56Sopenharmony_ci 'Spacey Bar', 807db96d56Sopenharmony_ci 'Spacey Bar From The Beginning', 817db96d56Sopenharmony_ci 'Types', 827db96d56Sopenharmony_ci 'This One Has A ] In It', 837db96d56Sopenharmony_ci ] 847db96d56Sopenharmony_ci 857db96d56Sopenharmony_ci if self.allow_no_value: 867db96d56Sopenharmony_ci E.append('NoValue') 877db96d56Sopenharmony_ci E.sort() 887db96d56Sopenharmony_ci F = [('baz', 'qwe'), ('foo', 'bar3')] 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci # API access 917db96d56Sopenharmony_ci L = cf.sections() 927db96d56Sopenharmony_ci L.sort() 937db96d56Sopenharmony_ci eq = self.assertEqual 947db96d56Sopenharmony_ci eq(L, E) 957db96d56Sopenharmony_ci L = cf.items('Spacey Bar From The Beginning') 967db96d56Sopenharmony_ci L.sort() 977db96d56Sopenharmony_ci eq(L, F) 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci # mapping access 1007db96d56Sopenharmony_ci L = [section for section in cf] 1017db96d56Sopenharmony_ci L.sort() 1027db96d56Sopenharmony_ci E.append(self.default_section) 1037db96d56Sopenharmony_ci E.sort() 1047db96d56Sopenharmony_ci eq(L, E) 1057db96d56Sopenharmony_ci L = cf['Spacey Bar From The Beginning'].items() 1067db96d56Sopenharmony_ci L = sorted(list(L)) 1077db96d56Sopenharmony_ci eq(L, F) 1087db96d56Sopenharmony_ci L = cf.items() 1097db96d56Sopenharmony_ci L = sorted(list(L)) 1107db96d56Sopenharmony_ci self.assertEqual(len(L), len(E)) 1117db96d56Sopenharmony_ci for name, section in L: 1127db96d56Sopenharmony_ci eq(name, section.name) 1137db96d56Sopenharmony_ci eq(cf.defaults(), cf[self.default_section]) 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci # The use of spaces in the section names serves as a 1167db96d56Sopenharmony_ci # regression test for SourceForge bug #583248: 1177db96d56Sopenharmony_ci # http://www.python.org/sf/583248 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci # API access 1207db96d56Sopenharmony_ci eq(cf.get('Foo Bar', 'foo'), 'bar1') 1217db96d56Sopenharmony_ci eq(cf.get('Spacey Bar', 'foo'), 'bar2') 1227db96d56Sopenharmony_ci eq(cf.get('Spacey Bar From The Beginning', 'foo'), 'bar3') 1237db96d56Sopenharmony_ci eq(cf.get('Spacey Bar From The Beginning', 'baz'), 'qwe') 1247db96d56Sopenharmony_ci eq(cf.get('Commented Bar', 'foo'), 'bar4') 1257db96d56Sopenharmony_ci eq(cf.get('Commented Bar', 'baz'), 'qwe') 1267db96d56Sopenharmony_ci eq(cf.get('Spaces', 'key with spaces'), 'value') 1277db96d56Sopenharmony_ci eq(cf.get('Spaces', 'another with spaces'), 'splat!') 1287db96d56Sopenharmony_ci eq(cf.getint('Types', 'int'), 42) 1297db96d56Sopenharmony_ci eq(cf.get('Types', 'int'), "42") 1307db96d56Sopenharmony_ci self.assertAlmostEqual(cf.getfloat('Types', 'float'), 0.44) 1317db96d56Sopenharmony_ci eq(cf.get('Types', 'float'), "0.44") 1327db96d56Sopenharmony_ci eq(cf.getboolean('Types', 'boolean'), False) 1337db96d56Sopenharmony_ci eq(cf.get('Types', '123'), 'strange but acceptable') 1347db96d56Sopenharmony_ci eq(cf.get('This One Has A ] In It', 'forks'), 'spoons') 1357db96d56Sopenharmony_ci if self.allow_no_value: 1367db96d56Sopenharmony_ci eq(cf.get('NoValue', 'option-without-value'), None) 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci # test vars= and fallback= 1397db96d56Sopenharmony_ci eq(cf.get('Foo Bar', 'foo', fallback='baz'), 'bar1') 1407db96d56Sopenharmony_ci eq(cf.get('Foo Bar', 'foo', vars={'foo': 'baz'}), 'baz') 1417db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError): 1427db96d56Sopenharmony_ci cf.get('No Such Foo Bar', 'foo') 1437db96d56Sopenharmony_ci with self.assertRaises(configparser.NoOptionError): 1447db96d56Sopenharmony_ci cf.get('Foo Bar', 'no-such-foo') 1457db96d56Sopenharmony_ci eq(cf.get('No Such Foo Bar', 'foo', fallback='baz'), 'baz') 1467db96d56Sopenharmony_ci eq(cf.get('Foo Bar', 'no-such-foo', fallback='baz'), 'baz') 1477db96d56Sopenharmony_ci eq(cf.get('Spacey Bar', 'foo', fallback=None), 'bar2') 1487db96d56Sopenharmony_ci eq(cf.get('No Such Spacey Bar', 'foo', fallback=None), None) 1497db96d56Sopenharmony_ci eq(cf.getint('Types', 'int', fallback=18), 42) 1507db96d56Sopenharmony_ci eq(cf.getint('Types', 'no-such-int', fallback=18), 18) 1517db96d56Sopenharmony_ci eq(cf.getint('Types', 'no-such-int', fallback="18"), "18") # sic! 1527db96d56Sopenharmony_ci with self.assertRaises(configparser.NoOptionError): 1537db96d56Sopenharmony_ci cf.getint('Types', 'no-such-int') 1547db96d56Sopenharmony_ci self.assertAlmostEqual(cf.getfloat('Types', 'float', 1557db96d56Sopenharmony_ci fallback=0.0), 0.44) 1567db96d56Sopenharmony_ci self.assertAlmostEqual(cf.getfloat('Types', 'no-such-float', 1577db96d56Sopenharmony_ci fallback=0.0), 0.0) 1587db96d56Sopenharmony_ci eq(cf.getfloat('Types', 'no-such-float', fallback="0.0"), "0.0") # sic! 1597db96d56Sopenharmony_ci with self.assertRaises(configparser.NoOptionError): 1607db96d56Sopenharmony_ci cf.getfloat('Types', 'no-such-float') 1617db96d56Sopenharmony_ci eq(cf.getboolean('Types', 'boolean', fallback=True), False) 1627db96d56Sopenharmony_ci eq(cf.getboolean('Types', 'no-such-boolean', fallback="yes"), 1637db96d56Sopenharmony_ci "yes") # sic! 1647db96d56Sopenharmony_ci eq(cf.getboolean('Types', 'no-such-boolean', fallback=True), True) 1657db96d56Sopenharmony_ci with self.assertRaises(configparser.NoOptionError): 1667db96d56Sopenharmony_ci cf.getboolean('Types', 'no-such-boolean') 1677db96d56Sopenharmony_ci eq(cf.getboolean('No Such Types', 'boolean', fallback=True), True) 1687db96d56Sopenharmony_ci if self.allow_no_value: 1697db96d56Sopenharmony_ci eq(cf.get('NoValue', 'option-without-value', fallback=False), None) 1707db96d56Sopenharmony_ci eq(cf.get('NoValue', 'no-such-option-without-value', 1717db96d56Sopenharmony_ci fallback=False), False) 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci # mapping access 1747db96d56Sopenharmony_ci eq(cf['Foo Bar']['foo'], 'bar1') 1757db96d56Sopenharmony_ci eq(cf['Spacey Bar']['foo'], 'bar2') 1767db96d56Sopenharmony_ci section = cf['Spacey Bar From The Beginning'] 1777db96d56Sopenharmony_ci eq(section.name, 'Spacey Bar From The Beginning') 1787db96d56Sopenharmony_ci self.assertIs(section.parser, cf) 1797db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 1807db96d56Sopenharmony_ci section.name = 'Name is read-only' 1817db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 1827db96d56Sopenharmony_ci section.parser = 'Parser is read-only' 1837db96d56Sopenharmony_ci eq(section['foo'], 'bar3') 1847db96d56Sopenharmony_ci eq(section['baz'], 'qwe') 1857db96d56Sopenharmony_ci eq(cf['Commented Bar']['foo'], 'bar4') 1867db96d56Sopenharmony_ci eq(cf['Commented Bar']['baz'], 'qwe') 1877db96d56Sopenharmony_ci eq(cf['Spaces']['key with spaces'], 'value') 1887db96d56Sopenharmony_ci eq(cf['Spaces']['another with spaces'], 'splat!') 1897db96d56Sopenharmony_ci eq(cf['Long Line']['foo'], 1907db96d56Sopenharmony_ci 'this line is much, much longer than my editor\nlikes it.') 1917db96d56Sopenharmony_ci if self.allow_no_value: 1927db96d56Sopenharmony_ci eq(cf['NoValue']['option-without-value'], None) 1937db96d56Sopenharmony_ci # test vars= and fallback= 1947db96d56Sopenharmony_ci eq(cf['Foo Bar'].get('foo', 'baz'), 'bar1') 1957db96d56Sopenharmony_ci eq(cf['Foo Bar'].get('foo', fallback='baz'), 'bar1') 1967db96d56Sopenharmony_ci eq(cf['Foo Bar'].get('foo', vars={'foo': 'baz'}), 'baz') 1977db96d56Sopenharmony_ci with self.assertRaises(KeyError): 1987db96d56Sopenharmony_ci cf['No Such Foo Bar']['foo'] 1997db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2007db96d56Sopenharmony_ci cf['Foo Bar']['no-such-foo'] 2017db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2027db96d56Sopenharmony_ci cf['No Such Foo Bar'].get('foo', fallback='baz') 2037db96d56Sopenharmony_ci eq(cf['Foo Bar'].get('no-such-foo', 'baz'), 'baz') 2047db96d56Sopenharmony_ci eq(cf['Foo Bar'].get('no-such-foo', fallback='baz'), 'baz') 2057db96d56Sopenharmony_ci eq(cf['Foo Bar'].get('no-such-foo'), None) 2067db96d56Sopenharmony_ci eq(cf['Spacey Bar'].get('foo', None), 'bar2') 2077db96d56Sopenharmony_ci eq(cf['Spacey Bar'].get('foo', fallback=None), 'bar2') 2087db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2097db96d56Sopenharmony_ci cf['No Such Spacey Bar'].get('foo', None) 2107db96d56Sopenharmony_ci eq(cf['Types'].getint('int', 18), 42) 2117db96d56Sopenharmony_ci eq(cf['Types'].getint('int', fallback=18), 42) 2127db96d56Sopenharmony_ci eq(cf['Types'].getint('no-such-int', 18), 18) 2137db96d56Sopenharmony_ci eq(cf['Types'].getint('no-such-int', fallback=18), 18) 2147db96d56Sopenharmony_ci eq(cf['Types'].getint('no-such-int', "18"), "18") # sic! 2157db96d56Sopenharmony_ci eq(cf['Types'].getint('no-such-int', fallback="18"), "18") # sic! 2167db96d56Sopenharmony_ci eq(cf['Types'].getint('no-such-int'), None) 2177db96d56Sopenharmony_ci self.assertAlmostEqual(cf['Types'].getfloat('float', 0.0), 0.44) 2187db96d56Sopenharmony_ci self.assertAlmostEqual(cf['Types'].getfloat('float', 2197db96d56Sopenharmony_ci fallback=0.0), 0.44) 2207db96d56Sopenharmony_ci self.assertAlmostEqual(cf['Types'].getfloat('no-such-float', 0.0), 0.0) 2217db96d56Sopenharmony_ci self.assertAlmostEqual(cf['Types'].getfloat('no-such-float', 2227db96d56Sopenharmony_ci fallback=0.0), 0.0) 2237db96d56Sopenharmony_ci eq(cf['Types'].getfloat('no-such-float', "0.0"), "0.0") # sic! 2247db96d56Sopenharmony_ci eq(cf['Types'].getfloat('no-such-float', fallback="0.0"), "0.0") # sic! 2257db96d56Sopenharmony_ci eq(cf['Types'].getfloat('no-such-float'), None) 2267db96d56Sopenharmony_ci eq(cf['Types'].getboolean('boolean', True), False) 2277db96d56Sopenharmony_ci eq(cf['Types'].getboolean('boolean', fallback=True), False) 2287db96d56Sopenharmony_ci eq(cf['Types'].getboolean('no-such-boolean', "yes"), "yes") # sic! 2297db96d56Sopenharmony_ci eq(cf['Types'].getboolean('no-such-boolean', fallback="yes"), 2307db96d56Sopenharmony_ci "yes") # sic! 2317db96d56Sopenharmony_ci eq(cf['Types'].getboolean('no-such-boolean', True), True) 2327db96d56Sopenharmony_ci eq(cf['Types'].getboolean('no-such-boolean', fallback=True), True) 2337db96d56Sopenharmony_ci eq(cf['Types'].getboolean('no-such-boolean'), None) 2347db96d56Sopenharmony_ci if self.allow_no_value: 2357db96d56Sopenharmony_ci eq(cf['NoValue'].get('option-without-value', False), None) 2367db96d56Sopenharmony_ci eq(cf['NoValue'].get('option-without-value', fallback=False), None) 2377db96d56Sopenharmony_ci eq(cf['NoValue'].get('no-such-option-without-value', False), False) 2387db96d56Sopenharmony_ci eq(cf['NoValue'].get('no-such-option-without-value', 2397db96d56Sopenharmony_ci fallback=False), False) 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci # Make sure the right things happen for remove_section() and 2427db96d56Sopenharmony_ci # remove_option(); added to include check for SourceForge bug #123324. 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ci cf[self.default_section]['this_value'] = '1' 2457db96d56Sopenharmony_ci cf[self.default_section]['that_value'] = '2' 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci # API access 2487db96d56Sopenharmony_ci self.assertTrue(cf.remove_section('Spaces')) 2497db96d56Sopenharmony_ci self.assertFalse(cf.has_option('Spaces', 'key with spaces')) 2507db96d56Sopenharmony_ci self.assertFalse(cf.remove_section('Spaces')) 2517db96d56Sopenharmony_ci self.assertFalse(cf.remove_section(self.default_section)) 2527db96d56Sopenharmony_ci self.assertTrue(cf.remove_option('Foo Bar', 'foo'), 2537db96d56Sopenharmony_ci "remove_option() failed to report existence of option") 2547db96d56Sopenharmony_ci self.assertFalse(cf.has_option('Foo Bar', 'foo'), 2557db96d56Sopenharmony_ci "remove_option() failed to remove option") 2567db96d56Sopenharmony_ci self.assertFalse(cf.remove_option('Foo Bar', 'foo'), 2577db96d56Sopenharmony_ci "remove_option() failed to report non-existence of option" 2587db96d56Sopenharmony_ci " that was removed") 2597db96d56Sopenharmony_ci self.assertTrue(cf.has_option('Foo Bar', 'this_value')) 2607db96d56Sopenharmony_ci self.assertFalse(cf.remove_option('Foo Bar', 'this_value')) 2617db96d56Sopenharmony_ci self.assertTrue(cf.remove_option(self.default_section, 'this_value')) 2627db96d56Sopenharmony_ci self.assertFalse(cf.has_option('Foo Bar', 'this_value')) 2637db96d56Sopenharmony_ci self.assertFalse(cf.remove_option(self.default_section, 'this_value')) 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError) as cm: 2667db96d56Sopenharmony_ci cf.remove_option('No Such Section', 'foo') 2677db96d56Sopenharmony_ci self.assertEqual(cm.exception.args, ('No Such Section',)) 2687db96d56Sopenharmony_ci 2697db96d56Sopenharmony_ci eq(cf.get('Long Line', 'foo'), 2707db96d56Sopenharmony_ci 'this line is much, much longer than my editor\nlikes it.') 2717db96d56Sopenharmony_ci 2727db96d56Sopenharmony_ci # mapping access 2737db96d56Sopenharmony_ci del cf['Types'] 2747db96d56Sopenharmony_ci self.assertFalse('Types' in cf) 2757db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2767db96d56Sopenharmony_ci del cf['Types'] 2777db96d56Sopenharmony_ci with self.assertRaises(ValueError): 2787db96d56Sopenharmony_ci del cf[self.default_section] 2797db96d56Sopenharmony_ci del cf['Spacey Bar']['foo'] 2807db96d56Sopenharmony_ci self.assertFalse('foo' in cf['Spacey Bar']) 2817db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2827db96d56Sopenharmony_ci del cf['Spacey Bar']['foo'] 2837db96d56Sopenharmony_ci self.assertTrue('that_value' in cf['Spacey Bar']) 2847db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2857db96d56Sopenharmony_ci del cf['Spacey Bar']['that_value'] 2867db96d56Sopenharmony_ci del cf[self.default_section]['that_value'] 2877db96d56Sopenharmony_ci self.assertFalse('that_value' in cf['Spacey Bar']) 2887db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2897db96d56Sopenharmony_ci del cf[self.default_section]['that_value'] 2907db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2917db96d56Sopenharmony_ci del cf['No Such Section']['foo'] 2927db96d56Sopenharmony_ci 2937db96d56Sopenharmony_ci # Don't add new asserts below in this method as most of the options 2947db96d56Sopenharmony_ci # and sections are now removed. 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ci def test_basic(self): 2977db96d56Sopenharmony_ci config_string = """\ 2987db96d56Sopenharmony_ci[Foo Bar] 2997db96d56Sopenharmony_cifoo{0[0]}bar1 3007db96d56Sopenharmony_ci[Spacey Bar] 3017db96d56Sopenharmony_cifoo {0[0]} bar2 3027db96d56Sopenharmony_ci[Spacey Bar From The Beginning] 3037db96d56Sopenharmony_ci foo {0[0]} bar3 3047db96d56Sopenharmony_ci baz {0[0]} qwe 3057db96d56Sopenharmony_ci[Commented Bar] 3067db96d56Sopenharmony_cifoo{0[1]} bar4 {1[1]} comment 3077db96d56Sopenharmony_cibaz{0[0]}qwe {1[0]}another one 3087db96d56Sopenharmony_ci[Long Line] 3097db96d56Sopenharmony_cifoo{0[1]} this line is much, much longer than my editor 3107db96d56Sopenharmony_ci likes it. 3117db96d56Sopenharmony_ci[Section\\with$weird%characters[\t] 3127db96d56Sopenharmony_ci[Internationalized Stuff] 3137db96d56Sopenharmony_cifoo[bg]{0[1]} Bulgarian 3147db96d56Sopenharmony_cifoo{0[0]}Default 3157db96d56Sopenharmony_cifoo[en]{0[0]}English 3167db96d56Sopenharmony_cifoo[de]{0[0]}Deutsch 3177db96d56Sopenharmony_ci[Spaces] 3187db96d56Sopenharmony_cikey with spaces {0[1]} value 3197db96d56Sopenharmony_cianother with spaces {0[0]} splat! 3207db96d56Sopenharmony_ci[Types] 3217db96d56Sopenharmony_ciint {0[1]} 42 3227db96d56Sopenharmony_cifloat {0[0]} 0.44 3237db96d56Sopenharmony_ciboolean {0[0]} NO 3247db96d56Sopenharmony_ci123 {0[1]} strange but acceptable 3257db96d56Sopenharmony_ci[This One Has A ] In It] 3267db96d56Sopenharmony_ci forks {0[0]} spoons 3277db96d56Sopenharmony_ci""".format(self.delimiters, self.comment_prefixes) 3287db96d56Sopenharmony_ci if self.allow_no_value: 3297db96d56Sopenharmony_ci config_string += ( 3307db96d56Sopenharmony_ci "[NoValue]\n" 3317db96d56Sopenharmony_ci "option-without-value\n" 3327db96d56Sopenharmony_ci ) 3337db96d56Sopenharmony_ci cf = self.fromstring(config_string) 3347db96d56Sopenharmony_ci self.basic_test(cf) 3357db96d56Sopenharmony_ci if self.strict: 3367db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateOptionError): 3377db96d56Sopenharmony_ci cf.read_string(textwrap.dedent("""\ 3387db96d56Sopenharmony_ci [Duplicate Options Here] 3397db96d56Sopenharmony_ci option {0[0]} with a value 3407db96d56Sopenharmony_ci option {0[1]} with another value 3417db96d56Sopenharmony_ci """.format(self.delimiters))) 3427db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateSectionError): 3437db96d56Sopenharmony_ci cf.read_string(textwrap.dedent("""\ 3447db96d56Sopenharmony_ci [And Now For Something] 3457db96d56Sopenharmony_ci completely different {0[0]} True 3467db96d56Sopenharmony_ci [And Now For Something] 3477db96d56Sopenharmony_ci the larch {0[1]} 1 3487db96d56Sopenharmony_ci """.format(self.delimiters))) 3497db96d56Sopenharmony_ci else: 3507db96d56Sopenharmony_ci cf.read_string(textwrap.dedent("""\ 3517db96d56Sopenharmony_ci [Duplicate Options Here] 3527db96d56Sopenharmony_ci option {0[0]} with a value 3537db96d56Sopenharmony_ci option {0[1]} with another value 3547db96d56Sopenharmony_ci """.format(self.delimiters))) 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ci cf.read_string(textwrap.dedent("""\ 3577db96d56Sopenharmony_ci [And Now For Something] 3587db96d56Sopenharmony_ci completely different {0[0]} True 3597db96d56Sopenharmony_ci [And Now For Something] 3607db96d56Sopenharmony_ci the larch {0[1]} 1 3617db96d56Sopenharmony_ci """.format(self.delimiters))) 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci def test_basic_from_dict(self): 3647db96d56Sopenharmony_ci config = { 3657db96d56Sopenharmony_ci "Foo Bar": { 3667db96d56Sopenharmony_ci "foo": "bar1", 3677db96d56Sopenharmony_ci }, 3687db96d56Sopenharmony_ci "Spacey Bar": { 3697db96d56Sopenharmony_ci "foo": "bar2", 3707db96d56Sopenharmony_ci }, 3717db96d56Sopenharmony_ci "Spacey Bar From The Beginning": { 3727db96d56Sopenharmony_ci "foo": "bar3", 3737db96d56Sopenharmony_ci "baz": "qwe", 3747db96d56Sopenharmony_ci }, 3757db96d56Sopenharmony_ci "Commented Bar": { 3767db96d56Sopenharmony_ci "foo": "bar4", 3777db96d56Sopenharmony_ci "baz": "qwe", 3787db96d56Sopenharmony_ci }, 3797db96d56Sopenharmony_ci "Long Line": { 3807db96d56Sopenharmony_ci "foo": "this line is much, much longer than my editor\nlikes " 3817db96d56Sopenharmony_ci "it.", 3827db96d56Sopenharmony_ci }, 3837db96d56Sopenharmony_ci "Section\\with$weird%characters[\t": { 3847db96d56Sopenharmony_ci }, 3857db96d56Sopenharmony_ci "Internationalized Stuff": { 3867db96d56Sopenharmony_ci "foo[bg]": "Bulgarian", 3877db96d56Sopenharmony_ci "foo": "Default", 3887db96d56Sopenharmony_ci "foo[en]": "English", 3897db96d56Sopenharmony_ci "foo[de]": "Deutsch", 3907db96d56Sopenharmony_ci }, 3917db96d56Sopenharmony_ci "Spaces": { 3927db96d56Sopenharmony_ci "key with spaces": "value", 3937db96d56Sopenharmony_ci "another with spaces": "splat!", 3947db96d56Sopenharmony_ci }, 3957db96d56Sopenharmony_ci "Types": { 3967db96d56Sopenharmony_ci "int": 42, 3977db96d56Sopenharmony_ci "float": 0.44, 3987db96d56Sopenharmony_ci "boolean": False, 3997db96d56Sopenharmony_ci 123: "strange but acceptable", 4007db96d56Sopenharmony_ci }, 4017db96d56Sopenharmony_ci "This One Has A ] In It": { 4027db96d56Sopenharmony_ci "forks": "spoons" 4037db96d56Sopenharmony_ci }, 4047db96d56Sopenharmony_ci } 4057db96d56Sopenharmony_ci if self.allow_no_value: 4067db96d56Sopenharmony_ci config.update({ 4077db96d56Sopenharmony_ci "NoValue": { 4087db96d56Sopenharmony_ci "option-without-value": None, 4097db96d56Sopenharmony_ci } 4107db96d56Sopenharmony_ci }) 4117db96d56Sopenharmony_ci cf = self.newconfig() 4127db96d56Sopenharmony_ci cf.read_dict(config) 4137db96d56Sopenharmony_ci self.basic_test(cf) 4147db96d56Sopenharmony_ci if self.strict: 4157db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateSectionError): 4167db96d56Sopenharmony_ci cf.read_dict({ 4177db96d56Sopenharmony_ci '1': {'key': 'value'}, 4187db96d56Sopenharmony_ci 1: {'key2': 'value2'}, 4197db96d56Sopenharmony_ci }) 4207db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateOptionError): 4217db96d56Sopenharmony_ci cf.read_dict({ 4227db96d56Sopenharmony_ci "Duplicate Options Here": { 4237db96d56Sopenharmony_ci 'option': 'with a value', 4247db96d56Sopenharmony_ci 'OPTION': 'with another value', 4257db96d56Sopenharmony_ci }, 4267db96d56Sopenharmony_ci }) 4277db96d56Sopenharmony_ci else: 4287db96d56Sopenharmony_ci cf.read_dict({ 4297db96d56Sopenharmony_ci 'section': {'key': 'value'}, 4307db96d56Sopenharmony_ci 'SECTION': {'key2': 'value2'}, 4317db96d56Sopenharmony_ci }) 4327db96d56Sopenharmony_ci cf.read_dict({ 4337db96d56Sopenharmony_ci "Duplicate Options Here": { 4347db96d56Sopenharmony_ci 'option': 'with a value', 4357db96d56Sopenharmony_ci 'OPTION': 'with another value', 4367db96d56Sopenharmony_ci }, 4377db96d56Sopenharmony_ci }) 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ci def test_case_sensitivity(self): 4407db96d56Sopenharmony_ci cf = self.newconfig() 4417db96d56Sopenharmony_ci cf.add_section("A") 4427db96d56Sopenharmony_ci cf.add_section("a") 4437db96d56Sopenharmony_ci cf.add_section("B") 4447db96d56Sopenharmony_ci L = cf.sections() 4457db96d56Sopenharmony_ci L.sort() 4467db96d56Sopenharmony_ci eq = self.assertEqual 4477db96d56Sopenharmony_ci eq(L, ["A", "B", "a"]) 4487db96d56Sopenharmony_ci cf.set("a", "B", "value") 4497db96d56Sopenharmony_ci eq(cf.options("a"), ["b"]) 4507db96d56Sopenharmony_ci eq(cf.get("a", "b"), "value", 4517db96d56Sopenharmony_ci "could not locate option, expecting case-insensitive option names") 4527db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError): 4537db96d56Sopenharmony_ci # section names are case-sensitive 4547db96d56Sopenharmony_ci cf.set("b", "A", "value") 4557db96d56Sopenharmony_ci self.assertTrue(cf.has_option("a", "b")) 4567db96d56Sopenharmony_ci self.assertFalse(cf.has_option("b", "b")) 4577db96d56Sopenharmony_ci cf.set("A", "A-B", "A-B value") 4587db96d56Sopenharmony_ci for opt in ("a-b", "A-b", "a-B", "A-B"): 4597db96d56Sopenharmony_ci self.assertTrue( 4607db96d56Sopenharmony_ci cf.has_option("A", opt), 4617db96d56Sopenharmony_ci "has_option() returned false for option which should exist") 4627db96d56Sopenharmony_ci eq(cf.options("A"), ["a-b"]) 4637db96d56Sopenharmony_ci eq(cf.options("a"), ["b"]) 4647db96d56Sopenharmony_ci cf.remove_option("a", "B") 4657db96d56Sopenharmony_ci eq(cf.options("a"), []) 4667db96d56Sopenharmony_ci 4677db96d56Sopenharmony_ci # SF bug #432369: 4687db96d56Sopenharmony_ci cf = self.fromstring( 4697db96d56Sopenharmony_ci "[MySection]\nOption{} first line \n\tsecond line \n".format( 4707db96d56Sopenharmony_ci self.delimiters[0])) 4717db96d56Sopenharmony_ci eq(cf.options("MySection"), ["option"]) 4727db96d56Sopenharmony_ci eq(cf.get("MySection", "Option"), "first line\nsecond line") 4737db96d56Sopenharmony_ci 4747db96d56Sopenharmony_ci # SF bug #561822: 4757db96d56Sopenharmony_ci cf = self.fromstring("[section]\n" 4767db96d56Sopenharmony_ci "nekey{}nevalue\n".format(self.delimiters[0]), 4777db96d56Sopenharmony_ci defaults={"key":"value"}) 4787db96d56Sopenharmony_ci self.assertTrue(cf.has_option("section", "Key")) 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci 4817db96d56Sopenharmony_ci def test_case_sensitivity_mapping_access(self): 4827db96d56Sopenharmony_ci cf = self.newconfig() 4837db96d56Sopenharmony_ci cf["A"] = {} 4847db96d56Sopenharmony_ci cf["a"] = {"B": "value"} 4857db96d56Sopenharmony_ci cf["B"] = {} 4867db96d56Sopenharmony_ci L = [section for section in cf] 4877db96d56Sopenharmony_ci L.sort() 4887db96d56Sopenharmony_ci eq = self.assertEqual 4897db96d56Sopenharmony_ci elem_eq = self.assertCountEqual 4907db96d56Sopenharmony_ci eq(L, sorted(["A", "B", self.default_section, "a"])) 4917db96d56Sopenharmony_ci eq(cf["a"].keys(), {"b"}) 4927db96d56Sopenharmony_ci eq(cf["a"]["b"], "value", 4937db96d56Sopenharmony_ci "could not locate option, expecting case-insensitive option names") 4947db96d56Sopenharmony_ci with self.assertRaises(KeyError): 4957db96d56Sopenharmony_ci # section names are case-sensitive 4967db96d56Sopenharmony_ci cf["b"]["A"] = "value" 4977db96d56Sopenharmony_ci self.assertTrue("b" in cf["a"]) 4987db96d56Sopenharmony_ci cf["A"]["A-B"] = "A-B value" 4997db96d56Sopenharmony_ci for opt in ("a-b", "A-b", "a-B", "A-B"): 5007db96d56Sopenharmony_ci self.assertTrue( 5017db96d56Sopenharmony_ci opt in cf["A"], 5027db96d56Sopenharmony_ci "has_option() returned false for option which should exist") 5037db96d56Sopenharmony_ci eq(cf["A"].keys(), {"a-b"}) 5047db96d56Sopenharmony_ci eq(cf["a"].keys(), {"b"}) 5057db96d56Sopenharmony_ci del cf["a"]["B"] 5067db96d56Sopenharmony_ci elem_eq(cf["a"].keys(), {}) 5077db96d56Sopenharmony_ci 5087db96d56Sopenharmony_ci # SF bug #432369: 5097db96d56Sopenharmony_ci cf = self.fromstring( 5107db96d56Sopenharmony_ci "[MySection]\nOption{} first line \n\tsecond line \n".format( 5117db96d56Sopenharmony_ci self.delimiters[0])) 5127db96d56Sopenharmony_ci eq(cf["MySection"].keys(), {"option"}) 5137db96d56Sopenharmony_ci eq(cf["MySection"]["Option"], "first line\nsecond line") 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci # SF bug #561822: 5167db96d56Sopenharmony_ci cf = self.fromstring("[section]\n" 5177db96d56Sopenharmony_ci "nekey{}nevalue\n".format(self.delimiters[0]), 5187db96d56Sopenharmony_ci defaults={"key":"value"}) 5197db96d56Sopenharmony_ci self.assertTrue("Key" in cf["section"]) 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_ci def test_default_case_sensitivity(self): 5227db96d56Sopenharmony_ci cf = self.newconfig({"foo": "Bar"}) 5237db96d56Sopenharmony_ci self.assertEqual( 5247db96d56Sopenharmony_ci cf.get(self.default_section, "Foo"), "Bar", 5257db96d56Sopenharmony_ci "could not locate option, expecting case-insensitive option names") 5267db96d56Sopenharmony_ci cf = self.newconfig({"Foo": "Bar"}) 5277db96d56Sopenharmony_ci self.assertEqual( 5287db96d56Sopenharmony_ci cf.get(self.default_section, "Foo"), "Bar", 5297db96d56Sopenharmony_ci "could not locate option, expecting case-insensitive defaults") 5307db96d56Sopenharmony_ci 5317db96d56Sopenharmony_ci def test_parse_errors(self): 5327db96d56Sopenharmony_ci cf = self.newconfig() 5337db96d56Sopenharmony_ci self.parse_error(cf, configparser.ParsingError, 5347db96d56Sopenharmony_ci "[Foo]\n" 5357db96d56Sopenharmony_ci "{}val-without-opt-name\n".format(self.delimiters[0])) 5367db96d56Sopenharmony_ci self.parse_error(cf, configparser.ParsingError, 5377db96d56Sopenharmony_ci "[Foo]\n" 5387db96d56Sopenharmony_ci "{}val-without-opt-name\n".format(self.delimiters[1])) 5397db96d56Sopenharmony_ci e = self.parse_error(cf, configparser.MissingSectionHeaderError, 5407db96d56Sopenharmony_ci "No Section!\n") 5417db96d56Sopenharmony_ci self.assertEqual(e.args, ('<???>', 1, "No Section!\n")) 5427db96d56Sopenharmony_ci if not self.allow_no_value: 5437db96d56Sopenharmony_ci e = self.parse_error(cf, configparser.ParsingError, 5447db96d56Sopenharmony_ci "[Foo]\n wrong-indent\n") 5457db96d56Sopenharmony_ci self.assertEqual(e.args, ('<???>',)) 5467db96d56Sopenharmony_ci # read_file on a real file 5477db96d56Sopenharmony_ci tricky = support.findfile("cfgparser.3") 5487db96d56Sopenharmony_ci if self.delimiters[0] == '=': 5497db96d56Sopenharmony_ci error = configparser.ParsingError 5507db96d56Sopenharmony_ci expected = (tricky,) 5517db96d56Sopenharmony_ci else: 5527db96d56Sopenharmony_ci error = configparser.MissingSectionHeaderError 5537db96d56Sopenharmony_ci expected = (tricky, 1, 5547db96d56Sopenharmony_ci ' # INI with as many tricky parts as possible\n') 5557db96d56Sopenharmony_ci with open(tricky, encoding='utf-8') as f: 5567db96d56Sopenharmony_ci e = self.parse_error(cf, error, f) 5577db96d56Sopenharmony_ci self.assertEqual(e.args, expected) 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_ci def parse_error(self, cf, exc, src): 5607db96d56Sopenharmony_ci if hasattr(src, 'readline'): 5617db96d56Sopenharmony_ci sio = src 5627db96d56Sopenharmony_ci else: 5637db96d56Sopenharmony_ci sio = io.StringIO(src) 5647db96d56Sopenharmony_ci with self.assertRaises(exc) as cm: 5657db96d56Sopenharmony_ci cf.read_file(sio) 5667db96d56Sopenharmony_ci return cm.exception 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_ci def test_query_errors(self): 5697db96d56Sopenharmony_ci cf = self.newconfig() 5707db96d56Sopenharmony_ci self.assertEqual(cf.sections(), [], 5717db96d56Sopenharmony_ci "new ConfigParser should have no defined sections") 5727db96d56Sopenharmony_ci self.assertFalse(cf.has_section("Foo"), 5737db96d56Sopenharmony_ci "new ConfigParser should have no acknowledged " 5747db96d56Sopenharmony_ci "sections") 5757db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError): 5767db96d56Sopenharmony_ci cf.options("Foo") 5777db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError): 5787db96d56Sopenharmony_ci cf.set("foo", "bar", "value") 5797db96d56Sopenharmony_ci e = self.get_error(cf, configparser.NoSectionError, "foo", "bar") 5807db96d56Sopenharmony_ci self.assertEqual(e.args, ("foo",)) 5817db96d56Sopenharmony_ci cf.add_section("foo") 5827db96d56Sopenharmony_ci e = self.get_error(cf, configparser.NoOptionError, "foo", "bar") 5837db96d56Sopenharmony_ci self.assertEqual(e.args, ("bar", "foo")) 5847db96d56Sopenharmony_ci 5857db96d56Sopenharmony_ci def get_error(self, cf, exc, section, option): 5867db96d56Sopenharmony_ci try: 5877db96d56Sopenharmony_ci cf.get(section, option) 5887db96d56Sopenharmony_ci except exc as e: 5897db96d56Sopenharmony_ci return e 5907db96d56Sopenharmony_ci else: 5917db96d56Sopenharmony_ci self.fail("expected exception type %s.%s" 5927db96d56Sopenharmony_ci % (exc.__module__, exc.__qualname__)) 5937db96d56Sopenharmony_ci 5947db96d56Sopenharmony_ci def test_boolean(self): 5957db96d56Sopenharmony_ci cf = self.fromstring( 5967db96d56Sopenharmony_ci "[BOOLTEST]\n" 5977db96d56Sopenharmony_ci "T1{equals}1\n" 5987db96d56Sopenharmony_ci "T2{equals}TRUE\n" 5997db96d56Sopenharmony_ci "T3{equals}True\n" 6007db96d56Sopenharmony_ci "T4{equals}oN\n" 6017db96d56Sopenharmony_ci "T5{equals}yes\n" 6027db96d56Sopenharmony_ci "F1{equals}0\n" 6037db96d56Sopenharmony_ci "F2{equals}FALSE\n" 6047db96d56Sopenharmony_ci "F3{equals}False\n" 6057db96d56Sopenharmony_ci "F4{equals}oFF\n" 6067db96d56Sopenharmony_ci "F5{equals}nO\n" 6077db96d56Sopenharmony_ci "E1{equals}2\n" 6087db96d56Sopenharmony_ci "E2{equals}foo\n" 6097db96d56Sopenharmony_ci "E3{equals}-1\n" 6107db96d56Sopenharmony_ci "E4{equals}0.1\n" 6117db96d56Sopenharmony_ci "E5{equals}FALSE AND MORE".format(equals=self.delimiters[0]) 6127db96d56Sopenharmony_ci ) 6137db96d56Sopenharmony_ci for x in range(1, 5): 6147db96d56Sopenharmony_ci self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x)) 6157db96d56Sopenharmony_ci self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x)) 6167db96d56Sopenharmony_ci self.assertRaises(ValueError, 6177db96d56Sopenharmony_ci cf.getboolean, 'BOOLTEST', 'e%d' % x) 6187db96d56Sopenharmony_ci 6197db96d56Sopenharmony_ci def test_weird_errors(self): 6207db96d56Sopenharmony_ci cf = self.newconfig() 6217db96d56Sopenharmony_ci cf.add_section("Foo") 6227db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateSectionError) as cm: 6237db96d56Sopenharmony_ci cf.add_section("Foo") 6247db96d56Sopenharmony_ci e = cm.exception 6257db96d56Sopenharmony_ci self.assertEqual(str(e), "Section 'Foo' already exists") 6267db96d56Sopenharmony_ci self.assertEqual(e.args, ("Foo", None, None)) 6277db96d56Sopenharmony_ci 6287db96d56Sopenharmony_ci if self.strict: 6297db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateSectionError) as cm: 6307db96d56Sopenharmony_ci cf.read_string(textwrap.dedent("""\ 6317db96d56Sopenharmony_ci [Foo] 6327db96d56Sopenharmony_ci will this be added{equals}True 6337db96d56Sopenharmony_ci [Bar] 6347db96d56Sopenharmony_ci what about this{equals}True 6357db96d56Sopenharmony_ci [Foo] 6367db96d56Sopenharmony_ci oops{equals}this won't 6377db96d56Sopenharmony_ci """.format(equals=self.delimiters[0])), source='<foo-bar>') 6387db96d56Sopenharmony_ci e = cm.exception 6397db96d56Sopenharmony_ci self.assertEqual(str(e), "While reading from '<foo-bar>' " 6407db96d56Sopenharmony_ci "[line 5]: section 'Foo' already exists") 6417db96d56Sopenharmony_ci self.assertEqual(e.args, ("Foo", '<foo-bar>', 5)) 6427db96d56Sopenharmony_ci 6437db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateOptionError) as cm: 6447db96d56Sopenharmony_ci cf.read_dict({'Bar': {'opt': 'val', 'OPT': 'is really `opt`'}}) 6457db96d56Sopenharmony_ci e = cm.exception 6467db96d56Sopenharmony_ci self.assertEqual(str(e), "While reading from '<dict>': option " 6477db96d56Sopenharmony_ci "'opt' in section 'Bar' already exists") 6487db96d56Sopenharmony_ci self.assertEqual(e.args, ("Bar", "opt", "<dict>", None)) 6497db96d56Sopenharmony_ci 6507db96d56Sopenharmony_ci def test_write(self): 6517db96d56Sopenharmony_ci config_string = ( 6527db96d56Sopenharmony_ci "[Long Line]\n" 6537db96d56Sopenharmony_ci "foo{0[0]} this line is much, much longer than my editor\n" 6547db96d56Sopenharmony_ci " likes it.\n" 6557db96d56Sopenharmony_ci "[{default_section}]\n" 6567db96d56Sopenharmony_ci "foo{0[1]} another very\n" 6577db96d56Sopenharmony_ci " long line\n" 6587db96d56Sopenharmony_ci "[Long Line - With Comments!]\n" 6597db96d56Sopenharmony_ci "test {0[1]} we {comment} can\n" 6607db96d56Sopenharmony_ci " also {comment} place\n" 6617db96d56Sopenharmony_ci " comments {comment} in\n" 6627db96d56Sopenharmony_ci " multiline {comment} values" 6637db96d56Sopenharmony_ci "\n".format(self.delimiters, comment=self.comment_prefixes[0], 6647db96d56Sopenharmony_ci default_section=self.default_section) 6657db96d56Sopenharmony_ci ) 6667db96d56Sopenharmony_ci if self.allow_no_value: 6677db96d56Sopenharmony_ci config_string += ( 6687db96d56Sopenharmony_ci "[Valueless]\n" 6697db96d56Sopenharmony_ci "option-without-value\n" 6707db96d56Sopenharmony_ci ) 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci cf = self.fromstring(config_string) 6737db96d56Sopenharmony_ci for space_around_delimiters in (True, False): 6747db96d56Sopenharmony_ci output = io.StringIO() 6757db96d56Sopenharmony_ci cf.write(output, space_around_delimiters=space_around_delimiters) 6767db96d56Sopenharmony_ci delimiter = self.delimiters[0] 6777db96d56Sopenharmony_ci if space_around_delimiters: 6787db96d56Sopenharmony_ci delimiter = " {} ".format(delimiter) 6797db96d56Sopenharmony_ci expect_string = ( 6807db96d56Sopenharmony_ci "[{default_section}]\n" 6817db96d56Sopenharmony_ci "foo{equals}another very\n" 6827db96d56Sopenharmony_ci "\tlong line\n" 6837db96d56Sopenharmony_ci "\n" 6847db96d56Sopenharmony_ci "[Long Line]\n" 6857db96d56Sopenharmony_ci "foo{equals}this line is much, much longer than my editor\n" 6867db96d56Sopenharmony_ci "\tlikes it.\n" 6877db96d56Sopenharmony_ci "\n" 6887db96d56Sopenharmony_ci "[Long Line - With Comments!]\n" 6897db96d56Sopenharmony_ci "test{equals}we\n" 6907db96d56Sopenharmony_ci "\talso\n" 6917db96d56Sopenharmony_ci "\tcomments\n" 6927db96d56Sopenharmony_ci "\tmultiline\n" 6937db96d56Sopenharmony_ci "\n".format(equals=delimiter, 6947db96d56Sopenharmony_ci default_section=self.default_section) 6957db96d56Sopenharmony_ci ) 6967db96d56Sopenharmony_ci if self.allow_no_value: 6977db96d56Sopenharmony_ci expect_string += ( 6987db96d56Sopenharmony_ci "[Valueless]\n" 6997db96d56Sopenharmony_ci "option-without-value\n" 7007db96d56Sopenharmony_ci "\n" 7017db96d56Sopenharmony_ci ) 7027db96d56Sopenharmony_ci self.assertEqual(output.getvalue(), expect_string) 7037db96d56Sopenharmony_ci 7047db96d56Sopenharmony_ci def test_set_string_types(self): 7057db96d56Sopenharmony_ci cf = self.fromstring("[sect]\n" 7067db96d56Sopenharmony_ci "option1{eq}foo\n".format(eq=self.delimiters[0])) 7077db96d56Sopenharmony_ci # Check that we don't get an exception when setting values in 7087db96d56Sopenharmony_ci # an existing section using strings: 7097db96d56Sopenharmony_ci class mystr(str): 7107db96d56Sopenharmony_ci pass 7117db96d56Sopenharmony_ci cf.set("sect", "option1", "splat") 7127db96d56Sopenharmony_ci cf.set("sect", "option1", mystr("splat")) 7137db96d56Sopenharmony_ci cf.set("sect", "option2", "splat") 7147db96d56Sopenharmony_ci cf.set("sect", "option2", mystr("splat")) 7157db96d56Sopenharmony_ci cf.set("sect", "option1", "splat") 7167db96d56Sopenharmony_ci cf.set("sect", "option2", "splat") 7177db96d56Sopenharmony_ci 7187db96d56Sopenharmony_ci def test_read_returns_file_list(self): 7197db96d56Sopenharmony_ci if self.delimiters[0] != '=': 7207db96d56Sopenharmony_ci self.skipTest('incompatible format') 7217db96d56Sopenharmony_ci file1 = support.findfile("cfgparser.1") 7227db96d56Sopenharmony_ci # check when we pass a mix of readable and non-readable files: 7237db96d56Sopenharmony_ci cf = self.newconfig() 7247db96d56Sopenharmony_ci parsed_files = cf.read([file1, "nonexistent-file"], encoding="utf-8") 7257db96d56Sopenharmony_ci self.assertEqual(parsed_files, [file1]) 7267db96d56Sopenharmony_ci self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") 7277db96d56Sopenharmony_ci # check when we pass only a filename: 7287db96d56Sopenharmony_ci cf = self.newconfig() 7297db96d56Sopenharmony_ci parsed_files = cf.read(file1, encoding="utf-8") 7307db96d56Sopenharmony_ci self.assertEqual(parsed_files, [file1]) 7317db96d56Sopenharmony_ci self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") 7327db96d56Sopenharmony_ci # check when we pass only a Path object: 7337db96d56Sopenharmony_ci cf = self.newconfig() 7347db96d56Sopenharmony_ci parsed_files = cf.read(pathlib.Path(file1), encoding="utf-8") 7357db96d56Sopenharmony_ci self.assertEqual(parsed_files, [file1]) 7367db96d56Sopenharmony_ci self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") 7377db96d56Sopenharmony_ci # check when we passed both a filename and a Path object: 7387db96d56Sopenharmony_ci cf = self.newconfig() 7397db96d56Sopenharmony_ci parsed_files = cf.read([pathlib.Path(file1), file1], encoding="utf-8") 7407db96d56Sopenharmony_ci self.assertEqual(parsed_files, [file1, file1]) 7417db96d56Sopenharmony_ci self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") 7427db96d56Sopenharmony_ci # check when we pass only missing files: 7437db96d56Sopenharmony_ci cf = self.newconfig() 7447db96d56Sopenharmony_ci parsed_files = cf.read(["nonexistent-file"], encoding="utf-8") 7457db96d56Sopenharmony_ci self.assertEqual(parsed_files, []) 7467db96d56Sopenharmony_ci # check when we pass no files: 7477db96d56Sopenharmony_ci cf = self.newconfig() 7487db96d56Sopenharmony_ci parsed_files = cf.read([], encoding="utf-8") 7497db96d56Sopenharmony_ci self.assertEqual(parsed_files, []) 7507db96d56Sopenharmony_ci 7517db96d56Sopenharmony_ci def test_read_returns_file_list_with_bytestring_path(self): 7527db96d56Sopenharmony_ci if self.delimiters[0] != '=': 7537db96d56Sopenharmony_ci self.skipTest('incompatible format') 7547db96d56Sopenharmony_ci file1_bytestring = support.findfile("cfgparser.1").encode() 7557db96d56Sopenharmony_ci # check when passing an existing bytestring path 7567db96d56Sopenharmony_ci cf = self.newconfig() 7577db96d56Sopenharmony_ci parsed_files = cf.read(file1_bytestring, encoding="utf-8") 7587db96d56Sopenharmony_ci self.assertEqual(parsed_files, [file1_bytestring]) 7597db96d56Sopenharmony_ci # check when passing an non-existing bytestring path 7607db96d56Sopenharmony_ci cf = self.newconfig() 7617db96d56Sopenharmony_ci parsed_files = cf.read(b'nonexistent-file', encoding="utf-8") 7627db96d56Sopenharmony_ci self.assertEqual(parsed_files, []) 7637db96d56Sopenharmony_ci # check when passing both an existing and non-existing bytestring path 7647db96d56Sopenharmony_ci cf = self.newconfig() 7657db96d56Sopenharmony_ci parsed_files = cf.read([file1_bytestring, b'nonexistent-file'], encoding="utf-8") 7667db96d56Sopenharmony_ci self.assertEqual(parsed_files, [file1_bytestring]) 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_ci # shared by subclasses 7697db96d56Sopenharmony_ci def get_interpolation_config(self): 7707db96d56Sopenharmony_ci return self.fromstring( 7717db96d56Sopenharmony_ci "[Foo]\n" 7727db96d56Sopenharmony_ci "bar{equals}something %(with1)s interpolation (1 step)\n" 7737db96d56Sopenharmony_ci "bar9{equals}something %(with9)s lots of interpolation (9 steps)\n" 7747db96d56Sopenharmony_ci "bar10{equals}something %(with10)s lots of interpolation (10 steps)\n" 7757db96d56Sopenharmony_ci "bar11{equals}something %(with11)s lots of interpolation (11 steps)\n" 7767db96d56Sopenharmony_ci "with11{equals}%(with10)s\n" 7777db96d56Sopenharmony_ci "with10{equals}%(with9)s\n" 7787db96d56Sopenharmony_ci "with9{equals}%(with8)s\n" 7797db96d56Sopenharmony_ci "with8{equals}%(With7)s\n" 7807db96d56Sopenharmony_ci "with7{equals}%(WITH6)s\n" 7817db96d56Sopenharmony_ci "with6{equals}%(with5)s\n" 7827db96d56Sopenharmony_ci "With5{equals}%(with4)s\n" 7837db96d56Sopenharmony_ci "WITH4{equals}%(with3)s\n" 7847db96d56Sopenharmony_ci "with3{equals}%(with2)s\n" 7857db96d56Sopenharmony_ci "with2{equals}%(with1)s\n" 7867db96d56Sopenharmony_ci "with1{equals}with\n" 7877db96d56Sopenharmony_ci "\n" 7887db96d56Sopenharmony_ci "[Mutual Recursion]\n" 7897db96d56Sopenharmony_ci "foo{equals}%(bar)s\n" 7907db96d56Sopenharmony_ci "bar{equals}%(foo)s\n" 7917db96d56Sopenharmony_ci "\n" 7927db96d56Sopenharmony_ci "[Interpolation Error]\n" 7937db96d56Sopenharmony_ci # no definition for 'reference' 7947db96d56Sopenharmony_ci "name{equals}%(reference)s\n".format(equals=self.delimiters[0])) 7957db96d56Sopenharmony_ci 7967db96d56Sopenharmony_ci def check_items_config(self, expected): 7977db96d56Sopenharmony_ci cf = self.fromstring(""" 7987db96d56Sopenharmony_ci [section] 7997db96d56Sopenharmony_ci name {0[0]} %(value)s 8007db96d56Sopenharmony_ci key{0[1]} |%(name)s| 8017db96d56Sopenharmony_ci getdefault{0[1]} |%(default)s| 8027db96d56Sopenharmony_ci """.format(self.delimiters), defaults={"default": "<default>"}) 8037db96d56Sopenharmony_ci L = list(cf.items("section", vars={'value': 'value'})) 8047db96d56Sopenharmony_ci L.sort() 8057db96d56Sopenharmony_ci self.assertEqual(L, expected) 8067db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError): 8077db96d56Sopenharmony_ci cf.items("no such section") 8087db96d56Sopenharmony_ci 8097db96d56Sopenharmony_ci def test_popitem(self): 8107db96d56Sopenharmony_ci cf = self.fromstring(""" 8117db96d56Sopenharmony_ci [section1] 8127db96d56Sopenharmony_ci name1 {0[0]} value1 8137db96d56Sopenharmony_ci [section2] 8147db96d56Sopenharmony_ci name2 {0[0]} value2 8157db96d56Sopenharmony_ci [section3] 8167db96d56Sopenharmony_ci name3 {0[0]} value3 8177db96d56Sopenharmony_ci """.format(self.delimiters), defaults={"default": "<default>"}) 8187db96d56Sopenharmony_ci self.assertEqual(cf.popitem()[0], 'section1') 8197db96d56Sopenharmony_ci self.assertEqual(cf.popitem()[0], 'section2') 8207db96d56Sopenharmony_ci self.assertEqual(cf.popitem()[0], 'section3') 8217db96d56Sopenharmony_ci with self.assertRaises(KeyError): 8227db96d56Sopenharmony_ci cf.popitem() 8237db96d56Sopenharmony_ci 8247db96d56Sopenharmony_ci def test_clear(self): 8257db96d56Sopenharmony_ci cf = self.newconfig({"foo": "Bar"}) 8267db96d56Sopenharmony_ci self.assertEqual( 8277db96d56Sopenharmony_ci cf.get(self.default_section, "Foo"), "Bar", 8287db96d56Sopenharmony_ci "could not locate option, expecting case-insensitive option names") 8297db96d56Sopenharmony_ci cf['zing'] = {'option1': 'value1', 'option2': 'value2'} 8307db96d56Sopenharmony_ci self.assertEqual(cf.sections(), ['zing']) 8317db96d56Sopenharmony_ci self.assertEqual(set(cf['zing'].keys()), {'option1', 'option2', 'foo'}) 8327db96d56Sopenharmony_ci cf.clear() 8337db96d56Sopenharmony_ci self.assertEqual(set(cf.sections()), set()) 8347db96d56Sopenharmony_ci self.assertEqual(set(cf[self.default_section].keys()), {'foo'}) 8357db96d56Sopenharmony_ci 8367db96d56Sopenharmony_ci def test_setitem(self): 8377db96d56Sopenharmony_ci cf = self.fromstring(""" 8387db96d56Sopenharmony_ci [section1] 8397db96d56Sopenharmony_ci name1 {0[0]} value1 8407db96d56Sopenharmony_ci [section2] 8417db96d56Sopenharmony_ci name2 {0[0]} value2 8427db96d56Sopenharmony_ci [section3] 8437db96d56Sopenharmony_ci name3 {0[0]} value3 8447db96d56Sopenharmony_ci """.format(self.delimiters), defaults={"nameD": "valueD"}) 8457db96d56Sopenharmony_ci self.assertEqual(set(cf['section1'].keys()), {'name1', 'named'}) 8467db96d56Sopenharmony_ci self.assertEqual(set(cf['section2'].keys()), {'name2', 'named'}) 8477db96d56Sopenharmony_ci self.assertEqual(set(cf['section3'].keys()), {'name3', 'named'}) 8487db96d56Sopenharmony_ci self.assertEqual(cf['section1']['name1'], 'value1') 8497db96d56Sopenharmony_ci self.assertEqual(cf['section2']['name2'], 'value2') 8507db96d56Sopenharmony_ci self.assertEqual(cf['section3']['name3'], 'value3') 8517db96d56Sopenharmony_ci self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) 8527db96d56Sopenharmony_ci cf['section2'] = {'name22': 'value22'} 8537db96d56Sopenharmony_ci self.assertEqual(set(cf['section2'].keys()), {'name22', 'named'}) 8547db96d56Sopenharmony_ci self.assertEqual(cf['section2']['name22'], 'value22') 8557db96d56Sopenharmony_ci self.assertNotIn('name2', cf['section2']) 8567db96d56Sopenharmony_ci self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) 8577db96d56Sopenharmony_ci cf['section3'] = {} 8587db96d56Sopenharmony_ci self.assertEqual(set(cf['section3'].keys()), {'named'}) 8597db96d56Sopenharmony_ci self.assertNotIn('name3', cf['section3']) 8607db96d56Sopenharmony_ci self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) 8617db96d56Sopenharmony_ci # For bpo-32108, assigning default_section to itself. 8627db96d56Sopenharmony_ci cf[self.default_section] = cf[self.default_section] 8637db96d56Sopenharmony_ci self.assertNotEqual(set(cf[self.default_section].keys()), set()) 8647db96d56Sopenharmony_ci cf[self.default_section] = {} 8657db96d56Sopenharmony_ci self.assertEqual(set(cf[self.default_section].keys()), set()) 8667db96d56Sopenharmony_ci self.assertEqual(set(cf['section1'].keys()), {'name1'}) 8677db96d56Sopenharmony_ci self.assertEqual(set(cf['section2'].keys()), {'name22'}) 8687db96d56Sopenharmony_ci self.assertEqual(set(cf['section3'].keys()), set()) 8697db96d56Sopenharmony_ci self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) 8707db96d56Sopenharmony_ci # For bpo-32108, assigning section to itself. 8717db96d56Sopenharmony_ci cf['section2'] = cf['section2'] 8727db96d56Sopenharmony_ci self.assertEqual(set(cf['section2'].keys()), {'name22'}) 8737db96d56Sopenharmony_ci 8747db96d56Sopenharmony_ci def test_invalid_multiline_value(self): 8757db96d56Sopenharmony_ci if self.allow_no_value: 8767db96d56Sopenharmony_ci self.skipTest('if no_value is allowed, ParsingError is not raised') 8777db96d56Sopenharmony_ci 8787db96d56Sopenharmony_ci invalid = textwrap.dedent("""\ 8797db96d56Sopenharmony_ci [DEFAULT] 8807db96d56Sopenharmony_ci test {0} test 8817db96d56Sopenharmony_ci invalid""".format(self.delimiters[0]) 8827db96d56Sopenharmony_ci ) 8837db96d56Sopenharmony_ci cf = self.newconfig() 8847db96d56Sopenharmony_ci with self.assertRaises(configparser.ParsingError): 8857db96d56Sopenharmony_ci cf.read_string(invalid) 8867db96d56Sopenharmony_ci self.assertEqual(cf.get('DEFAULT', 'test'), 'test') 8877db96d56Sopenharmony_ci self.assertEqual(cf['DEFAULT']['test'], 'test') 8887db96d56Sopenharmony_ci 8897db96d56Sopenharmony_ci 8907db96d56Sopenharmony_ciclass StrictTestCase(BasicTestCase, unittest.TestCase): 8917db96d56Sopenharmony_ci config_class = configparser.RawConfigParser 8927db96d56Sopenharmony_ci strict = True 8937db96d56Sopenharmony_ci 8947db96d56Sopenharmony_ci 8957db96d56Sopenharmony_ciclass ConfigParserTestCase(BasicTestCase, unittest.TestCase): 8967db96d56Sopenharmony_ci config_class = configparser.ConfigParser 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci def test_interpolation(self): 8997db96d56Sopenharmony_ci cf = self.get_interpolation_config() 9007db96d56Sopenharmony_ci eq = self.assertEqual 9017db96d56Sopenharmony_ci eq(cf.get("Foo", "bar"), "something with interpolation (1 step)") 9027db96d56Sopenharmony_ci eq(cf.get("Foo", "bar9"), 9037db96d56Sopenharmony_ci "something with lots of interpolation (9 steps)") 9047db96d56Sopenharmony_ci eq(cf.get("Foo", "bar10"), 9057db96d56Sopenharmony_ci "something with lots of interpolation (10 steps)") 9067db96d56Sopenharmony_ci e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11") 9077db96d56Sopenharmony_ci if self.interpolation == configparser._UNSET: 9087db96d56Sopenharmony_ci self.assertEqual(e.args, ("bar11", "Foo", 9097db96d56Sopenharmony_ci "something %(with11)s lots of interpolation (11 steps)")) 9107db96d56Sopenharmony_ci elif isinstance(self.interpolation, configparser.LegacyInterpolation): 9117db96d56Sopenharmony_ci self.assertEqual(e.args, ("bar11", "Foo", 9127db96d56Sopenharmony_ci "something %(with11)s lots of interpolation (11 steps)")) 9137db96d56Sopenharmony_ci 9147db96d56Sopenharmony_ci def test_interpolation_missing_value(self): 9157db96d56Sopenharmony_ci cf = self.get_interpolation_config() 9167db96d56Sopenharmony_ci e = self.get_error(cf, configparser.InterpolationMissingOptionError, 9177db96d56Sopenharmony_ci "Interpolation Error", "name") 9187db96d56Sopenharmony_ci self.assertEqual(e.reference, "reference") 9197db96d56Sopenharmony_ci self.assertEqual(e.section, "Interpolation Error") 9207db96d56Sopenharmony_ci self.assertEqual(e.option, "name") 9217db96d56Sopenharmony_ci if self.interpolation == configparser._UNSET: 9227db96d56Sopenharmony_ci self.assertEqual(e.args, ('name', 'Interpolation Error', 9237db96d56Sopenharmony_ci '%(reference)s', 'reference')) 9247db96d56Sopenharmony_ci elif isinstance(self.interpolation, configparser.LegacyInterpolation): 9257db96d56Sopenharmony_ci self.assertEqual(e.args, ('name', 'Interpolation Error', 9267db96d56Sopenharmony_ci '%(reference)s', 'reference')) 9277db96d56Sopenharmony_ci 9287db96d56Sopenharmony_ci def test_items(self): 9297db96d56Sopenharmony_ci self.check_items_config([('default', '<default>'), 9307db96d56Sopenharmony_ci ('getdefault', '|<default>|'), 9317db96d56Sopenharmony_ci ('key', '|value|'), 9327db96d56Sopenharmony_ci ('name', 'value')]) 9337db96d56Sopenharmony_ci 9347db96d56Sopenharmony_ci def test_safe_interpolation(self): 9357db96d56Sopenharmony_ci # See http://www.python.org/sf/511737 9367db96d56Sopenharmony_ci cf = self.fromstring("[section]\n" 9377db96d56Sopenharmony_ci "option1{eq}xxx\n" 9387db96d56Sopenharmony_ci "option2{eq}%(option1)s/xxx\n" 9397db96d56Sopenharmony_ci "ok{eq}%(option1)s/%%s\n" 9407db96d56Sopenharmony_ci "not_ok{eq}%(option2)s/%%s".format( 9417db96d56Sopenharmony_ci eq=self.delimiters[0])) 9427db96d56Sopenharmony_ci self.assertEqual(cf.get("section", "ok"), "xxx/%s") 9437db96d56Sopenharmony_ci if self.interpolation == configparser._UNSET: 9447db96d56Sopenharmony_ci self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s") 9457db96d56Sopenharmony_ci elif isinstance(self.interpolation, configparser.LegacyInterpolation): 9467db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9477db96d56Sopenharmony_ci cf.get("section", "not_ok") 9487db96d56Sopenharmony_ci 9497db96d56Sopenharmony_ci def test_set_malformatted_interpolation(self): 9507db96d56Sopenharmony_ci cf = self.fromstring("[sect]\n" 9517db96d56Sopenharmony_ci "option1{eq}foo\n".format(eq=self.delimiters[0])) 9527db96d56Sopenharmony_ci 9537db96d56Sopenharmony_ci self.assertEqual(cf.get('sect', "option1"), "foo") 9547db96d56Sopenharmony_ci 9557db96d56Sopenharmony_ci self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo") 9567db96d56Sopenharmony_ci self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%") 9577db96d56Sopenharmony_ci self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo") 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci self.assertEqual(cf.get('sect', "option1"), "foo") 9607db96d56Sopenharmony_ci 9617db96d56Sopenharmony_ci # bug #5741: double percents are *not* malformed 9627db96d56Sopenharmony_ci cf.set("sect", "option2", "foo%%bar") 9637db96d56Sopenharmony_ci self.assertEqual(cf.get("sect", "option2"), "foo%bar") 9647db96d56Sopenharmony_ci 9657db96d56Sopenharmony_ci def test_set_nonstring_types(self): 9667db96d56Sopenharmony_ci cf = self.fromstring("[sect]\n" 9677db96d56Sopenharmony_ci "option1{eq}foo\n".format(eq=self.delimiters[0])) 9687db96d56Sopenharmony_ci # Check that we get a TypeError when setting non-string values 9697db96d56Sopenharmony_ci # in an existing section: 9707db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", "option1", 1) 9717db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0) 9727db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", "option1", object()) 9737db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", "option2", 1) 9747db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0) 9757db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", "option2", object()) 9767db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.set, "sect", 123, "invalid opt name!") 9777db96d56Sopenharmony_ci self.assertRaises(TypeError, cf.add_section, 123) 9787db96d56Sopenharmony_ci 9797db96d56Sopenharmony_ci def test_add_section_default(self): 9807db96d56Sopenharmony_ci cf = self.newconfig() 9817db96d56Sopenharmony_ci self.assertRaises(ValueError, cf.add_section, self.default_section) 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci def test_defaults_keyword(self): 9847db96d56Sopenharmony_ci """bpo-23835 fix for ConfigParser""" 9857db96d56Sopenharmony_ci cf = self.newconfig(defaults={1: 2.4}) 9867db96d56Sopenharmony_ci self.assertEqual(cf[self.default_section]['1'], '2.4') 9877db96d56Sopenharmony_ci self.assertAlmostEqual(cf[self.default_section].getfloat('1'), 2.4) 9887db96d56Sopenharmony_ci cf = self.newconfig(defaults={"A": 5.2}) 9897db96d56Sopenharmony_ci self.assertEqual(cf[self.default_section]['a'], '5.2') 9907db96d56Sopenharmony_ci self.assertAlmostEqual(cf[self.default_section].getfloat('a'), 5.2) 9917db96d56Sopenharmony_ci 9927db96d56Sopenharmony_ci 9937db96d56Sopenharmony_ciclass ConfigParserTestCaseNoInterpolation(BasicTestCase, unittest.TestCase): 9947db96d56Sopenharmony_ci config_class = configparser.ConfigParser 9957db96d56Sopenharmony_ci interpolation = None 9967db96d56Sopenharmony_ci ini = textwrap.dedent(""" 9977db96d56Sopenharmony_ci [numbers] 9987db96d56Sopenharmony_ci one = 1 9997db96d56Sopenharmony_ci two = %(one)s * 2 10007db96d56Sopenharmony_ci three = ${common:one} * 3 10017db96d56Sopenharmony_ci 10027db96d56Sopenharmony_ci [hexen] 10037db96d56Sopenharmony_ci sixteen = ${numbers:two} * 8 10047db96d56Sopenharmony_ci """).strip() 10057db96d56Sopenharmony_ci 10067db96d56Sopenharmony_ci def assertMatchesIni(self, cf): 10077db96d56Sopenharmony_ci self.assertEqual(cf['numbers']['one'], '1') 10087db96d56Sopenharmony_ci self.assertEqual(cf['numbers']['two'], '%(one)s * 2') 10097db96d56Sopenharmony_ci self.assertEqual(cf['numbers']['three'], '${common:one} * 3') 10107db96d56Sopenharmony_ci self.assertEqual(cf['hexen']['sixteen'], '${numbers:two} * 8') 10117db96d56Sopenharmony_ci 10127db96d56Sopenharmony_ci def test_no_interpolation(self): 10137db96d56Sopenharmony_ci cf = self.fromstring(self.ini) 10147db96d56Sopenharmony_ci self.assertMatchesIni(cf) 10157db96d56Sopenharmony_ci 10167db96d56Sopenharmony_ci def test_empty_case(self): 10177db96d56Sopenharmony_ci cf = self.newconfig() 10187db96d56Sopenharmony_ci self.assertIsNone(cf.read_string("")) 10197db96d56Sopenharmony_ci 10207db96d56Sopenharmony_ci def test_none_as_default_interpolation(self): 10217db96d56Sopenharmony_ci class CustomConfigParser(configparser.ConfigParser): 10227db96d56Sopenharmony_ci _DEFAULT_INTERPOLATION = None 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_ci cf = CustomConfigParser() 10257db96d56Sopenharmony_ci cf.read_string(self.ini) 10267db96d56Sopenharmony_ci self.assertMatchesIni(cf) 10277db96d56Sopenharmony_ci 10287db96d56Sopenharmony_ci 10297db96d56Sopenharmony_ciclass ConfigParserTestCaseLegacyInterpolation(ConfigParserTestCase): 10307db96d56Sopenharmony_ci config_class = configparser.ConfigParser 10317db96d56Sopenharmony_ci with warnings.catch_warnings(): 10327db96d56Sopenharmony_ci warnings.simplefilter("ignore", DeprecationWarning) 10337db96d56Sopenharmony_ci interpolation = configparser.LegacyInterpolation() 10347db96d56Sopenharmony_ci 10357db96d56Sopenharmony_ci def test_set_malformatted_interpolation(self): 10367db96d56Sopenharmony_ci cf = self.fromstring("[sect]\n" 10377db96d56Sopenharmony_ci "option1{eq}foo\n".format(eq=self.delimiters[0])) 10387db96d56Sopenharmony_ci 10397db96d56Sopenharmony_ci self.assertEqual(cf.get('sect', "option1"), "foo") 10407db96d56Sopenharmony_ci 10417db96d56Sopenharmony_ci cf.set("sect", "option1", "%foo") 10427db96d56Sopenharmony_ci self.assertEqual(cf.get('sect', "option1"), "%foo") 10437db96d56Sopenharmony_ci cf.set("sect", "option1", "foo%") 10447db96d56Sopenharmony_ci self.assertEqual(cf.get('sect', "option1"), "foo%") 10457db96d56Sopenharmony_ci cf.set("sect", "option1", "f%oo") 10467db96d56Sopenharmony_ci self.assertEqual(cf.get('sect', "option1"), "f%oo") 10477db96d56Sopenharmony_ci 10487db96d56Sopenharmony_ci # bug #5741: double percents are *not* malformed 10497db96d56Sopenharmony_ci cf.set("sect", "option2", "foo%%bar") 10507db96d56Sopenharmony_ci self.assertEqual(cf.get("sect", "option2"), "foo%%bar") 10517db96d56Sopenharmony_ci 10527db96d56Sopenharmony_ci 10537db96d56Sopenharmony_ciclass ConfigParserTestCaseInvalidInterpolationType(unittest.TestCase): 10547db96d56Sopenharmony_ci def test_error_on_wrong_type_for_interpolation(self): 10557db96d56Sopenharmony_ci for value in [configparser.ExtendedInterpolation, 42, "a string"]: 10567db96d56Sopenharmony_ci with self.subTest(value=value): 10577db96d56Sopenharmony_ci with self.assertRaises(TypeError): 10587db96d56Sopenharmony_ci configparser.ConfigParser(interpolation=value) 10597db96d56Sopenharmony_ci 10607db96d56Sopenharmony_ci 10617db96d56Sopenharmony_ciclass ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase): 10627db96d56Sopenharmony_ci delimiters = (':=', '$') 10637db96d56Sopenharmony_ci comment_prefixes = ('//', '"') 10647db96d56Sopenharmony_ci inline_comment_prefixes = ('//', '"') 10657db96d56Sopenharmony_ci 10667db96d56Sopenharmony_ci 10677db96d56Sopenharmony_ciclass ConfigParserTestCaseNonStandardDefaultSection(ConfigParserTestCase): 10687db96d56Sopenharmony_ci default_section = 'general' 10697db96d56Sopenharmony_ci 10707db96d56Sopenharmony_ci 10717db96d56Sopenharmony_ciclass MultilineValuesTestCase(BasicTestCase, unittest.TestCase): 10727db96d56Sopenharmony_ci config_class = configparser.ConfigParser 10737db96d56Sopenharmony_ci wonderful_spam = ("I'm having spam spam spam spam " 10747db96d56Sopenharmony_ci "spam spam spam beaked beans spam " 10757db96d56Sopenharmony_ci "spam spam and spam!").replace(' ', '\t\n') 10767db96d56Sopenharmony_ci 10777db96d56Sopenharmony_ci def setUp(self): 10787db96d56Sopenharmony_ci cf = self.newconfig() 10797db96d56Sopenharmony_ci for i in range(100): 10807db96d56Sopenharmony_ci s = 'section{}'.format(i) 10817db96d56Sopenharmony_ci cf.add_section(s) 10827db96d56Sopenharmony_ci for j in range(10): 10837db96d56Sopenharmony_ci cf.set(s, 'lovely_spam{}'.format(j), self.wonderful_spam) 10847db96d56Sopenharmony_ci with open(os_helper.TESTFN, 'w', encoding="utf-8") as f: 10857db96d56Sopenharmony_ci cf.write(f) 10867db96d56Sopenharmony_ci 10877db96d56Sopenharmony_ci def tearDown(self): 10887db96d56Sopenharmony_ci os.unlink(os_helper.TESTFN) 10897db96d56Sopenharmony_ci 10907db96d56Sopenharmony_ci def test_dominating_multiline_values(self): 10917db96d56Sopenharmony_ci # We're reading from file because this is where the code changed 10927db96d56Sopenharmony_ci # during performance updates in Python 3.2 10937db96d56Sopenharmony_ci cf_from_file = self.newconfig() 10947db96d56Sopenharmony_ci with open(os_helper.TESTFN, encoding="utf-8") as f: 10957db96d56Sopenharmony_ci cf_from_file.read_file(f) 10967db96d56Sopenharmony_ci self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'), 10977db96d56Sopenharmony_ci self.wonderful_spam.replace('\t\n', '\n')) 10987db96d56Sopenharmony_ci 10997db96d56Sopenharmony_ci 11007db96d56Sopenharmony_ciclass RawConfigParserTestCase(BasicTestCase, unittest.TestCase): 11017db96d56Sopenharmony_ci config_class = configparser.RawConfigParser 11027db96d56Sopenharmony_ci 11037db96d56Sopenharmony_ci def test_interpolation(self): 11047db96d56Sopenharmony_ci cf = self.get_interpolation_config() 11057db96d56Sopenharmony_ci eq = self.assertEqual 11067db96d56Sopenharmony_ci eq(cf.get("Foo", "bar"), 11077db96d56Sopenharmony_ci "something %(with1)s interpolation (1 step)") 11087db96d56Sopenharmony_ci eq(cf.get("Foo", "bar9"), 11097db96d56Sopenharmony_ci "something %(with9)s lots of interpolation (9 steps)") 11107db96d56Sopenharmony_ci eq(cf.get("Foo", "bar10"), 11117db96d56Sopenharmony_ci "something %(with10)s lots of interpolation (10 steps)") 11127db96d56Sopenharmony_ci eq(cf.get("Foo", "bar11"), 11137db96d56Sopenharmony_ci "something %(with11)s lots of interpolation (11 steps)") 11147db96d56Sopenharmony_ci 11157db96d56Sopenharmony_ci def test_items(self): 11167db96d56Sopenharmony_ci self.check_items_config([('default', '<default>'), 11177db96d56Sopenharmony_ci ('getdefault', '|%(default)s|'), 11187db96d56Sopenharmony_ci ('key', '|%(name)s|'), 11197db96d56Sopenharmony_ci ('name', '%(value)s')]) 11207db96d56Sopenharmony_ci 11217db96d56Sopenharmony_ci def test_set_nonstring_types(self): 11227db96d56Sopenharmony_ci cf = self.newconfig() 11237db96d56Sopenharmony_ci cf.add_section('non-string') 11247db96d56Sopenharmony_ci cf.set('non-string', 'int', 1) 11257db96d56Sopenharmony_ci cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13]) 11267db96d56Sopenharmony_ci cf.set('non-string', 'dict', {'pi': 3.14159}) 11277db96d56Sopenharmony_ci self.assertEqual(cf.get('non-string', 'int'), 1) 11287db96d56Sopenharmony_ci self.assertEqual(cf.get('non-string', 'list'), 11297db96d56Sopenharmony_ci [0, 1, 1, 2, 3, 5, 8, 13]) 11307db96d56Sopenharmony_ci self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159}) 11317db96d56Sopenharmony_ci cf.add_section(123) 11327db96d56Sopenharmony_ci cf.set(123, 'this is sick', True) 11337db96d56Sopenharmony_ci self.assertEqual(cf.get(123, 'this is sick'), True) 11347db96d56Sopenharmony_ci if cf._dict is configparser._default_dict: 11357db96d56Sopenharmony_ci # would not work for SortedDict; only checking for the most common 11367db96d56Sopenharmony_ci # default dictionary (dict) 11377db96d56Sopenharmony_ci cf.optionxform = lambda x: x 11387db96d56Sopenharmony_ci cf.set('non-string', 1, 1) 11397db96d56Sopenharmony_ci self.assertEqual(cf.get('non-string', 1), 1) 11407db96d56Sopenharmony_ci 11417db96d56Sopenharmony_ci def test_defaults_keyword(self): 11427db96d56Sopenharmony_ci """bpo-23835 legacy behavior for RawConfigParser""" 11437db96d56Sopenharmony_ci with self.assertRaises(AttributeError) as ctx: 11447db96d56Sopenharmony_ci self.newconfig(defaults={1: 2.4}) 11457db96d56Sopenharmony_ci err = ctx.exception 11467db96d56Sopenharmony_ci self.assertEqual(str(err), "'int' object has no attribute 'lower'") 11477db96d56Sopenharmony_ci cf = self.newconfig(defaults={"A": 5.2}) 11487db96d56Sopenharmony_ci self.assertAlmostEqual(cf[self.default_section]['a'], 5.2) 11497db96d56Sopenharmony_ci 11507db96d56Sopenharmony_ci 11517db96d56Sopenharmony_ciclass RawConfigParserTestCaseNonStandardDelimiters(RawConfigParserTestCase): 11527db96d56Sopenharmony_ci delimiters = (':=', '$') 11537db96d56Sopenharmony_ci comment_prefixes = ('//', '"') 11547db96d56Sopenharmony_ci inline_comment_prefixes = ('//', '"') 11557db96d56Sopenharmony_ci 11567db96d56Sopenharmony_ci 11577db96d56Sopenharmony_ciclass RawConfigParserTestSambaConf(CfgParserTestCaseClass, unittest.TestCase): 11587db96d56Sopenharmony_ci config_class = configparser.RawConfigParser 11597db96d56Sopenharmony_ci comment_prefixes = ('#', ';', '----') 11607db96d56Sopenharmony_ci inline_comment_prefixes = ('//',) 11617db96d56Sopenharmony_ci empty_lines_in_values = False 11627db96d56Sopenharmony_ci 11637db96d56Sopenharmony_ci def test_reading(self): 11647db96d56Sopenharmony_ci smbconf = support.findfile("cfgparser.2") 11657db96d56Sopenharmony_ci # check when we pass a mix of readable and non-readable files: 11667db96d56Sopenharmony_ci cf = self.newconfig() 11677db96d56Sopenharmony_ci parsed_files = cf.read([smbconf, "nonexistent-file"], encoding='utf-8') 11687db96d56Sopenharmony_ci self.assertEqual(parsed_files, [smbconf]) 11697db96d56Sopenharmony_ci sections = ['global', 'homes', 'printers', 11707db96d56Sopenharmony_ci 'print$', 'pdf-generator', 'tmp', 'Agustin'] 11717db96d56Sopenharmony_ci self.assertEqual(cf.sections(), sections) 11727db96d56Sopenharmony_ci self.assertEqual(cf.get("global", "workgroup"), "MDKGROUP") 11737db96d56Sopenharmony_ci self.assertEqual(cf.getint("global", "max log size"), 50) 11747db96d56Sopenharmony_ci self.assertEqual(cf.get("global", "hosts allow"), "127.") 11757db96d56Sopenharmony_ci self.assertEqual(cf.get("tmp", "echo command"), "cat %s; rm %s") 11767db96d56Sopenharmony_ci 11777db96d56Sopenharmony_ciclass ConfigParserTestCaseExtendedInterpolation(BasicTestCase, unittest.TestCase): 11787db96d56Sopenharmony_ci config_class = configparser.ConfigParser 11797db96d56Sopenharmony_ci interpolation = configparser.ExtendedInterpolation() 11807db96d56Sopenharmony_ci default_section = 'common' 11817db96d56Sopenharmony_ci strict = True 11827db96d56Sopenharmony_ci 11837db96d56Sopenharmony_ci def fromstring(self, string, defaults=None, optionxform=None): 11847db96d56Sopenharmony_ci cf = self.newconfig(defaults) 11857db96d56Sopenharmony_ci if optionxform: 11867db96d56Sopenharmony_ci cf.optionxform = optionxform 11877db96d56Sopenharmony_ci cf.read_string(string) 11887db96d56Sopenharmony_ci return cf 11897db96d56Sopenharmony_ci 11907db96d56Sopenharmony_ci def test_extended_interpolation(self): 11917db96d56Sopenharmony_ci cf = self.fromstring(textwrap.dedent(""" 11927db96d56Sopenharmony_ci [common] 11937db96d56Sopenharmony_ci favourite Beatle = Paul 11947db96d56Sopenharmony_ci favourite color = green 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci [tom] 11977db96d56Sopenharmony_ci favourite band = ${favourite color} day 11987db96d56Sopenharmony_ci favourite pope = John ${favourite Beatle} II 11997db96d56Sopenharmony_ci sequel = ${favourite pope}I 12007db96d56Sopenharmony_ci 12017db96d56Sopenharmony_ci [ambv] 12027db96d56Sopenharmony_ci favourite Beatle = George 12037db96d56Sopenharmony_ci son of Edward VII = ${favourite Beatle} V 12047db96d56Sopenharmony_ci son of George V = ${son of Edward VII}I 12057db96d56Sopenharmony_ci 12067db96d56Sopenharmony_ci [stanley] 12077db96d56Sopenharmony_ci favourite Beatle = ${ambv:favourite Beatle} 12087db96d56Sopenharmony_ci favourite pope = ${tom:favourite pope} 12097db96d56Sopenharmony_ci favourite color = black 12107db96d56Sopenharmony_ci favourite state of mind = paranoid 12117db96d56Sopenharmony_ci favourite movie = soylent ${common:favourite color} 12127db96d56Sopenharmony_ci favourite song = ${favourite color} sabbath - ${favourite state of mind} 12137db96d56Sopenharmony_ci """).strip()) 12147db96d56Sopenharmony_ci 12157db96d56Sopenharmony_ci eq = self.assertEqual 12167db96d56Sopenharmony_ci eq(cf['common']['favourite Beatle'], 'Paul') 12177db96d56Sopenharmony_ci eq(cf['common']['favourite color'], 'green') 12187db96d56Sopenharmony_ci eq(cf['tom']['favourite Beatle'], 'Paul') 12197db96d56Sopenharmony_ci eq(cf['tom']['favourite color'], 'green') 12207db96d56Sopenharmony_ci eq(cf['tom']['favourite band'], 'green day') 12217db96d56Sopenharmony_ci eq(cf['tom']['favourite pope'], 'John Paul II') 12227db96d56Sopenharmony_ci eq(cf['tom']['sequel'], 'John Paul III') 12237db96d56Sopenharmony_ci eq(cf['ambv']['favourite Beatle'], 'George') 12247db96d56Sopenharmony_ci eq(cf['ambv']['favourite color'], 'green') 12257db96d56Sopenharmony_ci eq(cf['ambv']['son of Edward VII'], 'George V') 12267db96d56Sopenharmony_ci eq(cf['ambv']['son of George V'], 'George VI') 12277db96d56Sopenharmony_ci eq(cf['stanley']['favourite Beatle'], 'George') 12287db96d56Sopenharmony_ci eq(cf['stanley']['favourite color'], 'black') 12297db96d56Sopenharmony_ci eq(cf['stanley']['favourite state of mind'], 'paranoid') 12307db96d56Sopenharmony_ci eq(cf['stanley']['favourite movie'], 'soylent green') 12317db96d56Sopenharmony_ci eq(cf['stanley']['favourite pope'], 'John Paul II') 12327db96d56Sopenharmony_ci eq(cf['stanley']['favourite song'], 12337db96d56Sopenharmony_ci 'black sabbath - paranoid') 12347db96d56Sopenharmony_ci 12357db96d56Sopenharmony_ci def test_endless_loop(self): 12367db96d56Sopenharmony_ci cf = self.fromstring(textwrap.dedent(""" 12377db96d56Sopenharmony_ci [one for you] 12387db96d56Sopenharmony_ci ping = ${one for me:pong} 12397db96d56Sopenharmony_ci 12407db96d56Sopenharmony_ci [one for me] 12417db96d56Sopenharmony_ci pong = ${one for you:ping} 12427db96d56Sopenharmony_ci 12437db96d56Sopenharmony_ci [selfish] 12447db96d56Sopenharmony_ci me = ${me} 12457db96d56Sopenharmony_ci """).strip()) 12467db96d56Sopenharmony_ci 12477db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationDepthError): 12487db96d56Sopenharmony_ci cf['one for you']['ping'] 12497db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationDepthError): 12507db96d56Sopenharmony_ci cf['selfish']['me'] 12517db96d56Sopenharmony_ci 12527db96d56Sopenharmony_ci def test_strange_options(self): 12537db96d56Sopenharmony_ci cf = self.fromstring(""" 12547db96d56Sopenharmony_ci [dollars] 12557db96d56Sopenharmony_ci $var = $$value 12567db96d56Sopenharmony_ci $var2 = ${$var} 12577db96d56Sopenharmony_ci ${sick} = cannot interpolate me 12587db96d56Sopenharmony_ci 12597db96d56Sopenharmony_ci [interpolated] 12607db96d56Sopenharmony_ci $other = ${dollars:$var} 12617db96d56Sopenharmony_ci $trying = ${dollars:${sick}} 12627db96d56Sopenharmony_ci """) 12637db96d56Sopenharmony_ci 12647db96d56Sopenharmony_ci self.assertEqual(cf['dollars']['$var'], '$value') 12657db96d56Sopenharmony_ci self.assertEqual(cf['interpolated']['$other'], '$value') 12667db96d56Sopenharmony_ci self.assertEqual(cf['dollars']['${sick}'], 'cannot interpolate me') 12677db96d56Sopenharmony_ci exception_class = configparser.InterpolationMissingOptionError 12687db96d56Sopenharmony_ci with self.assertRaises(exception_class) as cm: 12697db96d56Sopenharmony_ci cf['interpolated']['$trying'] 12707db96d56Sopenharmony_ci self.assertEqual(cm.exception.reference, 'dollars:${sick') 12717db96d56Sopenharmony_ci self.assertEqual(cm.exception.args[2], '${dollars:${sick}}') #rawval 12727db96d56Sopenharmony_ci 12737db96d56Sopenharmony_ci def test_case_sensitivity_basic(self): 12747db96d56Sopenharmony_ci ini = textwrap.dedent(""" 12757db96d56Sopenharmony_ci [common] 12767db96d56Sopenharmony_ci optionlower = value 12777db96d56Sopenharmony_ci OptionUpper = Value 12787db96d56Sopenharmony_ci 12797db96d56Sopenharmony_ci [Common] 12807db96d56Sopenharmony_ci optionlower = a better ${common:optionlower} 12817db96d56Sopenharmony_ci OptionUpper = A Better ${common:OptionUpper} 12827db96d56Sopenharmony_ci 12837db96d56Sopenharmony_ci [random] 12847db96d56Sopenharmony_ci foolower = ${common:optionlower} redefined 12857db96d56Sopenharmony_ci FooUpper = ${Common:OptionUpper} Redefined 12867db96d56Sopenharmony_ci """).strip() 12877db96d56Sopenharmony_ci 12887db96d56Sopenharmony_ci cf = self.fromstring(ini) 12897db96d56Sopenharmony_ci eq = self.assertEqual 12907db96d56Sopenharmony_ci eq(cf['common']['optionlower'], 'value') 12917db96d56Sopenharmony_ci eq(cf['common']['OptionUpper'], 'Value') 12927db96d56Sopenharmony_ci eq(cf['Common']['optionlower'], 'a better value') 12937db96d56Sopenharmony_ci eq(cf['Common']['OptionUpper'], 'A Better Value') 12947db96d56Sopenharmony_ci eq(cf['random']['foolower'], 'value redefined') 12957db96d56Sopenharmony_ci eq(cf['random']['FooUpper'], 'A Better Value Redefined') 12967db96d56Sopenharmony_ci 12977db96d56Sopenharmony_ci def test_case_sensitivity_conflicts(self): 12987db96d56Sopenharmony_ci ini = textwrap.dedent(""" 12997db96d56Sopenharmony_ci [common] 13007db96d56Sopenharmony_ci option = value 13017db96d56Sopenharmony_ci Option = Value 13027db96d56Sopenharmony_ci 13037db96d56Sopenharmony_ci [Common] 13047db96d56Sopenharmony_ci option = a better ${common:option} 13057db96d56Sopenharmony_ci Option = A Better ${common:Option} 13067db96d56Sopenharmony_ci 13077db96d56Sopenharmony_ci [random] 13087db96d56Sopenharmony_ci foo = ${common:option} redefined 13097db96d56Sopenharmony_ci Foo = ${Common:Option} Redefined 13107db96d56Sopenharmony_ci """).strip() 13117db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateOptionError): 13127db96d56Sopenharmony_ci cf = self.fromstring(ini) 13137db96d56Sopenharmony_ci 13147db96d56Sopenharmony_ci # raw options 13157db96d56Sopenharmony_ci cf = self.fromstring(ini, optionxform=lambda opt: opt) 13167db96d56Sopenharmony_ci eq = self.assertEqual 13177db96d56Sopenharmony_ci eq(cf['common']['option'], 'value') 13187db96d56Sopenharmony_ci eq(cf['common']['Option'], 'Value') 13197db96d56Sopenharmony_ci eq(cf['Common']['option'], 'a better value') 13207db96d56Sopenharmony_ci eq(cf['Common']['Option'], 'A Better Value') 13217db96d56Sopenharmony_ci eq(cf['random']['foo'], 'value redefined') 13227db96d56Sopenharmony_ci eq(cf['random']['Foo'], 'A Better Value Redefined') 13237db96d56Sopenharmony_ci 13247db96d56Sopenharmony_ci def test_other_errors(self): 13257db96d56Sopenharmony_ci cf = self.fromstring(""" 13267db96d56Sopenharmony_ci [interpolation fail] 13277db96d56Sopenharmony_ci case1 = ${where's the brace 13287db96d56Sopenharmony_ci case2 = ${does_not_exist} 13297db96d56Sopenharmony_ci case3 = ${wrong_section:wrong_value} 13307db96d56Sopenharmony_ci case4 = ${i:like:colon:characters} 13317db96d56Sopenharmony_ci case5 = $100 for Fail No 5! 13327db96d56Sopenharmony_ci """) 13337db96d56Sopenharmony_ci 13347db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationSyntaxError): 13357db96d56Sopenharmony_ci cf['interpolation fail']['case1'] 13367db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationMissingOptionError): 13377db96d56Sopenharmony_ci cf['interpolation fail']['case2'] 13387db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationMissingOptionError): 13397db96d56Sopenharmony_ci cf['interpolation fail']['case3'] 13407db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationSyntaxError): 13417db96d56Sopenharmony_ci cf['interpolation fail']['case4'] 13427db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationSyntaxError): 13437db96d56Sopenharmony_ci cf['interpolation fail']['case5'] 13447db96d56Sopenharmony_ci with self.assertRaises(ValueError): 13457db96d56Sopenharmony_ci cf['interpolation fail']['case6'] = "BLACK $ABBATH" 13467db96d56Sopenharmony_ci 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_ciclass ConfigParserTestCaseNoValue(ConfigParserTestCase): 13497db96d56Sopenharmony_ci allow_no_value = True 13507db96d56Sopenharmony_ci 13517db96d56Sopenharmony_ci 13527db96d56Sopenharmony_ciclass ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass, unittest.TestCase): 13537db96d56Sopenharmony_ci config_class = configparser.ConfigParser 13547db96d56Sopenharmony_ci delimiters = {'='} 13557db96d56Sopenharmony_ci comment_prefixes = {'#'} 13567db96d56Sopenharmony_ci allow_no_value = True 13577db96d56Sopenharmony_ci 13587db96d56Sopenharmony_ci def test_cfgparser_dot_3(self): 13597db96d56Sopenharmony_ci tricky = support.findfile("cfgparser.3") 13607db96d56Sopenharmony_ci cf = self.newconfig() 13617db96d56Sopenharmony_ci self.assertEqual(len(cf.read(tricky, encoding='utf-8')), 1) 13627db96d56Sopenharmony_ci self.assertEqual(cf.sections(), ['strange', 13637db96d56Sopenharmony_ci 'corruption', 13647db96d56Sopenharmony_ci 'yeah, sections can be ' 13657db96d56Sopenharmony_ci 'indented as well', 13667db96d56Sopenharmony_ci 'another one!', 13677db96d56Sopenharmony_ci 'no values here', 13687db96d56Sopenharmony_ci 'tricky interpolation', 13697db96d56Sopenharmony_ci 'more interpolation']) 13707db96d56Sopenharmony_ci self.assertEqual(cf.getint(self.default_section, 'go', 13717db96d56Sopenharmony_ci vars={'interpolate': '-1'}), -1) 13727db96d56Sopenharmony_ci with self.assertRaises(ValueError): 13737db96d56Sopenharmony_ci # no interpolation will happen 13747db96d56Sopenharmony_ci cf.getint(self.default_section, 'go', raw=True, 13757db96d56Sopenharmony_ci vars={'interpolate': '-1'}) 13767db96d56Sopenharmony_ci self.assertEqual(len(cf.get('strange', 'other').split('\n')), 4) 13777db96d56Sopenharmony_ci self.assertEqual(len(cf.get('corruption', 'value').split('\n')), 10) 13787db96d56Sopenharmony_ci longname = 'yeah, sections can be indented as well' 13797db96d56Sopenharmony_ci self.assertFalse(cf.getboolean(longname, 'are they subsections')) 13807db96d56Sopenharmony_ci self.assertEqual(cf.get(longname, 'lets use some Unicode'), '片仮名') 13817db96d56Sopenharmony_ci self.assertEqual(len(cf.items('another one!')), 5) # 4 in section and 13827db96d56Sopenharmony_ci # `go` from DEFAULT 13837db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationMissingOptionError): 13847db96d56Sopenharmony_ci cf.items('no values here') 13857db96d56Sopenharmony_ci self.assertEqual(cf.get('tricky interpolation', 'lets'), 'do this') 13867db96d56Sopenharmony_ci self.assertEqual(cf.get('tricky interpolation', 'lets'), 13877db96d56Sopenharmony_ci cf.get('tricky interpolation', 'go')) 13887db96d56Sopenharmony_ci self.assertEqual(cf.get('more interpolation', 'lets'), 'go shopping') 13897db96d56Sopenharmony_ci 13907db96d56Sopenharmony_ci def test_unicode_failure(self): 13917db96d56Sopenharmony_ci tricky = support.findfile("cfgparser.3") 13927db96d56Sopenharmony_ci cf = self.newconfig() 13937db96d56Sopenharmony_ci with self.assertRaises(UnicodeDecodeError): 13947db96d56Sopenharmony_ci cf.read(tricky, encoding='ascii') 13957db96d56Sopenharmony_ci 13967db96d56Sopenharmony_ci 13977db96d56Sopenharmony_ciclass Issue7005TestCase(unittest.TestCase): 13987db96d56Sopenharmony_ci """Test output when None is set() as a value and allow_no_value == False. 13997db96d56Sopenharmony_ci 14007db96d56Sopenharmony_ci http://bugs.python.org/issue7005 14017db96d56Sopenharmony_ci 14027db96d56Sopenharmony_ci """ 14037db96d56Sopenharmony_ci 14047db96d56Sopenharmony_ci expected_output = "[section]\noption = None\n\n" 14057db96d56Sopenharmony_ci 14067db96d56Sopenharmony_ci def prepare(self, config_class): 14077db96d56Sopenharmony_ci # This is the default, but that's the point. 14087db96d56Sopenharmony_ci cp = config_class(allow_no_value=False) 14097db96d56Sopenharmony_ci cp.add_section("section") 14107db96d56Sopenharmony_ci cp.set("section", "option", None) 14117db96d56Sopenharmony_ci sio = io.StringIO() 14127db96d56Sopenharmony_ci cp.write(sio) 14137db96d56Sopenharmony_ci return sio.getvalue() 14147db96d56Sopenharmony_ci 14157db96d56Sopenharmony_ci def test_none_as_value_stringified(self): 14167db96d56Sopenharmony_ci cp = configparser.ConfigParser(allow_no_value=False) 14177db96d56Sopenharmony_ci cp.add_section("section") 14187db96d56Sopenharmony_ci with self.assertRaises(TypeError): 14197db96d56Sopenharmony_ci cp.set("section", "option", None) 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci def test_none_as_value_stringified_raw(self): 14227db96d56Sopenharmony_ci output = self.prepare(configparser.RawConfigParser) 14237db96d56Sopenharmony_ci self.assertEqual(output, self.expected_output) 14247db96d56Sopenharmony_ci 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ciclass SortedTestCase(RawConfigParserTestCase): 14277db96d56Sopenharmony_ci dict_type = SortedDict 14287db96d56Sopenharmony_ci 14297db96d56Sopenharmony_ci def test_sorted(self): 14307db96d56Sopenharmony_ci cf = self.fromstring("[b]\n" 14317db96d56Sopenharmony_ci "o4=1\n" 14327db96d56Sopenharmony_ci "o3=2\n" 14337db96d56Sopenharmony_ci "o2=3\n" 14347db96d56Sopenharmony_ci "o1=4\n" 14357db96d56Sopenharmony_ci "[a]\n" 14367db96d56Sopenharmony_ci "k=v\n") 14377db96d56Sopenharmony_ci output = io.StringIO() 14387db96d56Sopenharmony_ci cf.write(output) 14397db96d56Sopenharmony_ci self.assertEqual(output.getvalue(), 14407db96d56Sopenharmony_ci "[a]\n" 14417db96d56Sopenharmony_ci "k = v\n\n" 14427db96d56Sopenharmony_ci "[b]\n" 14437db96d56Sopenharmony_ci "o1 = 4\n" 14447db96d56Sopenharmony_ci "o2 = 3\n" 14457db96d56Sopenharmony_ci "o3 = 2\n" 14467db96d56Sopenharmony_ci "o4 = 1\n\n") 14477db96d56Sopenharmony_ci 14487db96d56Sopenharmony_ci 14497db96d56Sopenharmony_ciclass CompatibleTestCase(CfgParserTestCaseClass, unittest.TestCase): 14507db96d56Sopenharmony_ci config_class = configparser.RawConfigParser 14517db96d56Sopenharmony_ci comment_prefixes = '#;' 14527db96d56Sopenharmony_ci inline_comment_prefixes = ';' 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci def test_comment_handling(self): 14557db96d56Sopenharmony_ci config_string = textwrap.dedent("""\ 14567db96d56Sopenharmony_ci [Commented Bar] 14577db96d56Sopenharmony_ci baz=qwe ; a comment 14587db96d56Sopenharmony_ci foo: bar # not a comment! 14597db96d56Sopenharmony_ci # but this is a comment 14607db96d56Sopenharmony_ci ; another comment 14617db96d56Sopenharmony_ci quirk: this;is not a comment 14627db96d56Sopenharmony_ci ; a space must precede an inline comment 14637db96d56Sopenharmony_ci """) 14647db96d56Sopenharmony_ci cf = self.fromstring(config_string) 14657db96d56Sopenharmony_ci self.assertEqual(cf.get('Commented Bar', 'foo'), 14667db96d56Sopenharmony_ci 'bar # not a comment!') 14677db96d56Sopenharmony_ci self.assertEqual(cf.get('Commented Bar', 'baz'), 'qwe') 14687db96d56Sopenharmony_ci self.assertEqual(cf.get('Commented Bar', 'quirk'), 14697db96d56Sopenharmony_ci 'this;is not a comment') 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_ciclass CopyTestCase(BasicTestCase, unittest.TestCase): 14727db96d56Sopenharmony_ci config_class = configparser.ConfigParser 14737db96d56Sopenharmony_ci 14747db96d56Sopenharmony_ci def fromstring(self, string, defaults=None): 14757db96d56Sopenharmony_ci cf = self.newconfig(defaults) 14767db96d56Sopenharmony_ci cf.read_string(string) 14777db96d56Sopenharmony_ci cf_copy = self.newconfig() 14787db96d56Sopenharmony_ci cf_copy.read_dict(cf) 14797db96d56Sopenharmony_ci # we have to clean up option duplicates that appeared because of 14807db96d56Sopenharmony_ci # the magic DEFAULTSECT behaviour. 14817db96d56Sopenharmony_ci for section in cf_copy.values(): 14827db96d56Sopenharmony_ci if section.name == self.default_section: 14837db96d56Sopenharmony_ci continue 14847db96d56Sopenharmony_ci for default, value in cf[self.default_section].items(): 14857db96d56Sopenharmony_ci if section[default] == value: 14867db96d56Sopenharmony_ci del section[default] 14877db96d56Sopenharmony_ci return cf_copy 14887db96d56Sopenharmony_ci 14897db96d56Sopenharmony_ci 14907db96d56Sopenharmony_ciclass FakeFile: 14917db96d56Sopenharmony_ci def __init__(self): 14927db96d56Sopenharmony_ci file_path = support.findfile("cfgparser.1") 14937db96d56Sopenharmony_ci with open(file_path, encoding="utf-8") as f: 14947db96d56Sopenharmony_ci self.lines = f.readlines() 14957db96d56Sopenharmony_ci self.lines.reverse() 14967db96d56Sopenharmony_ci 14977db96d56Sopenharmony_ci def readline(self): 14987db96d56Sopenharmony_ci if len(self.lines): 14997db96d56Sopenharmony_ci return self.lines.pop() 15007db96d56Sopenharmony_ci return '' 15017db96d56Sopenharmony_ci 15027db96d56Sopenharmony_ci 15037db96d56Sopenharmony_cidef readline_generator(f): 15047db96d56Sopenharmony_ci """As advised in Doc/library/configparser.rst.""" 15057db96d56Sopenharmony_ci line = f.readline() 15067db96d56Sopenharmony_ci while line: 15077db96d56Sopenharmony_ci yield line 15087db96d56Sopenharmony_ci line = f.readline() 15097db96d56Sopenharmony_ci 15107db96d56Sopenharmony_ci 15117db96d56Sopenharmony_ciclass ReadFileTestCase(unittest.TestCase): 15127db96d56Sopenharmony_ci def test_file(self): 15137db96d56Sopenharmony_ci file_paths = [support.findfile("cfgparser.1")] 15147db96d56Sopenharmony_ci try: 15157db96d56Sopenharmony_ci file_paths.append(file_paths[0].encode('utf8')) 15167db96d56Sopenharmony_ci except UnicodeEncodeError: 15177db96d56Sopenharmony_ci pass # unfortunately we can't test bytes on this path 15187db96d56Sopenharmony_ci for file_path in file_paths: 15197db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15207db96d56Sopenharmony_ci with open(file_path, encoding="utf-8") as f: 15217db96d56Sopenharmony_ci parser.read_file(f) 15227db96d56Sopenharmony_ci self.assertIn("Foo Bar", parser) 15237db96d56Sopenharmony_ci self.assertIn("foo", parser["Foo Bar"]) 15247db96d56Sopenharmony_ci self.assertEqual(parser["Foo Bar"]["foo"], "newbar") 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_ci def test_iterable(self): 15277db96d56Sopenharmony_ci lines = textwrap.dedent(""" 15287db96d56Sopenharmony_ci [Foo Bar] 15297db96d56Sopenharmony_ci foo=newbar""").strip().split('\n') 15307db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15317db96d56Sopenharmony_ci parser.read_file(lines) 15327db96d56Sopenharmony_ci self.assertIn("Foo Bar", parser) 15337db96d56Sopenharmony_ci self.assertIn("foo", parser["Foo Bar"]) 15347db96d56Sopenharmony_ci self.assertEqual(parser["Foo Bar"]["foo"], "newbar") 15357db96d56Sopenharmony_ci 15367db96d56Sopenharmony_ci def test_readline_generator(self): 15377db96d56Sopenharmony_ci """Issue #11670.""" 15387db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15397db96d56Sopenharmony_ci with self.assertRaises(TypeError): 15407db96d56Sopenharmony_ci parser.read_file(FakeFile()) 15417db96d56Sopenharmony_ci parser.read_file(readline_generator(FakeFile())) 15427db96d56Sopenharmony_ci self.assertIn("Foo Bar", parser) 15437db96d56Sopenharmony_ci self.assertIn("foo", parser["Foo Bar"]) 15447db96d56Sopenharmony_ci self.assertEqual(parser["Foo Bar"]["foo"], "newbar") 15457db96d56Sopenharmony_ci 15467db96d56Sopenharmony_ci def test_source_as_bytes(self): 15477db96d56Sopenharmony_ci """Issue #18260.""" 15487db96d56Sopenharmony_ci lines = textwrap.dedent(""" 15497db96d56Sopenharmony_ci [badbad] 15507db96d56Sopenharmony_ci [badbad]""").strip().split('\n') 15517db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15527db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateSectionError) as dse: 15537db96d56Sopenharmony_ci parser.read_file(lines, source=b"badbad") 15547db96d56Sopenharmony_ci self.assertEqual( 15557db96d56Sopenharmony_ci str(dse.exception), 15567db96d56Sopenharmony_ci "While reading from b'badbad' [line 2]: section 'badbad' " 15577db96d56Sopenharmony_ci "already exists" 15587db96d56Sopenharmony_ci ) 15597db96d56Sopenharmony_ci lines = textwrap.dedent(""" 15607db96d56Sopenharmony_ci [badbad] 15617db96d56Sopenharmony_ci bad = bad 15627db96d56Sopenharmony_ci bad = bad""").strip().split('\n') 15637db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15647db96d56Sopenharmony_ci with self.assertRaises(configparser.DuplicateOptionError) as dse: 15657db96d56Sopenharmony_ci parser.read_file(lines, source=b"badbad") 15667db96d56Sopenharmony_ci self.assertEqual( 15677db96d56Sopenharmony_ci str(dse.exception), 15687db96d56Sopenharmony_ci "While reading from b'badbad' [line 3]: option 'bad' in section " 15697db96d56Sopenharmony_ci "'badbad' already exists" 15707db96d56Sopenharmony_ci ) 15717db96d56Sopenharmony_ci lines = textwrap.dedent(""" 15727db96d56Sopenharmony_ci [badbad] 15737db96d56Sopenharmony_ci = bad""").strip().split('\n') 15747db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15757db96d56Sopenharmony_ci with self.assertRaises(configparser.ParsingError) as dse: 15767db96d56Sopenharmony_ci parser.read_file(lines, source=b"badbad") 15777db96d56Sopenharmony_ci self.assertEqual( 15787db96d56Sopenharmony_ci str(dse.exception), 15797db96d56Sopenharmony_ci "Source contains parsing errors: b'badbad'\n\t[line 2]: '= bad'" 15807db96d56Sopenharmony_ci ) 15817db96d56Sopenharmony_ci lines = textwrap.dedent(""" 15827db96d56Sopenharmony_ci [badbad 15837db96d56Sopenharmony_ci bad = bad""").strip().split('\n') 15847db96d56Sopenharmony_ci parser = configparser.ConfigParser() 15857db96d56Sopenharmony_ci with self.assertRaises(configparser.MissingSectionHeaderError) as dse: 15867db96d56Sopenharmony_ci parser.read_file(lines, source=b"badbad") 15877db96d56Sopenharmony_ci self.assertEqual( 15887db96d56Sopenharmony_ci str(dse.exception), 15897db96d56Sopenharmony_ci "File contains no section headers.\nfile: b'badbad', line: 1\n" 15907db96d56Sopenharmony_ci "'[badbad'" 15917db96d56Sopenharmony_ci ) 15927db96d56Sopenharmony_ci 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ciclass CoverageOneHundredTestCase(unittest.TestCase): 15957db96d56Sopenharmony_ci """Covers edge cases in the codebase.""" 15967db96d56Sopenharmony_ci 15977db96d56Sopenharmony_ci def test_duplicate_option_error(self): 15987db96d56Sopenharmony_ci error = configparser.DuplicateOptionError('section', 'option') 15997db96d56Sopenharmony_ci self.assertEqual(error.section, 'section') 16007db96d56Sopenharmony_ci self.assertEqual(error.option, 'option') 16017db96d56Sopenharmony_ci self.assertEqual(error.source, None) 16027db96d56Sopenharmony_ci self.assertEqual(error.lineno, None) 16037db96d56Sopenharmony_ci self.assertEqual(error.args, ('section', 'option', None, None)) 16047db96d56Sopenharmony_ci self.assertEqual(str(error), "Option 'option' in section 'section' " 16057db96d56Sopenharmony_ci "already exists") 16067db96d56Sopenharmony_ci 16077db96d56Sopenharmony_ci def test_interpolation_depth_error(self): 16087db96d56Sopenharmony_ci error = configparser.InterpolationDepthError('option', 'section', 16097db96d56Sopenharmony_ci 'rawval') 16107db96d56Sopenharmony_ci self.assertEqual(error.args, ('option', 'section', 'rawval')) 16117db96d56Sopenharmony_ci self.assertEqual(error.option, 'option') 16127db96d56Sopenharmony_ci self.assertEqual(error.section, 'section') 16137db96d56Sopenharmony_ci 16147db96d56Sopenharmony_ci def test_parsing_error(self): 16157db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 16167db96d56Sopenharmony_ci configparser.ParsingError() 16177db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), "Required argument `source' not " 16187db96d56Sopenharmony_ci "given.") 16197db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 16207db96d56Sopenharmony_ci configparser.ParsingError(source='source', filename='filename') 16217db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), "Cannot specify both `filename' " 16227db96d56Sopenharmony_ci "and `source'. Use `source'.") 16237db96d56Sopenharmony_ci error = configparser.ParsingError(filename='source') 16247db96d56Sopenharmony_ci self.assertEqual(error.source, 'source') 16257db96d56Sopenharmony_ci with warnings.catch_warnings(record=True) as w: 16267db96d56Sopenharmony_ci warnings.simplefilter("always", DeprecationWarning) 16277db96d56Sopenharmony_ci self.assertEqual(error.filename, 'source') 16287db96d56Sopenharmony_ci error.filename = 'filename' 16297db96d56Sopenharmony_ci self.assertEqual(error.source, 'filename') 16307db96d56Sopenharmony_ci for warning in w: 16317db96d56Sopenharmony_ci self.assertTrue(warning.category is DeprecationWarning) 16327db96d56Sopenharmony_ci 16337db96d56Sopenharmony_ci def test_interpolation_validation(self): 16347db96d56Sopenharmony_ci parser = configparser.ConfigParser() 16357db96d56Sopenharmony_ci parser.read_string(""" 16367db96d56Sopenharmony_ci [section] 16377db96d56Sopenharmony_ci invalid_percent = % 16387db96d56Sopenharmony_ci invalid_reference = %(() 16397db96d56Sopenharmony_ci invalid_variable = %(does_not_exist)s 16407db96d56Sopenharmony_ci """) 16417db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationSyntaxError) as cm: 16427db96d56Sopenharmony_ci parser['section']['invalid_percent'] 16437db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), "'%' must be followed by '%' or " 16447db96d56Sopenharmony_ci "'(', found: '%'") 16457db96d56Sopenharmony_ci with self.assertRaises(configparser.InterpolationSyntaxError) as cm: 16467db96d56Sopenharmony_ci parser['section']['invalid_reference'] 16477db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), "bad interpolation variable " 16487db96d56Sopenharmony_ci "reference '%(()'") 16497db96d56Sopenharmony_ci 16507db96d56Sopenharmony_ci def test_readfp_deprecation(self): 16517db96d56Sopenharmony_ci sio = io.StringIO(""" 16527db96d56Sopenharmony_ci [section] 16537db96d56Sopenharmony_ci option = value 16547db96d56Sopenharmony_ci """) 16557db96d56Sopenharmony_ci parser = configparser.ConfigParser() 16567db96d56Sopenharmony_ci with warnings.catch_warnings(record=True) as w: 16577db96d56Sopenharmony_ci warnings.simplefilter("always", DeprecationWarning) 16587db96d56Sopenharmony_ci parser.readfp(sio, filename='StringIO') 16597db96d56Sopenharmony_ci for warning in w: 16607db96d56Sopenharmony_ci self.assertTrue(warning.category is DeprecationWarning) 16617db96d56Sopenharmony_ci self.assertEqual(len(parser), 2) 16627db96d56Sopenharmony_ci self.assertEqual(parser['section']['option'], 'value') 16637db96d56Sopenharmony_ci 16647db96d56Sopenharmony_ci def test_safeconfigparser_deprecation(self): 16657db96d56Sopenharmony_ci with warnings.catch_warnings(record=True) as w: 16667db96d56Sopenharmony_ci warnings.simplefilter("always", DeprecationWarning) 16677db96d56Sopenharmony_ci parser = configparser.SafeConfigParser() 16687db96d56Sopenharmony_ci for warning in w: 16697db96d56Sopenharmony_ci self.assertTrue(warning.category is DeprecationWarning) 16707db96d56Sopenharmony_ci 16717db96d56Sopenharmony_ci def test_legacyinterpolation_deprecation(self): 16727db96d56Sopenharmony_ci with warnings.catch_warnings(record=True) as w: 16737db96d56Sopenharmony_ci warnings.simplefilter("always", DeprecationWarning) 16747db96d56Sopenharmony_ci configparser.LegacyInterpolation() 16757db96d56Sopenharmony_ci self.assertGreaterEqual(len(w), 1) 16767db96d56Sopenharmony_ci for warning in w: 16777db96d56Sopenharmony_ci self.assertIs(warning.category, DeprecationWarning) 16787db96d56Sopenharmony_ci 16797db96d56Sopenharmony_ci def test_sectionproxy_repr(self): 16807db96d56Sopenharmony_ci parser = configparser.ConfigParser() 16817db96d56Sopenharmony_ci parser.read_string(""" 16827db96d56Sopenharmony_ci [section] 16837db96d56Sopenharmony_ci key = value 16847db96d56Sopenharmony_ci """) 16857db96d56Sopenharmony_ci self.assertEqual(repr(parser['section']), '<Section: section>') 16867db96d56Sopenharmony_ci 16877db96d56Sopenharmony_ci def test_inconsistent_converters_state(self): 16887db96d56Sopenharmony_ci parser = configparser.ConfigParser() 16897db96d56Sopenharmony_ci import decimal 16907db96d56Sopenharmony_ci parser.converters['decimal'] = decimal.Decimal 16917db96d56Sopenharmony_ci parser.read_string(""" 16927db96d56Sopenharmony_ci [s1] 16937db96d56Sopenharmony_ci one = 1 16947db96d56Sopenharmony_ci [s2] 16957db96d56Sopenharmony_ci two = 2 16967db96d56Sopenharmony_ci """) 16977db96d56Sopenharmony_ci self.assertIn('decimal', parser.converters) 16987db96d56Sopenharmony_ci self.assertEqual(parser.getdecimal('s1', 'one'), 1) 16997db96d56Sopenharmony_ci self.assertEqual(parser.getdecimal('s2', 'two'), 2) 17007db96d56Sopenharmony_ci self.assertEqual(parser['s1'].getdecimal('one'), 1) 17017db96d56Sopenharmony_ci self.assertEqual(parser['s2'].getdecimal('two'), 2) 17027db96d56Sopenharmony_ci del parser.getdecimal 17037db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 17047db96d56Sopenharmony_ci parser.getdecimal('s1', 'one') 17057db96d56Sopenharmony_ci self.assertIn('decimal', parser.converters) 17067db96d56Sopenharmony_ci del parser.converters['decimal'] 17077db96d56Sopenharmony_ci self.assertNotIn('decimal', parser.converters) 17087db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 17097db96d56Sopenharmony_ci parser.getdecimal('s1', 'one') 17107db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 17117db96d56Sopenharmony_ci parser['s1'].getdecimal('one') 17127db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 17137db96d56Sopenharmony_ci parser['s2'].getdecimal('two') 17147db96d56Sopenharmony_ci 17157db96d56Sopenharmony_ci 17167db96d56Sopenharmony_ciclass ExceptionPicklingTestCase(unittest.TestCase): 17177db96d56Sopenharmony_ci """Tests for issue #13760: ConfigParser exceptions are not picklable.""" 17187db96d56Sopenharmony_ci 17197db96d56Sopenharmony_ci def test_error(self): 17207db96d56Sopenharmony_ci import pickle 17217db96d56Sopenharmony_ci e1 = configparser.Error('value') 17227db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17237db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17247db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17257db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17267db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 17277db96d56Sopenharmony_ci 17287db96d56Sopenharmony_ci def test_nosectionerror(self): 17297db96d56Sopenharmony_ci import pickle 17307db96d56Sopenharmony_ci e1 = configparser.NoSectionError('section') 17317db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17327db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17337db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17347db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17357db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 17367db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 17377db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 17387db96d56Sopenharmony_ci 17397db96d56Sopenharmony_ci def test_nooptionerror(self): 17407db96d56Sopenharmony_ci import pickle 17417db96d56Sopenharmony_ci e1 = configparser.NoOptionError('option', 'section') 17427db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17437db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17447db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17457db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17467db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 17477db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 17487db96d56Sopenharmony_ci self.assertEqual(e1.option, e2.option) 17497db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 17507db96d56Sopenharmony_ci 17517db96d56Sopenharmony_ci def test_duplicatesectionerror(self): 17527db96d56Sopenharmony_ci import pickle 17537db96d56Sopenharmony_ci e1 = configparser.DuplicateSectionError('section', 'source', 123) 17547db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17557db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17567db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17577db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17587db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 17597db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 17607db96d56Sopenharmony_ci self.assertEqual(e1.source, e2.source) 17617db96d56Sopenharmony_ci self.assertEqual(e1.lineno, e2.lineno) 17627db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 17637db96d56Sopenharmony_ci 17647db96d56Sopenharmony_ci def test_duplicateoptionerror(self): 17657db96d56Sopenharmony_ci import pickle 17667db96d56Sopenharmony_ci e1 = configparser.DuplicateOptionError('section', 'option', 'source', 17677db96d56Sopenharmony_ci 123) 17687db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17697db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17707db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17717db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17727db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 17737db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 17747db96d56Sopenharmony_ci self.assertEqual(e1.option, e2.option) 17757db96d56Sopenharmony_ci self.assertEqual(e1.source, e2.source) 17767db96d56Sopenharmony_ci self.assertEqual(e1.lineno, e2.lineno) 17777db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 17787db96d56Sopenharmony_ci 17797db96d56Sopenharmony_ci def test_interpolationerror(self): 17807db96d56Sopenharmony_ci import pickle 17817db96d56Sopenharmony_ci e1 = configparser.InterpolationError('option', 'section', 'msg') 17827db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17837db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17847db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17857db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17867db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 17877db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 17887db96d56Sopenharmony_ci self.assertEqual(e1.option, e2.option) 17897db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 17907db96d56Sopenharmony_ci 17917db96d56Sopenharmony_ci def test_interpolationmissingoptionerror(self): 17927db96d56Sopenharmony_ci import pickle 17937db96d56Sopenharmony_ci e1 = configparser.InterpolationMissingOptionError('option', 'section', 17947db96d56Sopenharmony_ci 'rawval', 'reference') 17957db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 17967db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 17977db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 17987db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 17997db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 18007db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 18017db96d56Sopenharmony_ci self.assertEqual(e1.option, e2.option) 18027db96d56Sopenharmony_ci self.assertEqual(e1.reference, e2.reference) 18037db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 18047db96d56Sopenharmony_ci 18057db96d56Sopenharmony_ci def test_interpolationsyntaxerror(self): 18067db96d56Sopenharmony_ci import pickle 18077db96d56Sopenharmony_ci e1 = configparser.InterpolationSyntaxError('option', 'section', 'msg') 18087db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 18097db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 18107db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 18117db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 18127db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 18137db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 18147db96d56Sopenharmony_ci self.assertEqual(e1.option, e2.option) 18157db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 18167db96d56Sopenharmony_ci 18177db96d56Sopenharmony_ci def test_interpolationdeptherror(self): 18187db96d56Sopenharmony_ci import pickle 18197db96d56Sopenharmony_ci e1 = configparser.InterpolationDepthError('option', 'section', 18207db96d56Sopenharmony_ci 'rawval') 18217db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 18227db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 18237db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 18247db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 18257db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 18267db96d56Sopenharmony_ci self.assertEqual(e1.section, e2.section) 18277db96d56Sopenharmony_ci self.assertEqual(e1.option, e2.option) 18287db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 18297db96d56Sopenharmony_ci 18307db96d56Sopenharmony_ci def test_parsingerror(self): 18317db96d56Sopenharmony_ci import pickle 18327db96d56Sopenharmony_ci e1 = configparser.ParsingError('source') 18337db96d56Sopenharmony_ci e1.append(1, 'line1') 18347db96d56Sopenharmony_ci e1.append(2, 'line2') 18357db96d56Sopenharmony_ci e1.append(3, 'line3') 18367db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 18377db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 18387db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 18397db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 18407db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 18417db96d56Sopenharmony_ci self.assertEqual(e1.source, e2.source) 18427db96d56Sopenharmony_ci self.assertEqual(e1.errors, e2.errors) 18437db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 18447db96d56Sopenharmony_ci e1 = configparser.ParsingError(filename='filename') 18457db96d56Sopenharmony_ci e1.append(1, 'line1') 18467db96d56Sopenharmony_ci e1.append(2, 'line2') 18477db96d56Sopenharmony_ci e1.append(3, 'line3') 18487db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 18497db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 18507db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 18517db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 18527db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 18537db96d56Sopenharmony_ci self.assertEqual(e1.source, e2.source) 18547db96d56Sopenharmony_ci self.assertEqual(e1.errors, e2.errors) 18557db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 18567db96d56Sopenharmony_ci 18577db96d56Sopenharmony_ci def test_missingsectionheadererror(self): 18587db96d56Sopenharmony_ci import pickle 18597db96d56Sopenharmony_ci e1 = configparser.MissingSectionHeaderError('filename', 123, 'line') 18607db96d56Sopenharmony_ci for proto in range(pickle.HIGHEST_PROTOCOL + 1): 18617db96d56Sopenharmony_ci pickled = pickle.dumps(e1, proto) 18627db96d56Sopenharmony_ci e2 = pickle.loads(pickled) 18637db96d56Sopenharmony_ci self.assertEqual(e1.message, e2.message) 18647db96d56Sopenharmony_ci self.assertEqual(e1.args, e2.args) 18657db96d56Sopenharmony_ci self.assertEqual(e1.line, e2.line) 18667db96d56Sopenharmony_ci self.assertEqual(e1.source, e2.source) 18677db96d56Sopenharmony_ci self.assertEqual(e1.lineno, e2.lineno) 18687db96d56Sopenharmony_ci self.assertEqual(repr(e1), repr(e2)) 18697db96d56Sopenharmony_ci 18707db96d56Sopenharmony_ci 18717db96d56Sopenharmony_ciclass InlineCommentStrippingTestCase(unittest.TestCase): 18727db96d56Sopenharmony_ci """Tests for issue #14590: ConfigParser doesn't strip inline comment when 18737db96d56Sopenharmony_ci delimiter occurs earlier without preceding space..""" 18747db96d56Sopenharmony_ci 18757db96d56Sopenharmony_ci def test_stripping(self): 18767db96d56Sopenharmony_ci cfg = configparser.ConfigParser(inline_comment_prefixes=(';', '#', 18777db96d56Sopenharmony_ci '//')) 18787db96d56Sopenharmony_ci cfg.read_string(""" 18797db96d56Sopenharmony_ci [section] 18807db96d56Sopenharmony_ci k1 = v1;still v1 18817db96d56Sopenharmony_ci k2 = v2 ;a comment 18827db96d56Sopenharmony_ci k3 = v3 ; also a comment 18837db96d56Sopenharmony_ci k4 = v4;still v4 ;a comment 18847db96d56Sopenharmony_ci k5 = v5;still v5 ; also a comment 18857db96d56Sopenharmony_ci k6 = v6;still v6; and still v6 ;a comment 18867db96d56Sopenharmony_ci k7 = v7;still v7; and still v7 ; also a comment 18877db96d56Sopenharmony_ci 18887db96d56Sopenharmony_ci [multiprefix] 18897db96d56Sopenharmony_ci k1 = v1;still v1 #a comment ; yeah, pretty much 18907db96d56Sopenharmony_ci k2 = v2 // this already is a comment ; continued 18917db96d56Sopenharmony_ci k3 = v3;#//still v3# and still v3 ; a comment 18927db96d56Sopenharmony_ci """) 18937db96d56Sopenharmony_ci s = cfg['section'] 18947db96d56Sopenharmony_ci self.assertEqual(s['k1'], 'v1;still v1') 18957db96d56Sopenharmony_ci self.assertEqual(s['k2'], 'v2') 18967db96d56Sopenharmony_ci self.assertEqual(s['k3'], 'v3') 18977db96d56Sopenharmony_ci self.assertEqual(s['k4'], 'v4;still v4') 18987db96d56Sopenharmony_ci self.assertEqual(s['k5'], 'v5;still v5') 18997db96d56Sopenharmony_ci self.assertEqual(s['k6'], 'v6;still v6; and still v6') 19007db96d56Sopenharmony_ci self.assertEqual(s['k7'], 'v7;still v7; and still v7') 19017db96d56Sopenharmony_ci s = cfg['multiprefix'] 19027db96d56Sopenharmony_ci self.assertEqual(s['k1'], 'v1;still v1') 19037db96d56Sopenharmony_ci self.assertEqual(s['k2'], 'v2') 19047db96d56Sopenharmony_ci self.assertEqual(s['k3'], 'v3;#//still v3# and still v3') 19057db96d56Sopenharmony_ci 19067db96d56Sopenharmony_ci 19077db96d56Sopenharmony_ciclass ExceptionContextTestCase(unittest.TestCase): 19087db96d56Sopenharmony_ci """ Test that implementation details doesn't leak 19097db96d56Sopenharmony_ci through raising exceptions. """ 19107db96d56Sopenharmony_ci 19117db96d56Sopenharmony_ci def test_get_basic_interpolation(self): 19127db96d56Sopenharmony_ci parser = configparser.ConfigParser() 19137db96d56Sopenharmony_ci parser.read_string(""" 19147db96d56Sopenharmony_ci [Paths] 19157db96d56Sopenharmony_ci home_dir: /Users 19167db96d56Sopenharmony_ci my_dir: %(home_dir1)s/lumberjack 19177db96d56Sopenharmony_ci my_pictures: %(my_dir)s/Pictures 19187db96d56Sopenharmony_ci """) 19197db96d56Sopenharmony_ci cm = self.assertRaises(configparser.InterpolationMissingOptionError) 19207db96d56Sopenharmony_ci with cm: 19217db96d56Sopenharmony_ci parser.get('Paths', 'my_dir') 19227db96d56Sopenharmony_ci self.assertIs(cm.exception.__suppress_context__, True) 19237db96d56Sopenharmony_ci 19247db96d56Sopenharmony_ci def test_get_extended_interpolation(self): 19257db96d56Sopenharmony_ci parser = configparser.ConfigParser( 19267db96d56Sopenharmony_ci interpolation=configparser.ExtendedInterpolation()) 19277db96d56Sopenharmony_ci parser.read_string(""" 19287db96d56Sopenharmony_ci [Paths] 19297db96d56Sopenharmony_ci home_dir: /Users 19307db96d56Sopenharmony_ci my_dir: ${home_dir1}/lumberjack 19317db96d56Sopenharmony_ci my_pictures: ${my_dir}/Pictures 19327db96d56Sopenharmony_ci """) 19337db96d56Sopenharmony_ci cm = self.assertRaises(configparser.InterpolationMissingOptionError) 19347db96d56Sopenharmony_ci with cm: 19357db96d56Sopenharmony_ci parser.get('Paths', 'my_dir') 19367db96d56Sopenharmony_ci self.assertIs(cm.exception.__suppress_context__, True) 19377db96d56Sopenharmony_ci 19387db96d56Sopenharmony_ci def test_missing_options(self): 19397db96d56Sopenharmony_ci parser = configparser.ConfigParser() 19407db96d56Sopenharmony_ci parser.read_string(""" 19417db96d56Sopenharmony_ci [Paths] 19427db96d56Sopenharmony_ci home_dir: /Users 19437db96d56Sopenharmony_ci """) 19447db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError) as cm: 19457db96d56Sopenharmony_ci parser.options('test') 19467db96d56Sopenharmony_ci self.assertIs(cm.exception.__suppress_context__, True) 19477db96d56Sopenharmony_ci 19487db96d56Sopenharmony_ci def test_missing_section(self): 19497db96d56Sopenharmony_ci config = configparser.ConfigParser() 19507db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError) as cm: 19517db96d56Sopenharmony_ci config.set('Section1', 'an_int', '15') 19527db96d56Sopenharmony_ci self.assertIs(cm.exception.__suppress_context__, True) 19537db96d56Sopenharmony_ci 19547db96d56Sopenharmony_ci def test_remove_option(self): 19557db96d56Sopenharmony_ci config = configparser.ConfigParser() 19567db96d56Sopenharmony_ci with self.assertRaises(configparser.NoSectionError) as cm: 19577db96d56Sopenharmony_ci config.remove_option('Section1', 'an_int') 19587db96d56Sopenharmony_ci self.assertIs(cm.exception.__suppress_context__, True) 19597db96d56Sopenharmony_ci 19607db96d56Sopenharmony_ci 19617db96d56Sopenharmony_ciclass ConvertersTestCase(BasicTestCase, unittest.TestCase): 19627db96d56Sopenharmony_ci """Introduced in 3.5, issue #18159.""" 19637db96d56Sopenharmony_ci 19647db96d56Sopenharmony_ci config_class = configparser.ConfigParser 19657db96d56Sopenharmony_ci 19667db96d56Sopenharmony_ci def newconfig(self, defaults=None): 19677db96d56Sopenharmony_ci instance = super().newconfig(defaults=defaults) 19687db96d56Sopenharmony_ci instance.converters['list'] = lambda v: [e.strip() for e in v.split() 19697db96d56Sopenharmony_ci if e.strip()] 19707db96d56Sopenharmony_ci return instance 19717db96d56Sopenharmony_ci 19727db96d56Sopenharmony_ci def test_converters(self): 19737db96d56Sopenharmony_ci cfg = self.newconfig() 19747db96d56Sopenharmony_ci self.assertIn('boolean', cfg.converters) 19757db96d56Sopenharmony_ci self.assertIn('list', cfg.converters) 19767db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['int']) 19777db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['float']) 19787db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['boolean']) 19797db96d56Sopenharmony_ci self.assertIsNotNone(cfg.converters['list']) 19807db96d56Sopenharmony_ci self.assertEqual(len(cfg.converters), 4) 19817db96d56Sopenharmony_ci with self.assertRaises(ValueError): 19827db96d56Sopenharmony_ci cfg.converters[''] = lambda v: v 19837db96d56Sopenharmony_ci with self.assertRaises(ValueError): 19847db96d56Sopenharmony_ci cfg.converters[None] = lambda v: v 19857db96d56Sopenharmony_ci cfg.read_string(""" 19867db96d56Sopenharmony_ci [s] 19877db96d56Sopenharmony_ci str = string 19887db96d56Sopenharmony_ci int = 1 19897db96d56Sopenharmony_ci float = 0.5 19907db96d56Sopenharmony_ci list = a b c d e f g 19917db96d56Sopenharmony_ci bool = yes 19927db96d56Sopenharmony_ci """) 19937db96d56Sopenharmony_ci s = cfg['s'] 19947db96d56Sopenharmony_ci self.assertEqual(s['str'], 'string') 19957db96d56Sopenharmony_ci self.assertEqual(s['int'], '1') 19967db96d56Sopenharmony_ci self.assertEqual(s['float'], '0.5') 19977db96d56Sopenharmony_ci self.assertEqual(s['list'], 'a b c d e f g') 19987db96d56Sopenharmony_ci self.assertEqual(s['bool'], 'yes') 19997db96d56Sopenharmony_ci self.assertEqual(cfg.get('s', 'str'), 'string') 20007db96d56Sopenharmony_ci self.assertEqual(cfg.get('s', 'int'), '1') 20017db96d56Sopenharmony_ci self.assertEqual(cfg.get('s', 'float'), '0.5') 20027db96d56Sopenharmony_ci self.assertEqual(cfg.get('s', 'list'), 'a b c d e f g') 20037db96d56Sopenharmony_ci self.assertEqual(cfg.get('s', 'bool'), 'yes') 20047db96d56Sopenharmony_ci self.assertEqual(cfg.get('s', 'str'), 'string') 20057db96d56Sopenharmony_ci self.assertEqual(cfg.getint('s', 'int'), 1) 20067db96d56Sopenharmony_ci self.assertEqual(cfg.getfloat('s', 'float'), 0.5) 20077db96d56Sopenharmony_ci self.assertEqual(cfg.getlist('s', 'list'), ['a', 'b', 'c', 'd', 20087db96d56Sopenharmony_ci 'e', 'f', 'g']) 20097db96d56Sopenharmony_ci self.assertEqual(cfg.getboolean('s', 'bool'), True) 20107db96d56Sopenharmony_ci self.assertEqual(s.get('str'), 'string') 20117db96d56Sopenharmony_ci self.assertEqual(s.getint('int'), 1) 20127db96d56Sopenharmony_ci self.assertEqual(s.getfloat('float'), 0.5) 20137db96d56Sopenharmony_ci self.assertEqual(s.getlist('list'), ['a', 'b', 'c', 'd', 20147db96d56Sopenharmony_ci 'e', 'f', 'g']) 20157db96d56Sopenharmony_ci self.assertEqual(s.getboolean('bool'), True) 20167db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 20177db96d56Sopenharmony_ci cfg.getdecimal('s', 'float') 20187db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 20197db96d56Sopenharmony_ci s.getdecimal('float') 20207db96d56Sopenharmony_ci import decimal 20217db96d56Sopenharmony_ci cfg.converters['decimal'] = decimal.Decimal 20227db96d56Sopenharmony_ci self.assertIn('decimal', cfg.converters) 20237db96d56Sopenharmony_ci self.assertIsNotNone(cfg.converters['decimal']) 20247db96d56Sopenharmony_ci self.assertEqual(len(cfg.converters), 5) 20257db96d56Sopenharmony_ci dec0_5 = decimal.Decimal('0.5') 20267db96d56Sopenharmony_ci self.assertEqual(cfg.getdecimal('s', 'float'), dec0_5) 20277db96d56Sopenharmony_ci self.assertEqual(s.getdecimal('float'), dec0_5) 20287db96d56Sopenharmony_ci del cfg.converters['decimal'] 20297db96d56Sopenharmony_ci self.assertNotIn('decimal', cfg.converters) 20307db96d56Sopenharmony_ci self.assertEqual(len(cfg.converters), 4) 20317db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 20327db96d56Sopenharmony_ci cfg.getdecimal('s', 'float') 20337db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 20347db96d56Sopenharmony_ci s.getdecimal('float') 20357db96d56Sopenharmony_ci with self.assertRaises(KeyError): 20367db96d56Sopenharmony_ci del cfg.converters['decimal'] 20377db96d56Sopenharmony_ci with self.assertRaises(KeyError): 20387db96d56Sopenharmony_ci del cfg.converters[''] 20397db96d56Sopenharmony_ci with self.assertRaises(KeyError): 20407db96d56Sopenharmony_ci del cfg.converters[None] 20417db96d56Sopenharmony_ci 20427db96d56Sopenharmony_ci 20437db96d56Sopenharmony_ciclass BlatantOverrideConvertersTestCase(unittest.TestCase): 20447db96d56Sopenharmony_ci """What if somebody overrode a getboolean()? We want to make sure that in 20457db96d56Sopenharmony_ci this case the automatic converters do not kick in.""" 20467db96d56Sopenharmony_ci 20477db96d56Sopenharmony_ci config = """ 20487db96d56Sopenharmony_ci [one] 20497db96d56Sopenharmony_ci one = false 20507db96d56Sopenharmony_ci two = false 20517db96d56Sopenharmony_ci three = long story short 20527db96d56Sopenharmony_ci 20537db96d56Sopenharmony_ci [two] 20547db96d56Sopenharmony_ci one = false 20557db96d56Sopenharmony_ci two = false 20567db96d56Sopenharmony_ci three = four 20577db96d56Sopenharmony_ci """ 20587db96d56Sopenharmony_ci 20597db96d56Sopenharmony_ci def test_converters_at_init(self): 20607db96d56Sopenharmony_ci cfg = configparser.ConfigParser(converters={'len': len}) 20617db96d56Sopenharmony_ci cfg.read_string(self.config) 20627db96d56Sopenharmony_ci self._test_len(cfg) 20637db96d56Sopenharmony_ci self.assertIsNotNone(cfg.converters['len']) 20647db96d56Sopenharmony_ci 20657db96d56Sopenharmony_ci def test_inheritance(self): 20667db96d56Sopenharmony_ci class StrangeConfigParser(configparser.ConfigParser): 20677db96d56Sopenharmony_ci gettysburg = 'a historic borough in south central Pennsylvania' 20687db96d56Sopenharmony_ci 20697db96d56Sopenharmony_ci def getboolean(self, section, option, *, raw=False, vars=None, 20707db96d56Sopenharmony_ci fallback=configparser._UNSET): 20717db96d56Sopenharmony_ci if section == option: 20727db96d56Sopenharmony_ci return True 20737db96d56Sopenharmony_ci return super().getboolean(section, option, raw=raw, vars=vars, 20747db96d56Sopenharmony_ci fallback=fallback) 20757db96d56Sopenharmony_ci def getlen(self, section, option, *, raw=False, vars=None, 20767db96d56Sopenharmony_ci fallback=configparser._UNSET): 20777db96d56Sopenharmony_ci return self._get_conv(section, option, len, raw=raw, vars=vars, 20787db96d56Sopenharmony_ci fallback=fallback) 20797db96d56Sopenharmony_ci 20807db96d56Sopenharmony_ci cfg = StrangeConfigParser() 20817db96d56Sopenharmony_ci cfg.read_string(self.config) 20827db96d56Sopenharmony_ci self._test_len(cfg) 20837db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['len']) 20847db96d56Sopenharmony_ci self.assertTrue(cfg.getboolean('one', 'one')) 20857db96d56Sopenharmony_ci self.assertTrue(cfg.getboolean('two', 'two')) 20867db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('one', 'two')) 20877db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('two', 'one')) 20887db96d56Sopenharmony_ci cfg.converters['boolean'] = cfg._convert_to_boolean 20897db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('one', 'one')) 20907db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('two', 'two')) 20917db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('one', 'two')) 20927db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('two', 'one')) 20937db96d56Sopenharmony_ci 20947db96d56Sopenharmony_ci def _test_len(self, cfg): 20957db96d56Sopenharmony_ci self.assertEqual(len(cfg.converters), 4) 20967db96d56Sopenharmony_ci self.assertIn('boolean', cfg.converters) 20977db96d56Sopenharmony_ci self.assertIn('len', cfg.converters) 20987db96d56Sopenharmony_ci self.assertNotIn('tysburg', cfg.converters) 20997db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['int']) 21007db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['float']) 21017db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['boolean']) 21027db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('one', 'one'), 5) 21037db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('one', 'two'), 5) 21047db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('one', 'three'), 16) 21057db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'one'), 5) 21067db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'two'), 5) 21077db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'three'), 4) 21087db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'four', fallback=0), 0) 21097db96d56Sopenharmony_ci with self.assertRaises(configparser.NoOptionError): 21107db96d56Sopenharmony_ci cfg.getlen('two', 'four') 21117db96d56Sopenharmony_ci self.assertEqual(cfg['one'].getlen('one'), 5) 21127db96d56Sopenharmony_ci self.assertEqual(cfg['one'].getlen('two'), 5) 21137db96d56Sopenharmony_ci self.assertEqual(cfg['one'].getlen('three'), 16) 21147db96d56Sopenharmony_ci self.assertEqual(cfg['two'].getlen('one'), 5) 21157db96d56Sopenharmony_ci self.assertEqual(cfg['two'].getlen('two'), 5) 21167db96d56Sopenharmony_ci self.assertEqual(cfg['two'].getlen('three'), 4) 21177db96d56Sopenharmony_ci self.assertEqual(cfg['two'].getlen('four', 0), 0) 21187db96d56Sopenharmony_ci self.assertEqual(cfg['two'].getlen('four'), None) 21197db96d56Sopenharmony_ci 21207db96d56Sopenharmony_ci def test_instance_assignment(self): 21217db96d56Sopenharmony_ci cfg = configparser.ConfigParser() 21227db96d56Sopenharmony_ci cfg.getboolean = lambda section, option: True 21237db96d56Sopenharmony_ci cfg.getlen = lambda section, option: len(cfg[section][option]) 21247db96d56Sopenharmony_ci cfg.read_string(self.config) 21257db96d56Sopenharmony_ci self.assertEqual(len(cfg.converters), 3) 21267db96d56Sopenharmony_ci self.assertIn('boolean', cfg.converters) 21277db96d56Sopenharmony_ci self.assertNotIn('len', cfg.converters) 21287db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['int']) 21297db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['float']) 21307db96d56Sopenharmony_ci self.assertIsNone(cfg.converters['boolean']) 21317db96d56Sopenharmony_ci self.assertTrue(cfg.getboolean('one', 'one')) 21327db96d56Sopenharmony_ci self.assertTrue(cfg.getboolean('two', 'two')) 21337db96d56Sopenharmony_ci self.assertTrue(cfg.getboolean('one', 'two')) 21347db96d56Sopenharmony_ci self.assertTrue(cfg.getboolean('two', 'one')) 21357db96d56Sopenharmony_ci cfg.converters['boolean'] = cfg._convert_to_boolean 21367db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('one', 'one')) 21377db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('two', 'two')) 21387db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('one', 'two')) 21397db96d56Sopenharmony_ci self.assertFalse(cfg.getboolean('two', 'one')) 21407db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('one', 'one'), 5) 21417db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('one', 'two'), 5) 21427db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('one', 'three'), 16) 21437db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'one'), 5) 21447db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'two'), 5) 21457db96d56Sopenharmony_ci self.assertEqual(cfg.getlen('two', 'three'), 4) 21467db96d56Sopenharmony_ci # If a getter impl is assigned straight to the instance, it won't 21477db96d56Sopenharmony_ci # be available on the section proxies. 21487db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 21497db96d56Sopenharmony_ci self.assertEqual(cfg['one'].getlen('one'), 5) 21507db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 21517db96d56Sopenharmony_ci self.assertEqual(cfg['two'].getlen('one'), 5) 21527db96d56Sopenharmony_ci 21537db96d56Sopenharmony_ci 21547db96d56Sopenharmony_ciclass MiscTestCase(unittest.TestCase): 21557db96d56Sopenharmony_ci def test__all__(self): 21567db96d56Sopenharmony_ci support.check__all__(self, configparser, not_exported={"Error"}) 21577db96d56Sopenharmony_ci 21587db96d56Sopenharmony_ci 21597db96d56Sopenharmony_ciif __name__ == '__main__': 21607db96d56Sopenharmony_ci unittest.main() 2161