diff options
author | Łukasz Langa <lukasz@langa.pl> | 2010-11-10 18:57:39 (GMT) |
---|---|---|
committer | Łukasz Langa <lukasz@langa.pl> | 2010-11-10 18:57:39 (GMT) |
commit | 26d513cf2ff31ba7c4f8862d5d28cb4cfa71de67 (patch) | |
tree | 058c9a6c41ea34dfd04472c5328463e063bbdcd9 /Lib/test/test_cfgparser.py | |
parent | 47f637ce17022464307b093cee6f367e2dc7f024 (diff) | |
download | cpython-26d513cf2ff31ba7c4f8862d5d28cb4cfa71de67.zip cpython-26d513cf2ff31ba7c4f8862d5d28cb4cfa71de67.tar.gz cpython-26d513cf2ff31ba7c4f8862d5d28cb4cfa71de67.tar.bz2 |
Issue #5412: extend configparser to support mapping access
Diffstat (limited to 'Lib/test/test_cfgparser.py')
-rw-r--r-- | Lib/test/test_cfgparser.py | 161 |
1 files changed, 127 insertions, 34 deletions
diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py index f7e240f..11aa267 100644 --- a/Lib/test/test_cfgparser.py +++ b/Lib/test/test_cfgparser.py @@ -52,8 +52,6 @@ class CfgParserTestCaseClass(unittest.TestCase): class BasicTestCase(CfgParserTestCaseClass): def basic_test(self, cf): - L = cf.sections() - L.sort() E = ['Commented Bar', 'Foo Bar', 'Internationalized Stuff', @@ -64,20 +62,34 @@ class BasicTestCase(CfgParserTestCaseClass): 'Spacey Bar From The Beginning', 'Types', ] + if self.allow_no_value: E.append('NoValue') E.sort() + + # API access + L = cf.sections() + L.sort() eq = self.assertEqual eq(L, E) + # mapping access + L = [section for section in cf] + L.sort() + E.append(configparser.DEFAULTSECT) + E.sort() + eq(L, E) + # The use of spaces in the section names serves as a # regression test for SourceForge bug #583248: # http://www.python.org/sf/583248 - eq(cf.get('Foo Bar', 'foo'), 'bar') - eq(cf.get('Spacey Bar', 'foo'), 'bar') - eq(cf.get('Spacey Bar From The Beginning', 'foo'), 'bar') + + # API access + eq(cf.get('Foo Bar', 'foo'), 'bar1') + eq(cf.get('Spacey Bar', 'foo'), 'bar2') + eq(cf.get('Spacey Bar From The Beginning', 'foo'), 'bar3') eq(cf.get('Spacey Bar From The Beginning', 'baz'), 'qwe') - eq(cf.get('Commented Bar', 'foo'), 'bar') + eq(cf.get('Commented Bar', 'foo'), 'bar4') eq(cf.get('Commented Bar', 'baz'), 'qwe') eq(cf.get('Spaces', 'key with spaces'), 'value') eq(cf.get('Spaces', 'another with spaces'), 'splat!') @@ -89,40 +101,69 @@ class BasicTestCase(CfgParserTestCaseClass): if self.allow_no_value: eq(cf.get('NoValue', 'option-without-value'), None) - # test vars= and default= - eq(cf.get('Foo Bar', 'foo', default='baz'), 'bar') + # test vars= and fallback= + eq(cf.get('Foo Bar', 'foo', fallback='baz'), 'bar1') eq(cf.get('Foo Bar', 'foo', vars={'foo': 'baz'}), 'baz') with self.assertRaises(configparser.NoSectionError): cf.get('No Such Foo Bar', 'foo') with self.assertRaises(configparser.NoOptionError): cf.get('Foo Bar', 'no-such-foo') - eq(cf.get('No Such Foo Bar', 'foo', default='baz'), 'baz') - eq(cf.get('Foo Bar', 'no-such-foo', default='baz'), 'baz') - eq(cf.get('Spacey Bar', 'foo', default=None), 'bar') - eq(cf.get('No Such Spacey Bar', 'foo', default=None), None) - eq(cf.getint('Types', 'int', default=18), 42) - eq(cf.getint('Types', 'no-such-int', default=18), 18) - eq(cf.getint('Types', 'no-such-int', default="18"), "18") # sic! + eq(cf.get('No Such Foo Bar', 'foo', fallback='baz'), 'baz') + eq(cf.get('Foo Bar', 'no-such-foo', fallback='baz'), 'baz') + eq(cf.get('Spacey Bar', 'foo', fallback=None), 'bar2') + eq(cf.get('No Such Spacey Bar', 'foo', fallback=None), None) + eq(cf.getint('Types', 'int', fallback=18), 42) + eq(cf.getint('Types', 'no-such-int', fallback=18), 18) + eq(cf.getint('Types', 'no-such-int', fallback="18"), "18") # sic! self.assertAlmostEqual(cf.getfloat('Types', 'float', - default=0.0), 0.44) + fallback=0.0), 0.44) self.assertAlmostEqual(cf.getfloat('Types', 'no-such-float', - default=0.0), 0.0) - eq(cf.getfloat('Types', 'no-such-float', default="0.0"), "0.0") # sic! - eq(cf.getboolean('Types', 'boolean', default=True), False) - eq(cf.getboolean('Types', 'no-such-boolean', default="yes"), + fallback=0.0), 0.0) + eq(cf.getfloat('Types', 'no-such-float', fallback="0.0"), "0.0") # sic! + eq(cf.getboolean('Types', 'boolean', fallback=True), False) + eq(cf.getboolean('Types', 'no-such-boolean', fallback="yes"), "yes") # sic! - eq(cf.getboolean('Types', 'no-such-boolean', default=True), True) - eq(cf.getboolean('No Such Types', 'boolean', default=True), True) + eq(cf.getboolean('Types', 'no-such-boolean', fallback=True), True) + eq(cf.getboolean('No Such Types', 'boolean', fallback=True), True) if self.allow_no_value: - eq(cf.get('NoValue', 'option-without-value', default=False), None) + eq(cf.get('NoValue', 'option-without-value', fallback=False), None) eq(cf.get('NoValue', 'no-such-option-without-value', - default=False), False) + fallback=False), False) + + # mapping access + eq(cf['Foo Bar']['foo'], 'bar1') + eq(cf['Spacey Bar']['foo'], 'bar2') + eq(cf['Spacey Bar From The Beginning']['foo'], 'bar3') + eq(cf['Spacey Bar From The Beginning']['baz'], 'qwe') + eq(cf['Commented Bar']['foo'], 'bar4') + eq(cf['Commented Bar']['baz'], 'qwe') + eq(cf['Spaces']['key with spaces'], 'value') + eq(cf['Spaces']['another with spaces'], 'splat!') + eq(cf['Long Line']['foo'], + 'this line is much, much longer than my editor\nlikes it.') + if self.allow_no_value: + eq(cf['NoValue']['option-without-value'], None) + # API access self.assertNotIn('__name__', cf.options("Foo Bar"), '__name__ "option" should not be exposed by the API!') + # mapping access + self.assertNotIn('__name__', cf['Foo Bar'], + '__name__ "option" should not be exposed by ' + 'mapping protocol access') + self.assertFalse('__name__' in cf['Foo Bar']) + with self.assertRaises(ValueError): + cf['Foo Bar']['__name__'] + with self.assertRaises(ValueError): + del cf['Foo Bar']['__name__'] + with self.assertRaises(ValueError): + cf['Foo Bar']['__name__'] = "can't write to this special name" + # Make sure the right things happen for remove_option(); # added to include check for SourceForge bug #123324: + + # API acceess self.assertTrue(cf.remove_option('Foo Bar', 'foo'), "remove_option() failed to report existence of option") self.assertFalse(cf.has_option('Foo Bar', 'foo'), @@ -138,17 +179,25 @@ class BasicTestCase(CfgParserTestCaseClass): eq(cf.get('Long Line', 'foo'), 'this line is much, much longer than my editor\nlikes it.') + # mapping access + del cf['Spacey Bar']['foo'] + self.assertFalse('foo' in cf['Spacey Bar']) + with self.assertRaises(KeyError): + del cf['Spacey Bar']['foo'] + with self.assertRaises(KeyError): + del cf['No Such Section']['foo'] + def test_basic(self): config_string = """\ [Foo Bar] -foo{0[0]}bar +foo{0[0]}bar1 [Spacey Bar] -foo {0[0]} bar +foo {0[0]} bar2 [Spacey Bar From The Beginning] - foo {0[0]} bar + foo {0[0]} bar3 baz {0[0]} qwe [Commented Bar] -foo{0[1]} bar {1[1]} comment +foo{0[1]} bar4 {1[1]} comment baz{0[0]}qwe {1[0]}another one [Long Line] foo{0[1]} this line is much, much longer than my editor @@ -205,17 +254,17 @@ boolean {0[0]} NO def test_basic_from_dict(self): config = { "Foo Bar": { - "foo": "bar", + "foo": "bar1", }, "Spacey Bar": { - "foo": "bar", + "foo": "bar2", }, "Spacey Bar From The Beginning": { - "foo": "bar", + "foo": "bar3", "baz": "qwe", }, "Commented Bar": { - "foo": "bar", + "foo": "bar4", "baz": "qwe", }, "Long Line": { @@ -270,14 +319,18 @@ boolean {0[0]} NO cf = self.newconfig() cf.add_section("A") cf.add_section("a") + cf.add_section("B") L = cf.sections() L.sort() eq = self.assertEqual - eq(L, ["A", "a"]) + eq(L, ["A", "B", "a"]) cf.set("a", "B", "value") eq(cf.options("a"), ["b"]) eq(cf.get("a", "b"), "value", "could not locate option, expecting case-insensitive option names") + with self.assertRaises(configparser.NoSectionError): + # section names are case-sensitive + cf.set("b", "A", "value") self.assertTrue(cf.has_option("a", "b")) cf.set("A", "A-B", "A-B value") for opt in ("a-b", "A-b", "a-B", "A-B"): @@ -291,7 +344,7 @@ boolean {0[0]} NO # SF bug #432369: cf = self.fromstring( - "[MySection]\nOption{} first line\n\tsecond line\n".format( + "[MySection]\nOption{} first line \n\tsecond line \n".format( self.delimiters[0])) eq(cf.options("MySection"), ["option"]) eq(cf.get("MySection", "Option"), "first line\nsecond line") @@ -303,6 +356,46 @@ boolean {0[0]} NO self.assertTrue(cf.has_option("section", "Key")) + def test_case_sensitivity_mapping_access(self): + cf = self.newconfig() + cf["A"] = {} + cf["a"] = {"B": "value"} + cf["B"] = {} + L = [section for section in cf] + L.sort() + eq = self.assertEqual + elem_eq = self.assertItemsEqual + eq(L, ["A", "B", configparser.DEFAULTSECT, "a"]) + eq(cf["a"].keys(), {"b"}) + eq(cf["a"]["b"], "value", + "could not locate option, expecting case-insensitive option names") + with self.assertRaises(KeyError): + # section names are case-sensitive + cf["b"]["A"] = "value" + self.assertTrue("b" in cf["a"]) + cf["A"]["A-B"] = "A-B value" + for opt in ("a-b", "A-b", "a-B", "A-B"): + self.assertTrue( + opt in cf["A"], + "has_option() returned false for option which should exist") + eq(cf["A"].keys(), {"a-b"}) + eq(cf["a"].keys(), {"b"}) + del cf["a"]["B"] + elem_eq(cf["a"].keys(), {}) + + # SF bug #432369: + cf = self.fromstring( + "[MySection]\nOption{} first line \n\tsecond line \n".format( + self.delimiters[0])) + eq(cf["MySection"].keys(), {"option"}) + eq(cf["MySection"]["Option"], "first line\nsecond line") + + # SF bug #561822: + cf = self.fromstring("[section]\n" + "nekey{}nevalue\n".format(self.delimiters[0]), + defaults={"key":"value"}) + self.assertTrue("Key" in cf["section"]) + def test_default_case_sensitivity(self): cf = self.newconfig({"foo": "Bar"}) self.assertEqual( |