blob: 2409bf94e972460ed298408309060f73f070d4a0 [file] [log] [blame]
Fred Drake8ef67672000-09-27 22:45:25 +00001import ConfigParser
2import StringIO
Fred Drakec6f28912002-10-25 19:40:49 +00003import unittest
Fred Drake8ef67672000-09-27 22:45:25 +00004
Fred Drakec6f28912002-10-25 19:40:49 +00005from test import test_support
Fred Drake3d5f7e82000-12-04 16:30:40 +00006
7
Fred Drakec6f28912002-10-25 19:40:49 +00008class TestCaseBase(unittest.TestCase):
9 def newconfig(self, defaults=None):
10 if defaults is None:
11 self.cf = self.config_class()
12 else:
13 self.cf = self.config_class(defaults)
14 return self.cf
Fred Drake8ef67672000-09-27 22:45:25 +000015
Fred Drakec6f28912002-10-25 19:40:49 +000016 def fromstring(self, string, defaults=None):
17 cf = self.newconfig(defaults)
18 sio = StringIO.StringIO(string)
19 cf.readfp(sio)
20 return cf
Fred Drake8ef67672000-09-27 22:45:25 +000021
Fred Drakec6f28912002-10-25 19:40:49 +000022 def test_basic(self):
23 cf = self.fromstring(
24 "[Foo Bar]\n"
25 "foo=bar\n"
26 "[Spacey Bar]\n"
27 "foo = bar\n"
28 "[Commented Bar]\n"
29 "foo: bar ; comment\n"
30 "[Long Line]\n"
31 "foo: this line is much, much longer than my editor\n"
32 " likes it.\n"
33 "[Section\\with$weird%characters[\t]\n"
34 "[Internationalized Stuff]\n"
35 "foo[bg]: Bulgarian\n"
36 "foo=Default\n"
37 "foo[en]=English\n"
38 "foo[de]=Deutsch\n"
39 "[Spaces]\n"
40 "key with spaces : value\n"
41 "another with spaces = splat!\n"
42 )
43 L = cf.sections()
44 L.sort()
45 eq = self.assertEqual
46 eq(L, [r'Commented Bar',
47 r'Foo Bar',
48 r'Internationalized Stuff',
49 r'Long Line',
50 r'Section\with$weird%characters[' '\t',
51 r'Spaces',
52 r'Spacey Bar',
53 ])
Fred Drake8ef67672000-09-27 22:45:25 +000054
Fred Drakec6f28912002-10-25 19:40:49 +000055 # The use of spaces in the section names serves as a
56 # regression test for SourceForge bug #583248:
57 # http://www.python.org/sf/583248
58 eq(cf.get('Foo Bar', 'foo'), 'bar')
59 eq(cf.get('Spacey Bar', 'foo'), 'bar')
60 eq(cf.get('Commented Bar', 'foo'), 'bar')
61 eq(cf.get('Spaces', 'key with spaces'), 'value')
62 eq(cf.get('Spaces', 'another with spaces'), 'splat!')
Fred Drake3d5f7e82000-12-04 16:30:40 +000063
Fred Drakec6f28912002-10-25 19:40:49 +000064 self.failIf('__name__' in cf.options("Foo Bar"),
65 '__name__ "option" should not be exposed by the API!')
66
67 # Make sure the right things happen for remove_option();
68 # added to include check for SourceForge bug #123324:
69 self.failUnless(cf.remove_option('Foo Bar', 'foo'),
70 "remove_option() failed to report existance of option")
71 self.failIf(cf.has_option('Foo Bar', 'foo'),
72 "remove_option() failed to remove option")
73 self.failIf(cf.remove_option('Foo Bar', 'foo'),
74 "remove_option() failed to report non-existance of option"
75 " that was removed")
76
77 self.assertRaises(ConfigParser.NoSectionError,
78 cf.remove_option, 'No Such Section', 'foo')
79
80 eq(cf.get('Long Line', 'foo'),
Andrew M. Kuchling1bf71172002-03-08 18:10:12 +000081 'this line is much, much longer than my editor\nlikes it.')
Fred Drake3d5f7e82000-12-04 16:30:40 +000082
Fred Drakec6f28912002-10-25 19:40:49 +000083 def test_case_sensitivity(self):
84 cf = self.newconfig()
85 cf.add_section("A")
86 cf.add_section("a")
87 L = cf.sections()
88 L.sort()
89 eq = self.assertEqual
90 eq(L, ["A", "a"])
91 cf.set("a", "B", "value")
92 eq(cf.options("a"), ["b"])
93 eq(cf.get("a", "b"), "value",
Fred Drake3c823aa2001-02-26 21:55:34 +000094 "could not locate option, expecting case-insensitive option names")
Fred Drakec6f28912002-10-25 19:40:49 +000095 self.failUnless(cf.has_option("a", "b"))
96 cf.set("A", "A-B", "A-B value")
97 for opt in ("a-b", "A-b", "a-B", "A-B"):
98 self.failUnless(
99 cf.has_option("A", opt),
100 "has_option() returned false for option which should exist")
101 eq(cf.options("A"), ["a-b"])
102 eq(cf.options("a"), ["b"])
103 cf.remove_option("a", "B")
104 eq(cf.options("a"), [])
Fred Drake3c823aa2001-02-26 21:55:34 +0000105
Fred Drakec6f28912002-10-25 19:40:49 +0000106 # SF bug #432369:
107 cf = self.fromstring(
108 "[MySection]\nOption: first line\n\tsecond line\n")
109 eq(cf.options("MySection"), ["option"])
110 eq(cf.get("MySection", "Option"), "first line\nsecond line")
Fred Drakebeb67132001-07-06 17:22:48 +0000111
Fred Drakec6f28912002-10-25 19:40:49 +0000112 # SF bug #561822:
113 cf = self.fromstring("[section]\nnekey=nevalue\n",
114 defaults={"key":"value"})
115 self.failUnless(cf.has_option("section", "Key"))
Fred Drake309db062002-09-27 15:35:23 +0000116
Fred Drake3c823aa2001-02-26 21:55:34 +0000117
Fred Drakec6f28912002-10-25 19:40:49 +0000118 def test_parse_errors(self):
119 self.newconfig()
120 self.parse_error(ConfigParser.ParsingError,
121 "[Foo]\n extra-spaces: splat\n")
122 self.parse_error(ConfigParser.ParsingError,
123 "[Foo]\n extra-spaces= splat\n")
124 self.parse_error(ConfigParser.ParsingError,
125 "[Foo]\noption-without-value\n")
126 self.parse_error(ConfigParser.ParsingError,
127 "[Foo]\n:value-without-option-name\n")
128 self.parse_error(ConfigParser.ParsingError,
129 "[Foo]\n=value-without-option-name\n")
130 self.parse_error(ConfigParser.MissingSectionHeaderError,
131 "No Section!\n")
Fred Drake168bead2001-10-08 17:13:12 +0000132
Fred Drakec6f28912002-10-25 19:40:49 +0000133 def parse_error(self, exc, src):
134 sio = StringIO.StringIO(src)
135 self.assertRaises(exc, self.cf.readfp, sio)
Fred Drake168bead2001-10-08 17:13:12 +0000136
Fred Drakec6f28912002-10-25 19:40:49 +0000137 def test_query_errors(self):
138 cf = self.newconfig()
139 self.assertEqual(cf.sections(), [],
140 "new ConfigParser should have no defined sections")
141 self.failIf(cf.has_section("Foo"),
142 "new ConfigParser should have no acknowledged sections")
143 self.assertRaises(ConfigParser.NoSectionError,
144 cf.options, "Foo")
145 self.assertRaises(ConfigParser.NoSectionError,
146 cf.set, "foo", "bar", "value")
147 self.get_error(ConfigParser.NoSectionError, "foo", "bar")
148 cf.add_section("foo")
149 self.get_error(ConfigParser.NoOptionError, "foo", "bar")
Fred Drake8ef67672000-09-27 22:45:25 +0000150
Fred Drakec6f28912002-10-25 19:40:49 +0000151 def get_error(self, exc, section, option):
152 self.assertRaises(exc, self.cf.get, section, option)
Fred Drake3af0eb82002-10-25 18:09:24 +0000153
Fred Drakec6f28912002-10-25 19:40:49 +0000154 def test_boolean(self):
155 cf = self.fromstring(
156 "[BOOLTEST]\n"
157 "T1=1\n"
158 "T2=TRUE\n"
159 "T3=True\n"
160 "T4=oN\n"
161 "T5=yes\n"
162 "F1=0\n"
163 "F2=FALSE\n"
164 "F3=False\n"
165 "F4=oFF\n"
166 "F5=nO\n"
167 "E1=2\n"
168 "E2=foo\n"
169 "E3=-1\n"
170 "E4=0.1\n"
171 "E5=FALSE AND MORE"
172 )
173 for x in range(1, 5):
174 self.failUnless(cf.getboolean('BOOLTEST', 't%d' % x))
175 self.failIf(cf.getboolean('BOOLTEST', 'f%d' % x))
176 self.assertRaises(ValueError,
177 cf.getboolean, 'BOOLTEST', 'e%d' % x)
Fred Drake95b96d32001-02-12 17:23:20 +0000178
Fred Drakec6f28912002-10-25 19:40:49 +0000179 def test_weird_errors(self):
180 cf = self.newconfig()
Fred Drake8ef67672000-09-27 22:45:25 +0000181 cf.add_section("Foo")
Fred Drakec6f28912002-10-25 19:40:49 +0000182 self.assertRaises(ConfigParser.DuplicateSectionError,
183 cf.add_section, "Foo")
184
185 def test_write(self):
186 cf = self.fromstring(
187 "[Long Line]\n"
188 "foo: this line is much, much longer than my editor\n"
189 " likes it.\n"
190 "[DEFAULT]\n"
191 "foo: another very\n"
192 " long line"
193 )
194 output = StringIO.StringIO()
195 cf.write(output)
196 self.assertEqual(
197 output.getvalue(),
198 "[DEFAULT]\n"
199 "foo = another very\n"
200 "\tlong line\n"
201 "\n"
202 "[Long Line]\n"
203 "foo = this line is much, much longer than my editor\n"
204 "\tlikes it.\n"
205 "\n"
206 )
207
208 # shared by subclasses
209 def get_interpolation_config(self):
210 return self.fromstring(
211 "[Foo]\n"
212 "bar=something %(with1)s interpolation (1 step)\n"
213 "bar9=something %(with9)s lots of interpolation (9 steps)\n"
214 "bar10=something %(with10)s lots of interpolation (10 steps)\n"
215 "bar11=something %(with11)s lots of interpolation (11 steps)\n"
216 "with11=%(with10)s\n"
217 "with10=%(with9)s\n"
218 "with9=%(with8)s\n"
219 "with8=%(with7)s\n"
220 "with7=%(with6)s\n"
221 "with6=%(with5)s\n"
222 "with5=%(with4)s\n"
223 "with4=%(with3)s\n"
224 "with3=%(with2)s\n"
225 "with2=%(with1)s\n"
226 "with1=with\n"
227 "\n"
228 "[Mutual Recursion]\n"
229 "foo=%(bar)s\n"
230 "bar=%(foo)s\n",
231 defaults={"getname": "%(__name__)s"})
Fred Drake95b96d32001-02-12 17:23:20 +0000232
Fred Drake8ef67672000-09-27 22:45:25 +0000233
Fred Drakec6f28912002-10-25 19:40:49 +0000234class ConfigParserTestCase(TestCaseBase):
235 config_class = ConfigParser.ConfigParser
236
237 def test_interpolation(self):
238 cf = self.get_interpolation_config()
239 eq = self.assertEqual
240 eq(cf.get("Foo", "getname"), "Foo")
241 eq(cf.get("Foo", "bar"), "something with interpolation (1 step)")
242 eq(cf.get("Foo", "bar9"),
243 "something with lots of interpolation (9 steps)")
244 eq(cf.get("Foo", "bar10"),
245 "something with lots of interpolation (10 steps)")
246 self.get_error(ConfigParser.InterpolationDepthError, "Foo", "bar11")
Fred Drake95b96d32001-02-12 17:23:20 +0000247
Fred Drake8ef67672000-09-27 22:45:25 +0000248
Fred Drakec6f28912002-10-25 19:40:49 +0000249class RawConfigParserTestCase(TestCaseBase):
250 config_class = ConfigParser.RawConfigParser
251
252 def test_interpolation(self):
253 cf = self.get_interpolation_config()
254 eq = self.assertEqual
255 eq(cf.get("Foo", "getname"), "%(__name__)s")
256 eq(cf.get("Foo", "bar"),
257 "something %(with1)s interpolation (1 step)")
258 eq(cf.get("Foo", "bar9"),
259 "something %(with9)s lots of interpolation (9 steps)")
260 eq(cf.get("Foo", "bar10"),
261 "something %(with10)s lots of interpolation (10 steps)")
262 eq(cf.get("Foo", "bar11"),
263 "something %(with11)s lots of interpolation (11 steps)")
Fred Drake95b96d32001-02-12 17:23:20 +0000264
Fred Drake8ef67672000-09-27 22:45:25 +0000265
Fred Drakec6f28912002-10-25 19:40:49 +0000266def test_main():
267 suite = unittest.TestSuite()
268 suite.addTests([unittest.makeSuite(ConfigParserTestCase),
269 unittest.makeSuite(RawConfigParserTestCase)])
270 test_support.run_suite(suite)
Fred Drake3af0eb82002-10-25 18:09:24 +0000271
Fred Drakec6f28912002-10-25 19:40:49 +0000272if __name__ == "__main__":
273 test_main()