summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_cfgparser.py
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2010-08-09 12:52:45 (GMT)
committerFred Drake <fdrake@acm.org>2010-08-09 12:52:45 (GMT)
commita492362f9a2a44e411147fd7b2886466bb0bb17f (patch)
tree0e150dd20d8c8add5b3282bbac9efe16b8696e21 /Lib/test/test_cfgparser.py
parentf14c2632806ec19b0d58c2c1f721c6a31b535209 (diff)
downloadcpython-a492362f9a2a44e411147fd7b2886466bb0bb17f.zip
cpython-a492362f9a2a44e411147fd7b2886466bb0bb17f.tar.gz
cpython-a492362f9a2a44e411147fd7b2886466bb0bb17f.tar.bz2
issue #9452:
Add read_file, read_string, and read_dict to the configparser API; new source attribute to exceptions.
Diffstat (limited to 'Lib/test/test_cfgparser.py')
-rw-r--r--Lib/test/test_cfgparser.py243
1 files changed, 179 insertions, 64 deletions
diff --git a/Lib/test/test_cfgparser.py b/Lib/test/test_cfgparser.py
index e54ccfe..f43d1d7 100644
--- a/Lib/test/test_cfgparser.py
+++ b/Lib/test/test_cfgparser.py
@@ -30,62 +30,28 @@ class CfgParserTestCaseClass(unittest.TestCase):
comment_prefixes = (';', '#')
empty_lines_in_values = True
dict_type = configparser._default_dict
+ strict = False
def newconfig(self, defaults=None):
arguments = dict(
+ defaults=defaults,
allow_no_value=self.allow_no_value,
delimiters=self.delimiters,
comment_prefixes=self.comment_prefixes,
empty_lines_in_values=self.empty_lines_in_values,
dict_type=self.dict_type,
+ strict=self.strict,
)
- if defaults is None:
- self.cf = self.config_class(**arguments)
- else:
- self.cf = self.config_class(defaults,
- **arguments)
- return self.cf
+ return self.config_class(**arguments)
def fromstring(self, string, defaults=None):
cf = self.newconfig(defaults)
- sio = io.StringIO(string)
- cf.readfp(sio)
+ cf.read_string(string)
return cf
class BasicTestCase(CfgParserTestCaseClass):
- def test_basic(self):
- config_string = """\
-[Foo Bar]
-foo{0[0]}bar
-[Spacey Bar]
-foo {0[0]} bar
-[Spacey Bar From The Beginning]
- foo {0[0]} bar
- baz {0[0]} qwe
-[Commented Bar]
-foo{0[1]} bar {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
- likes it.
-[Section\\with$weird%characters[\t]
-[Internationalized Stuff]
-foo[bg]{0[1]} Bulgarian
-foo{0[0]}Default
-foo[en]{0[0]}English
-foo[de]{0[0]}Deutsch
-[Spaces]
-key with spaces {0[1]} value
-another with spaces {0[0]} splat!
-""".format(self.delimiters, self.comment_prefixes)
- if self.allow_no_value:
- config_string += (
- "[NoValue]\n"
- "option-without-value\n"
- )
-
- cf = self.fromstring(config_string)
+ def basic_test(self, cf):
L = cf.sections()
L.sort()
E = ['Commented Bar',
@@ -137,6 +103,125 @@ another with spaces {0[0]} splat!
eq(cf.get('Long Line', 'foo'),
'this line is much, much longer than my editor\nlikes it.')
+ def test_basic(self):
+ config_string = """\
+[Foo Bar]
+foo{0[0]}bar
+[Spacey Bar]
+foo {0[0]} bar
+[Spacey Bar From The Beginning]
+ foo {0[0]} bar
+ baz {0[0]} qwe
+[Commented Bar]
+foo{0[1]} bar {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
+ likes it.
+[Section\\with$weird%characters[\t]
+[Internationalized Stuff]
+foo[bg]{0[1]} Bulgarian
+foo{0[0]}Default
+foo[en]{0[0]}English
+foo[de]{0[0]}Deutsch
+[Spaces]
+key with spaces {0[1]} value
+another with spaces {0[0]} splat!
+""".format(self.delimiters, self.comment_prefixes)
+ if self.allow_no_value:
+ config_string += (
+ "[NoValue]\n"
+ "option-without-value\n"
+ )
+ cf = self.fromstring(config_string)
+ self.basic_test(cf)
+ if self.strict:
+ with self.assertRaises(configparser.DuplicateOptionError):
+ cf.read_string(textwrap.dedent("""\
+ [Duplicate Options Here]
+ option {0[0]} with a value
+ option {0[1]} with another value
+ """.format(self.delimiters)))
+ with self.assertRaises(configparser.DuplicateSectionError):
+ cf.read_string(textwrap.dedent("""\
+ [And Now For Something]
+ completely different {0[0]} True
+ [And Now For Something]
+ the larch {0[1]} 1
+ """.format(self.delimiters)))
+ else:
+ cf.read_string(textwrap.dedent("""\
+ [Duplicate Options Here]
+ option {0[0]} with a value
+ option {0[1]} with another value
+ """.format(self.delimiters)))
+
+ cf.read_string(textwrap.dedent("""\
+ [And Now For Something]
+ completely different {0[0]} True
+ [And Now For Something]
+ the larch {0[1]} 1
+ """.format(self.delimiters)))
+
+ def test_basic_from_dict(self):
+ config = {
+ "Foo Bar": {
+ "foo": "bar",
+ },
+ "Spacey Bar": {
+ "foo": "bar",
+ },
+ "Spacey Bar From The Beginning": {
+ "foo": "bar",
+ "baz": "qwe",
+ },
+ "Commented Bar": {
+ "foo": "bar",
+ "baz": "qwe",
+ },
+ "Long Line": {
+ "foo": "this line is much, much longer than my editor\nlikes "
+ "it.",
+ },
+ "Section\\with$weird%characters[\t": {
+ },
+ "Internationalized Stuff": {
+ "foo[bg]": "Bulgarian",
+ "foo": "Default",
+ "foo[en]": "English",
+ "foo[de]": "Deutsch",
+ },
+ "Spaces": {
+ "key with spaces": "value",
+ "another with spaces": "splat!",
+ }
+ }
+ if self.allow_no_value:
+ config.update({
+ "NoValue": {
+ "option-without-value": None,
+ }
+ })
+ cf = self.newconfig()
+ cf.read_dict(config)
+ self.basic_test(cf)
+ if self.strict:
+ with self.assertRaises(configparser.DuplicateOptionError):
+ cf.read_dict({
+ "Duplicate Options Here": {
+ 'option': 'with a value',
+ 'OPTION': 'with another value',
+ },
+ })
+ else:
+ cf.read_dict({
+ "Duplicate Options Here": {
+ 'option': 'with a value',
+ 'OPTION': 'with another value',
+ },
+ })
+
+
def test_case_sensitivity(self):
cf = self.newconfig()
cf.add_section("A")
@@ -185,25 +270,25 @@ another with spaces {0[0]} splat!
"could not locate option, expecting case-insensitive defaults")
def test_parse_errors(self):
- self.newconfig()
- self.parse_error(configparser.ParsingError,
+ cf = self.newconfig()
+ self.parse_error(cf, configparser.ParsingError,
"[Foo]\n"
"{}val-without-opt-name\n".format(self.delimiters[0]))
- self.parse_error(configparser.ParsingError,
+ self.parse_error(cf, configparser.ParsingError,
"[Foo]\n"
"{}val-without-opt-name\n".format(self.delimiters[1]))
- e = self.parse_error(configparser.MissingSectionHeaderError,
+ e = self.parse_error(cf, configparser.MissingSectionHeaderError,
"No Section!\n")
self.assertEqual(e.args, ('<???>', 1, "No Section!\n"))
if not self.allow_no_value:
- e = self.parse_error(configparser.ParsingError,
+ e = self.parse_error(cf, configparser.ParsingError,
"[Foo]\n wrong-indent\n")
self.assertEqual(e.args, ('<???>',))
- def parse_error(self, exc, src):
+ def parse_error(self, cf, exc, src):
sio = io.StringIO(src)
with self.assertRaises(exc) as cm:
- self.cf.readfp(sio)
+ cf.read_file(sio)
return cm.exception
def test_query_errors(self):
@@ -217,15 +302,15 @@ another with spaces {0[0]} splat!
cf.options("Foo")
with self.assertRaises(configparser.NoSectionError):
cf.set("foo", "bar", "value")
- e = self.get_error(configparser.NoSectionError, "foo", "bar")
+ e = self.get_error(cf, configparser.NoSectionError, "foo", "bar")
self.assertEqual(e.args, ("foo",))
cf.add_section("foo")
- e = self.get_error(configparser.NoOptionError, "foo", "bar")
+ e = self.get_error(cf, configparser.NoOptionError, "foo", "bar")
self.assertEqual(e.args, ("bar", "foo"))
- def get_error(self, exc, section, option):
+ def get_error(self, cf, exc, section, option):
try:
- self.cf.get(section, option)
+ cf.get(section, option)
except exc as e:
return e
else:
@@ -262,7 +347,31 @@ another with spaces {0[0]} splat!
cf.add_section("Foo")
with self.assertRaises(configparser.DuplicateSectionError) as cm:
cf.add_section("Foo")
- self.assertEqual(cm.exception.args, ("Foo",))
+ e = cm.exception
+ self.assertEqual(str(e), "Section 'Foo' already exists")
+ self.assertEqual(e.args, ("Foo", None, None))
+
+ if self.strict:
+ with self.assertRaises(configparser.DuplicateSectionError) as cm:
+ cf.read_string(textwrap.dedent("""\
+ [Foo]
+ will this be added{equals}True
+ [Bar]
+ what about this{equals}True
+ [Foo]
+ oops{equals}this won't
+ """.format(equals=self.delimiters[0])), source='<foo-bar>')
+ e = cm.exception
+ self.assertEqual(str(e), "While reading from <foo-bar> [line 5]: "
+ "section 'Foo' already exists")
+ self.assertEqual(e.args, ("Foo", '<foo-bar>', 5))
+
+ with self.assertRaises(configparser.DuplicateOptionError) as cm:
+ cf.read_dict({'Bar': {'opt': 'val', 'OPT': 'is really `opt`'}})
+ e = cm.exception
+ self.assertEqual(str(e), "While reading from <dict>: option 'opt' "
+ "in section 'Bar' already exists")
+ self.assertEqual(e.args, ("Bar", "opt", "<dict>", None))
def test_write(self):
config_string = (
@@ -392,6 +501,11 @@ another with spaces {0[0]} splat!
self.assertEqual(L, expected)
+class StrictTestCase(BasicTestCase):
+ config_class = configparser.RawConfigParser
+ strict = True
+
+
class ConfigParserTestCase(BasicTestCase):
config_class = configparser.ConfigParser
@@ -409,7 +523,7 @@ class ConfigParserTestCase(BasicTestCase):
"something with lots of interpolation (9 steps)")
eq(cf.get("Foo", "bar10"),
"something with lots of interpolation (10 steps)")
- e = self.get_error(configparser.InterpolationDepthError, "Foo", "bar11")
+ e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11")
self.assertEqual(e.args, ("bar11", "Foo", rawval[self.config_class]))
def test_interpolation_missing_value(self):
@@ -417,8 +531,8 @@ class ConfigParserTestCase(BasicTestCase):
configparser.ConfigParser: '%(reference)s',
configparser.SafeConfigParser: '',
}
- self.get_interpolation_config()
- e = self.get_error(configparser.InterpolationMissingOptionError,
+ cf = self.get_interpolation_config()
+ e = self.get_error(cf, configparser.InterpolationMissingOptionError,
"Interpolation Error", "name")
self.assertEqual(e.reference, "reference")
self.assertEqual(e.section, "Interpolation Error")
@@ -482,7 +596,7 @@ class MultilineValuesTestCase(BasicTestCase):
# during performance updates in Python 3.2
cf_from_file = self.newconfig()
with open(support.TESTFN) as f:
- cf_from_file.readfp(f)
+ cf_from_file.read_file(f)
self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'),
self.wonderful_spam.replace('\t\n', '\n'))
@@ -645,15 +759,15 @@ class SortedTestCase(RawConfigParserTestCase):
dict_type = SortedDict
def test_sorted(self):
- self.fromstring("[b]\n"
- "o4=1\n"
- "o3=2\n"
- "o2=3\n"
- "o1=4\n"
- "[a]\n"
- "k=v\n")
+ cf = self.fromstring("[b]\n"
+ "o4=1\n"
+ "o3=2\n"
+ "o2=3\n"
+ "o1=4\n"
+ "[a]\n"
+ "k=v\n")
output = io.StringIO()
- self.cf.write(output)
+ cf.write(output)
self.assertEquals(output.getvalue(),
"[a]\n"
"k = v\n\n"
@@ -697,6 +811,7 @@ def test_main():
SafeConfigParserTestCaseNoValue,
SafeConfigParserTestCaseTrickyFile,
SortedTestCase,
+ StrictTestCase,
CompatibleTestCase,
)