| 1 | n/a | import collections | 
|---|
| 2 | n/a | import configparser | 
|---|
| 3 | n/a | import io | 
|---|
| 4 | n/a | import os | 
|---|
| 5 | n/a | import textwrap | 
|---|
| 6 | n/a | import unittest | 
|---|
| 7 | n/a | import warnings | 
|---|
| 8 | n/a |  | 
|---|
| 9 | n/a | from test import support | 
|---|
| 10 | n/a |  | 
|---|
| 11 | n/a |  | 
|---|
| 12 | n/a | class SortedDict(collections.UserDict): | 
|---|
| 13 | n/a |  | 
|---|
| 14 | n/a |     def items(self): | 
|---|
| 15 | n/a |         return sorted(self.data.items()) | 
|---|
| 16 | n/a |  | 
|---|
| 17 | n/a |     def keys(self): | 
|---|
| 18 | n/a |         return sorted(self.data.keys()) | 
|---|
| 19 | n/a |  | 
|---|
| 20 | n/a |     def values(self): | 
|---|
| 21 | n/a |         return [i[1] for i in self.items()] | 
|---|
| 22 | n/a |  | 
|---|
| 23 | n/a |     def iteritems(self): | 
|---|
| 24 | n/a |         return iter(self.items()) | 
|---|
| 25 | n/a |  | 
|---|
| 26 | n/a |     def iterkeys(self): | 
|---|
| 27 | n/a |         return iter(self.keys()) | 
|---|
| 28 | n/a |  | 
|---|
| 29 | n/a |     def itervalues(self): | 
|---|
| 30 | n/a |         return iter(self.values()) | 
|---|
| 31 | n/a |  | 
|---|
| 32 | n/a |     __iter__ = iterkeys | 
|---|
| 33 | n/a |  | 
|---|
| 34 | n/a |  | 
|---|
| 35 | n/a | class CfgParserTestCaseClass: | 
|---|
| 36 | n/a |     allow_no_value = False | 
|---|
| 37 | n/a |     delimiters = ('=', ':') | 
|---|
| 38 | n/a |     comment_prefixes = (';', '#') | 
|---|
| 39 | n/a |     inline_comment_prefixes = (';', '#') | 
|---|
| 40 | n/a |     empty_lines_in_values = True | 
|---|
| 41 | n/a |     dict_type = configparser._default_dict | 
|---|
| 42 | n/a |     strict = False | 
|---|
| 43 | n/a |     default_section = configparser.DEFAULTSECT | 
|---|
| 44 | n/a |     interpolation = configparser._UNSET | 
|---|
| 45 | n/a |  | 
|---|
| 46 | n/a |     def newconfig(self, defaults=None): | 
|---|
| 47 | n/a |         arguments = dict( | 
|---|
| 48 | n/a |             defaults=defaults, | 
|---|
| 49 | n/a |             allow_no_value=self.allow_no_value, | 
|---|
| 50 | n/a |             delimiters=self.delimiters, | 
|---|
| 51 | n/a |             comment_prefixes=self.comment_prefixes, | 
|---|
| 52 | n/a |             inline_comment_prefixes=self.inline_comment_prefixes, | 
|---|
| 53 | n/a |             empty_lines_in_values=self.empty_lines_in_values, | 
|---|
| 54 | n/a |             dict_type=self.dict_type, | 
|---|
| 55 | n/a |             strict=self.strict, | 
|---|
| 56 | n/a |             default_section=self.default_section, | 
|---|
| 57 | n/a |             interpolation=self.interpolation, | 
|---|
| 58 | n/a |         ) | 
|---|
| 59 | n/a |         instance = self.config_class(**arguments) | 
|---|
| 60 | n/a |         return instance | 
|---|
| 61 | n/a |  | 
|---|
| 62 | n/a |     def fromstring(self, string, defaults=None): | 
|---|
| 63 | n/a |         cf = self.newconfig(defaults) | 
|---|
| 64 | n/a |         cf.read_string(string) | 
|---|
| 65 | n/a |         return cf | 
|---|
| 66 | n/a |  | 
|---|
| 67 | n/a |  | 
|---|
| 68 | n/a | class BasicTestCase(CfgParserTestCaseClass): | 
|---|
| 69 | n/a |  | 
|---|
| 70 | n/a |     def basic_test(self, cf): | 
|---|
| 71 | n/a |         E = ['Commented Bar', | 
|---|
| 72 | n/a |              'Foo Bar', | 
|---|
| 73 | n/a |              'Internationalized Stuff', | 
|---|
| 74 | n/a |              'Long Line', | 
|---|
| 75 | n/a |              'Section\\with$weird%characters[\t', | 
|---|
| 76 | n/a |              'Spaces', | 
|---|
| 77 | n/a |              'Spacey Bar', | 
|---|
| 78 | n/a |              'Spacey Bar From The Beginning', | 
|---|
| 79 | n/a |              'Types', | 
|---|
| 80 | n/a |              ] | 
|---|
| 81 | n/a |  | 
|---|
| 82 | n/a |         if self.allow_no_value: | 
|---|
| 83 | n/a |             E.append('NoValue') | 
|---|
| 84 | n/a |         E.sort() | 
|---|
| 85 | n/a |         F = [('baz', 'qwe'), ('foo', 'bar3')] | 
|---|
| 86 | n/a |  | 
|---|
| 87 | n/a |         # API access | 
|---|
| 88 | n/a |         L = cf.sections() | 
|---|
| 89 | n/a |         L.sort() | 
|---|
| 90 | n/a |         eq = self.assertEqual | 
|---|
| 91 | n/a |         eq(L, E) | 
|---|
| 92 | n/a |         L = cf.items('Spacey Bar From The Beginning') | 
|---|
| 93 | n/a |         L.sort() | 
|---|
| 94 | n/a |         eq(L, F) | 
|---|
| 95 | n/a |  | 
|---|
| 96 | n/a |         # mapping access | 
|---|
| 97 | n/a |         L = [section for section in cf] | 
|---|
| 98 | n/a |         L.sort() | 
|---|
| 99 | n/a |         E.append(self.default_section) | 
|---|
| 100 | n/a |         E.sort() | 
|---|
| 101 | n/a |         eq(L, E) | 
|---|
| 102 | n/a |         L = cf['Spacey Bar From The Beginning'].items() | 
|---|
| 103 | n/a |         L = sorted(list(L)) | 
|---|
| 104 | n/a |         eq(L, F) | 
|---|
| 105 | n/a |         L = cf.items() | 
|---|
| 106 | n/a |         L = sorted(list(L)) | 
|---|
| 107 | n/a |         self.assertEqual(len(L), len(E)) | 
|---|
| 108 | n/a |         for name, section in L: | 
|---|
| 109 | n/a |             eq(name, section.name) | 
|---|
| 110 | n/a |         eq(cf.defaults(), cf[self.default_section]) | 
|---|
| 111 | n/a |  | 
|---|
| 112 | n/a |         # The use of spaces in the section names serves as a | 
|---|
| 113 | n/a |         # regression test for SourceForge bug #583248: | 
|---|
| 114 | n/a |         # http://www.python.org/sf/583248 | 
|---|
| 115 | n/a |  | 
|---|
| 116 | n/a |         # API access | 
|---|
| 117 | n/a |         eq(cf.get('Foo Bar', 'foo'), 'bar1') | 
|---|
| 118 | n/a |         eq(cf.get('Spacey Bar', 'foo'), 'bar2') | 
|---|
| 119 | n/a |         eq(cf.get('Spacey Bar From The Beginning', 'foo'), 'bar3') | 
|---|
| 120 | n/a |         eq(cf.get('Spacey Bar From The Beginning', 'baz'), 'qwe') | 
|---|
| 121 | n/a |         eq(cf.get('Commented Bar', 'foo'), 'bar4') | 
|---|
| 122 | n/a |         eq(cf.get('Commented Bar', 'baz'), 'qwe') | 
|---|
| 123 | n/a |         eq(cf.get('Spaces', 'key with spaces'), 'value') | 
|---|
| 124 | n/a |         eq(cf.get('Spaces', 'another with spaces'), 'splat!') | 
|---|
| 125 | n/a |         eq(cf.getint('Types', 'int'), 42) | 
|---|
| 126 | n/a |         eq(cf.get('Types', 'int'), "42") | 
|---|
| 127 | n/a |         self.assertAlmostEqual(cf.getfloat('Types', 'float'), 0.44) | 
|---|
| 128 | n/a |         eq(cf.get('Types', 'float'), "0.44") | 
|---|
| 129 | n/a |         eq(cf.getboolean('Types', 'boolean'), False) | 
|---|
| 130 | n/a |         eq(cf.get('Types', '123'), 'strange but acceptable') | 
|---|
| 131 | n/a |         if self.allow_no_value: | 
|---|
| 132 | n/a |             eq(cf.get('NoValue', 'option-without-value'), None) | 
|---|
| 133 | n/a |  | 
|---|
| 134 | n/a |         # test vars= and fallback= | 
|---|
| 135 | n/a |         eq(cf.get('Foo Bar', 'foo', fallback='baz'), 'bar1') | 
|---|
| 136 | n/a |         eq(cf.get('Foo Bar', 'foo', vars={'foo': 'baz'}), 'baz') | 
|---|
| 137 | n/a |         with self.assertRaises(configparser.NoSectionError): | 
|---|
| 138 | n/a |             cf.get('No Such Foo Bar', 'foo') | 
|---|
| 139 | n/a |         with self.assertRaises(configparser.NoOptionError): | 
|---|
| 140 | n/a |             cf.get('Foo Bar', 'no-such-foo') | 
|---|
| 141 | n/a |         eq(cf.get('No Such Foo Bar', 'foo', fallback='baz'), 'baz') | 
|---|
| 142 | n/a |         eq(cf.get('Foo Bar', 'no-such-foo', fallback='baz'), 'baz') | 
|---|
| 143 | n/a |         eq(cf.get('Spacey Bar', 'foo', fallback=None), 'bar2') | 
|---|
| 144 | n/a |         eq(cf.get('No Such Spacey Bar', 'foo', fallback=None), None) | 
|---|
| 145 | n/a |         eq(cf.getint('Types', 'int', fallback=18), 42) | 
|---|
| 146 | n/a |         eq(cf.getint('Types', 'no-such-int', fallback=18), 18) | 
|---|
| 147 | n/a |         eq(cf.getint('Types', 'no-such-int', fallback="18"), "18") # sic! | 
|---|
| 148 | n/a |         with self.assertRaises(configparser.NoOptionError): | 
|---|
| 149 | n/a |             cf.getint('Types', 'no-such-int') | 
|---|
| 150 | n/a |         self.assertAlmostEqual(cf.getfloat('Types', 'float', | 
|---|
| 151 | n/a |                                            fallback=0.0), 0.44) | 
|---|
| 152 | n/a |         self.assertAlmostEqual(cf.getfloat('Types', 'no-such-float', | 
|---|
| 153 | n/a |                                            fallback=0.0), 0.0) | 
|---|
| 154 | n/a |         eq(cf.getfloat('Types', 'no-such-float', fallback="0.0"), "0.0") # sic! | 
|---|
| 155 | n/a |         with self.assertRaises(configparser.NoOptionError): | 
|---|
| 156 | n/a |             cf.getfloat('Types', 'no-such-float') | 
|---|
| 157 | n/a |         eq(cf.getboolean('Types', 'boolean', fallback=True), False) | 
|---|
| 158 | n/a |         eq(cf.getboolean('Types', 'no-such-boolean', fallback="yes"), | 
|---|
| 159 | n/a |            "yes") # sic! | 
|---|
| 160 | n/a |         eq(cf.getboolean('Types', 'no-such-boolean', fallback=True), True) | 
|---|
| 161 | n/a |         with self.assertRaises(configparser.NoOptionError): | 
|---|
| 162 | n/a |             cf.getboolean('Types', 'no-such-boolean') | 
|---|
| 163 | n/a |         eq(cf.getboolean('No Such Types', 'boolean', fallback=True), True) | 
|---|
| 164 | n/a |         if self.allow_no_value: | 
|---|
| 165 | n/a |             eq(cf.get('NoValue', 'option-without-value', fallback=False), None) | 
|---|
| 166 | n/a |             eq(cf.get('NoValue', 'no-such-option-without-value', | 
|---|
| 167 | n/a |                       fallback=False), False) | 
|---|
| 168 | n/a |  | 
|---|
| 169 | n/a |         # mapping access | 
|---|
| 170 | n/a |         eq(cf['Foo Bar']['foo'], 'bar1') | 
|---|
| 171 | n/a |         eq(cf['Spacey Bar']['foo'], 'bar2') | 
|---|
| 172 | n/a |         section = cf['Spacey Bar From The Beginning'] | 
|---|
| 173 | n/a |         eq(section.name, 'Spacey Bar From The Beginning') | 
|---|
| 174 | n/a |         self.assertIs(section.parser, cf) | 
|---|
| 175 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 176 | n/a |             section.name = 'Name is read-only' | 
|---|
| 177 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 178 | n/a |             section.parser = 'Parser is read-only' | 
|---|
| 179 | n/a |         eq(section['foo'], 'bar3') | 
|---|
| 180 | n/a |         eq(section['baz'], 'qwe') | 
|---|
| 181 | n/a |         eq(cf['Commented Bar']['foo'], 'bar4') | 
|---|
| 182 | n/a |         eq(cf['Commented Bar']['baz'], 'qwe') | 
|---|
| 183 | n/a |         eq(cf['Spaces']['key with spaces'], 'value') | 
|---|
| 184 | n/a |         eq(cf['Spaces']['another with spaces'], 'splat!') | 
|---|
| 185 | n/a |         eq(cf['Long Line']['foo'], | 
|---|
| 186 | n/a |            'this line is much, much longer than my editor\nlikes it.') | 
|---|
| 187 | n/a |         if self.allow_no_value: | 
|---|
| 188 | n/a |             eq(cf['NoValue']['option-without-value'], None) | 
|---|
| 189 | n/a |         # test vars= and fallback= | 
|---|
| 190 | n/a |         eq(cf['Foo Bar'].get('foo', 'baz'), 'bar1') | 
|---|
| 191 | n/a |         eq(cf['Foo Bar'].get('foo', fallback='baz'), 'bar1') | 
|---|
| 192 | n/a |         eq(cf['Foo Bar'].get('foo', vars={'foo': 'baz'}), 'baz') | 
|---|
| 193 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 194 | n/a |             cf['No Such Foo Bar']['foo'] | 
|---|
| 195 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 196 | n/a |             cf['Foo Bar']['no-such-foo'] | 
|---|
| 197 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 198 | n/a |             cf['No Such Foo Bar'].get('foo', fallback='baz') | 
|---|
| 199 | n/a |         eq(cf['Foo Bar'].get('no-such-foo', 'baz'), 'baz') | 
|---|
| 200 | n/a |         eq(cf['Foo Bar'].get('no-such-foo', fallback='baz'), 'baz') | 
|---|
| 201 | n/a |         eq(cf['Foo Bar'].get('no-such-foo'), None) | 
|---|
| 202 | n/a |         eq(cf['Spacey Bar'].get('foo', None), 'bar2') | 
|---|
| 203 | n/a |         eq(cf['Spacey Bar'].get('foo', fallback=None), 'bar2') | 
|---|
| 204 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 205 | n/a |             cf['No Such Spacey Bar'].get('foo', None) | 
|---|
| 206 | n/a |         eq(cf['Types'].getint('int', 18), 42) | 
|---|
| 207 | n/a |         eq(cf['Types'].getint('int', fallback=18), 42) | 
|---|
| 208 | n/a |         eq(cf['Types'].getint('no-such-int', 18), 18) | 
|---|
| 209 | n/a |         eq(cf['Types'].getint('no-such-int', fallback=18), 18) | 
|---|
| 210 | n/a |         eq(cf['Types'].getint('no-such-int', "18"), "18") # sic! | 
|---|
| 211 | n/a |         eq(cf['Types'].getint('no-such-int', fallback="18"), "18") # sic! | 
|---|
| 212 | n/a |         eq(cf['Types'].getint('no-such-int'), None) | 
|---|
| 213 | n/a |         self.assertAlmostEqual(cf['Types'].getfloat('float', 0.0), 0.44) | 
|---|
| 214 | n/a |         self.assertAlmostEqual(cf['Types'].getfloat('float', | 
|---|
| 215 | n/a |                                                     fallback=0.0), 0.44) | 
|---|
| 216 | n/a |         self.assertAlmostEqual(cf['Types'].getfloat('no-such-float', 0.0), 0.0) | 
|---|
| 217 | n/a |         self.assertAlmostEqual(cf['Types'].getfloat('no-such-float', | 
|---|
| 218 | n/a |                                                     fallback=0.0), 0.0) | 
|---|
| 219 | n/a |         eq(cf['Types'].getfloat('no-such-float', "0.0"), "0.0") # sic! | 
|---|
| 220 | n/a |         eq(cf['Types'].getfloat('no-such-float', fallback="0.0"), "0.0") # sic! | 
|---|
| 221 | n/a |         eq(cf['Types'].getfloat('no-such-float'), None) | 
|---|
| 222 | n/a |         eq(cf['Types'].getboolean('boolean', True), False) | 
|---|
| 223 | n/a |         eq(cf['Types'].getboolean('boolean', fallback=True), False) | 
|---|
| 224 | n/a |         eq(cf['Types'].getboolean('no-such-boolean', "yes"), "yes") # sic! | 
|---|
| 225 | n/a |         eq(cf['Types'].getboolean('no-such-boolean', fallback="yes"), | 
|---|
| 226 | n/a |            "yes") # sic! | 
|---|
| 227 | n/a |         eq(cf['Types'].getboolean('no-such-boolean', True), True) | 
|---|
| 228 | n/a |         eq(cf['Types'].getboolean('no-such-boolean', fallback=True), True) | 
|---|
| 229 | n/a |         eq(cf['Types'].getboolean('no-such-boolean'), None) | 
|---|
| 230 | n/a |         if self.allow_no_value: | 
|---|
| 231 | n/a |             eq(cf['NoValue'].get('option-without-value', False), None) | 
|---|
| 232 | n/a |             eq(cf['NoValue'].get('option-without-value', fallback=False), None) | 
|---|
| 233 | n/a |             eq(cf['NoValue'].get('no-such-option-without-value', False), False) | 
|---|
| 234 | n/a |             eq(cf['NoValue'].get('no-such-option-without-value', | 
|---|
| 235 | n/a |                       fallback=False), False) | 
|---|
| 236 | n/a |  | 
|---|
| 237 | n/a |         # Make sure the right things happen for remove_section() and | 
|---|
| 238 | n/a |         # remove_option(); added to include check for SourceForge bug #123324. | 
|---|
| 239 | n/a |  | 
|---|
| 240 | n/a |         cf[self.default_section]['this_value'] = '1' | 
|---|
| 241 | n/a |         cf[self.default_section]['that_value'] = '2' | 
|---|
| 242 | n/a |  | 
|---|
| 243 | n/a |         # API access | 
|---|
| 244 | n/a |         self.assertTrue(cf.remove_section('Spaces')) | 
|---|
| 245 | n/a |         self.assertFalse(cf.has_option('Spaces', 'key with spaces')) | 
|---|
| 246 | n/a |         self.assertFalse(cf.remove_section('Spaces')) | 
|---|
| 247 | n/a |         self.assertFalse(cf.remove_section(self.default_section)) | 
|---|
| 248 | n/a |         self.assertTrue(cf.remove_option('Foo Bar', 'foo'), | 
|---|
| 249 | n/a |                         "remove_option() failed to report existence of option") | 
|---|
| 250 | n/a |         self.assertFalse(cf.has_option('Foo Bar', 'foo'), | 
|---|
| 251 | n/a |                     "remove_option() failed to remove option") | 
|---|
| 252 | n/a |         self.assertFalse(cf.remove_option('Foo Bar', 'foo'), | 
|---|
| 253 | n/a |                     "remove_option() failed to report non-existence of option" | 
|---|
| 254 | n/a |                     " that was removed") | 
|---|
| 255 | n/a |         self.assertTrue(cf.has_option('Foo Bar', 'this_value')) | 
|---|
| 256 | n/a |         self.assertFalse(cf.remove_option('Foo Bar', 'this_value')) | 
|---|
| 257 | n/a |         self.assertTrue(cf.remove_option(self.default_section, 'this_value')) | 
|---|
| 258 | n/a |         self.assertFalse(cf.has_option('Foo Bar', 'this_value')) | 
|---|
| 259 | n/a |         self.assertFalse(cf.remove_option(self.default_section, 'this_value')) | 
|---|
| 260 | n/a |  | 
|---|
| 261 | n/a |         with self.assertRaises(configparser.NoSectionError) as cm: | 
|---|
| 262 | n/a |             cf.remove_option('No Such Section', 'foo') | 
|---|
| 263 | n/a |         self.assertEqual(cm.exception.args, ('No Such Section',)) | 
|---|
| 264 | n/a |  | 
|---|
| 265 | n/a |         eq(cf.get('Long Line', 'foo'), | 
|---|
| 266 | n/a |            'this line is much, much longer than my editor\nlikes it.') | 
|---|
| 267 | n/a |  | 
|---|
| 268 | n/a |         # mapping access | 
|---|
| 269 | n/a |         del cf['Types'] | 
|---|
| 270 | n/a |         self.assertFalse('Types' in cf) | 
|---|
| 271 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 272 | n/a |             del cf['Types'] | 
|---|
| 273 | n/a |         with self.assertRaises(ValueError): | 
|---|
| 274 | n/a |             del cf[self.default_section] | 
|---|
| 275 | n/a |         del cf['Spacey Bar']['foo'] | 
|---|
| 276 | n/a |         self.assertFalse('foo' in cf['Spacey Bar']) | 
|---|
| 277 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 278 | n/a |             del cf['Spacey Bar']['foo'] | 
|---|
| 279 | n/a |         self.assertTrue('that_value' in cf['Spacey Bar']) | 
|---|
| 280 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 281 | n/a |             del cf['Spacey Bar']['that_value'] | 
|---|
| 282 | n/a |         del cf[self.default_section]['that_value'] | 
|---|
| 283 | n/a |         self.assertFalse('that_value' in cf['Spacey Bar']) | 
|---|
| 284 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 285 | n/a |             del cf[self.default_section]['that_value'] | 
|---|
| 286 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 287 | n/a |             del cf['No Such Section']['foo'] | 
|---|
| 288 | n/a |  | 
|---|
| 289 | n/a |         # Don't add new asserts below in this method as most of the options | 
|---|
| 290 | n/a |         # and sections are now removed. | 
|---|
| 291 | n/a |  | 
|---|
| 292 | n/a |     def test_basic(self): | 
|---|
| 293 | n/a |         config_string = """\ | 
|---|
| 294 | n/a | [Foo Bar] | 
|---|
| 295 | n/a | foo{0[0]}bar1 | 
|---|
| 296 | n/a | [Spacey Bar] | 
|---|
| 297 | n/a | foo {0[0]} bar2 | 
|---|
| 298 | n/a | [Spacey Bar From The Beginning] | 
|---|
| 299 | n/a |   foo {0[0]} bar3 | 
|---|
| 300 | n/a |   baz {0[0]} qwe | 
|---|
| 301 | n/a | [Commented Bar] | 
|---|
| 302 | n/a | foo{0[1]} bar4 {1[1]} comment | 
|---|
| 303 | n/a | baz{0[0]}qwe {1[0]}another one | 
|---|
| 304 | n/a | [Long Line] | 
|---|
| 305 | n/a | foo{0[1]} this line is much, much longer than my editor | 
|---|
| 306 | n/a |    likes it. | 
|---|
| 307 | n/a | [Section\\with$weird%characters[\t] | 
|---|
| 308 | n/a | [Internationalized Stuff] | 
|---|
| 309 | n/a | foo[bg]{0[1]} Bulgarian | 
|---|
| 310 | n/a | foo{0[0]}Default | 
|---|
| 311 | n/a | foo[en]{0[0]}English | 
|---|
| 312 | n/a | foo[de]{0[0]}Deutsch | 
|---|
| 313 | n/a | [Spaces] | 
|---|
| 314 | n/a | key with spaces {0[1]} value | 
|---|
| 315 | n/a | another with spaces {0[0]} splat! | 
|---|
| 316 | n/a | [Types] | 
|---|
| 317 | n/a | int {0[1]} 42 | 
|---|
| 318 | n/a | float {0[0]} 0.44 | 
|---|
| 319 | n/a | boolean {0[0]} NO | 
|---|
| 320 | n/a | 123 {0[1]} strange but acceptable | 
|---|
| 321 | n/a | """.format(self.delimiters, self.comment_prefixes) | 
|---|
| 322 | n/a |         if self.allow_no_value: | 
|---|
| 323 | n/a |             config_string += ( | 
|---|
| 324 | n/a |                 "[NoValue]\n" | 
|---|
| 325 | n/a |                 "option-without-value\n" | 
|---|
| 326 | n/a |                 ) | 
|---|
| 327 | n/a |         cf = self.fromstring(config_string) | 
|---|
| 328 | n/a |         self.basic_test(cf) | 
|---|
| 329 | n/a |         if self.strict: | 
|---|
| 330 | n/a |             with self.assertRaises(configparser.DuplicateOptionError): | 
|---|
| 331 | n/a |                 cf.read_string(textwrap.dedent("""\ | 
|---|
| 332 | n/a |                     [Duplicate Options Here] | 
|---|
| 333 | n/a |                     option {0[0]} with a value | 
|---|
| 334 | n/a |                     option {0[1]} with another value | 
|---|
| 335 | n/a |                 """.format(self.delimiters))) | 
|---|
| 336 | n/a |             with self.assertRaises(configparser.DuplicateSectionError): | 
|---|
| 337 | n/a |                 cf.read_string(textwrap.dedent("""\ | 
|---|
| 338 | n/a |                     [And Now For Something] | 
|---|
| 339 | n/a |                     completely different {0[0]} True | 
|---|
| 340 | n/a |                     [And Now For Something] | 
|---|
| 341 | n/a |                     the larch {0[1]} 1 | 
|---|
| 342 | n/a |                 """.format(self.delimiters))) | 
|---|
| 343 | n/a |         else: | 
|---|
| 344 | n/a |             cf.read_string(textwrap.dedent("""\ | 
|---|
| 345 | n/a |                 [Duplicate Options Here] | 
|---|
| 346 | n/a |                 option {0[0]} with a value | 
|---|
| 347 | n/a |                 option {0[1]} with another value | 
|---|
| 348 | n/a |             """.format(self.delimiters))) | 
|---|
| 349 | n/a |  | 
|---|
| 350 | n/a |             cf.read_string(textwrap.dedent("""\ | 
|---|
| 351 | n/a |                 [And Now For Something] | 
|---|
| 352 | n/a |                 completely different {0[0]} True | 
|---|
| 353 | n/a |                 [And Now For Something] | 
|---|
| 354 | n/a |                 the larch {0[1]} 1 | 
|---|
| 355 | n/a |             """.format(self.delimiters))) | 
|---|
| 356 | n/a |  | 
|---|
| 357 | n/a |     def test_basic_from_dict(self): | 
|---|
| 358 | n/a |         config = { | 
|---|
| 359 | n/a |             "Foo Bar": { | 
|---|
| 360 | n/a |                 "foo": "bar1", | 
|---|
| 361 | n/a |             }, | 
|---|
| 362 | n/a |             "Spacey Bar": { | 
|---|
| 363 | n/a |                 "foo": "bar2", | 
|---|
| 364 | n/a |             }, | 
|---|
| 365 | n/a |             "Spacey Bar From The Beginning": { | 
|---|
| 366 | n/a |                 "foo": "bar3", | 
|---|
| 367 | n/a |                 "baz": "qwe", | 
|---|
| 368 | n/a |             }, | 
|---|
| 369 | n/a |             "Commented Bar": { | 
|---|
| 370 | n/a |                 "foo": "bar4", | 
|---|
| 371 | n/a |                 "baz": "qwe", | 
|---|
| 372 | n/a |             }, | 
|---|
| 373 | n/a |             "Long Line": { | 
|---|
| 374 | n/a |                 "foo": "this line is much, much longer than my editor\nlikes " | 
|---|
| 375 | n/a |                        "it.", | 
|---|
| 376 | n/a |             }, | 
|---|
| 377 | n/a |             "Section\\with$weird%characters[\t": { | 
|---|
| 378 | n/a |             }, | 
|---|
| 379 | n/a |             "Internationalized Stuff": { | 
|---|
| 380 | n/a |                 "foo[bg]": "Bulgarian", | 
|---|
| 381 | n/a |                 "foo": "Default", | 
|---|
| 382 | n/a |                 "foo[en]": "English", | 
|---|
| 383 | n/a |                 "foo[de]": "Deutsch", | 
|---|
| 384 | n/a |             }, | 
|---|
| 385 | n/a |             "Spaces": { | 
|---|
| 386 | n/a |                 "key with spaces": "value", | 
|---|
| 387 | n/a |                 "another with spaces": "splat!", | 
|---|
| 388 | n/a |             }, | 
|---|
| 389 | n/a |             "Types": { | 
|---|
| 390 | n/a |                 "int": 42, | 
|---|
| 391 | n/a |                 "float": 0.44, | 
|---|
| 392 | n/a |                 "boolean": False, | 
|---|
| 393 | n/a |                 123: "strange but acceptable", | 
|---|
| 394 | n/a |             }, | 
|---|
| 395 | n/a |         } | 
|---|
| 396 | n/a |         if self.allow_no_value: | 
|---|
| 397 | n/a |             config.update({ | 
|---|
| 398 | n/a |                 "NoValue": { | 
|---|
| 399 | n/a |                     "option-without-value": None, | 
|---|
| 400 | n/a |                 } | 
|---|
| 401 | n/a |             }) | 
|---|
| 402 | n/a |         cf = self.newconfig() | 
|---|
| 403 | n/a |         cf.read_dict(config) | 
|---|
| 404 | n/a |         self.basic_test(cf) | 
|---|
| 405 | n/a |         if self.strict: | 
|---|
| 406 | n/a |             with self.assertRaises(configparser.DuplicateSectionError): | 
|---|
| 407 | n/a |                 cf.read_dict({ | 
|---|
| 408 | n/a |                     '1': {'key': 'value'}, | 
|---|
| 409 | n/a |                     1: {'key2': 'value2'}, | 
|---|
| 410 | n/a |                 }) | 
|---|
| 411 | n/a |             with self.assertRaises(configparser.DuplicateOptionError): | 
|---|
| 412 | n/a |                 cf.read_dict({ | 
|---|
| 413 | n/a |                     "Duplicate Options Here": { | 
|---|
| 414 | n/a |                         'option': 'with a value', | 
|---|
| 415 | n/a |                         'OPTION': 'with another value', | 
|---|
| 416 | n/a |                     }, | 
|---|
| 417 | n/a |                 }) | 
|---|
| 418 | n/a |         else: | 
|---|
| 419 | n/a |             cf.read_dict({ | 
|---|
| 420 | n/a |                 'section': {'key': 'value'}, | 
|---|
| 421 | n/a |                 'SECTION': {'key2': 'value2'}, | 
|---|
| 422 | n/a |             }) | 
|---|
| 423 | n/a |             cf.read_dict({ | 
|---|
| 424 | n/a |                 "Duplicate Options Here": { | 
|---|
| 425 | n/a |                     'option': 'with a value', | 
|---|
| 426 | n/a |                     'OPTION': 'with another value', | 
|---|
| 427 | n/a |                 }, | 
|---|
| 428 | n/a |             }) | 
|---|
| 429 | n/a |  | 
|---|
| 430 | n/a |     def test_case_sensitivity(self): | 
|---|
| 431 | n/a |         cf = self.newconfig() | 
|---|
| 432 | n/a |         cf.add_section("A") | 
|---|
| 433 | n/a |         cf.add_section("a") | 
|---|
| 434 | n/a |         cf.add_section("B") | 
|---|
| 435 | n/a |         L = cf.sections() | 
|---|
| 436 | n/a |         L.sort() | 
|---|
| 437 | n/a |         eq = self.assertEqual | 
|---|
| 438 | n/a |         eq(L, ["A", "B", "a"]) | 
|---|
| 439 | n/a |         cf.set("a", "B", "value") | 
|---|
| 440 | n/a |         eq(cf.options("a"), ["b"]) | 
|---|
| 441 | n/a |         eq(cf.get("a", "b"), "value", | 
|---|
| 442 | n/a |            "could not locate option, expecting case-insensitive option names") | 
|---|
| 443 | n/a |         with self.assertRaises(configparser.NoSectionError): | 
|---|
| 444 | n/a |             # section names are case-sensitive | 
|---|
| 445 | n/a |             cf.set("b", "A", "value") | 
|---|
| 446 | n/a |         self.assertTrue(cf.has_option("a", "b")) | 
|---|
| 447 | n/a |         self.assertFalse(cf.has_option("b", "b")) | 
|---|
| 448 | n/a |         cf.set("A", "A-B", "A-B value") | 
|---|
| 449 | n/a |         for opt in ("a-b", "A-b", "a-B", "A-B"): | 
|---|
| 450 | n/a |             self.assertTrue( | 
|---|
| 451 | n/a |                 cf.has_option("A", opt), | 
|---|
| 452 | n/a |                 "has_option() returned false for option which should exist") | 
|---|
| 453 | n/a |         eq(cf.options("A"), ["a-b"]) | 
|---|
| 454 | n/a |         eq(cf.options("a"), ["b"]) | 
|---|
| 455 | n/a |         cf.remove_option("a", "B") | 
|---|
| 456 | n/a |         eq(cf.options("a"), []) | 
|---|
| 457 | n/a |  | 
|---|
| 458 | n/a |         # SF bug #432369: | 
|---|
| 459 | n/a |         cf = self.fromstring( | 
|---|
| 460 | n/a |             "[MySection]\nOption{} first line   \n\tsecond line   \n".format( | 
|---|
| 461 | n/a |                 self.delimiters[0])) | 
|---|
| 462 | n/a |         eq(cf.options("MySection"), ["option"]) | 
|---|
| 463 | n/a |         eq(cf.get("MySection", "Option"), "first line\nsecond line") | 
|---|
| 464 | n/a |  | 
|---|
| 465 | n/a |         # SF bug #561822: | 
|---|
| 466 | n/a |         cf = self.fromstring("[section]\n" | 
|---|
| 467 | n/a |                              "nekey{}nevalue\n".format(self.delimiters[0]), | 
|---|
| 468 | n/a |                              defaults={"key":"value"}) | 
|---|
| 469 | n/a |         self.assertTrue(cf.has_option("section", "Key")) | 
|---|
| 470 | n/a |  | 
|---|
| 471 | n/a |  | 
|---|
| 472 | n/a |     def test_case_sensitivity_mapping_access(self): | 
|---|
| 473 | n/a |         cf = self.newconfig() | 
|---|
| 474 | n/a |         cf["A"] = {} | 
|---|
| 475 | n/a |         cf["a"] = {"B": "value"} | 
|---|
| 476 | n/a |         cf["B"] = {} | 
|---|
| 477 | n/a |         L = [section for section in cf] | 
|---|
| 478 | n/a |         L.sort() | 
|---|
| 479 | n/a |         eq = self.assertEqual | 
|---|
| 480 | n/a |         elem_eq = self.assertCountEqual | 
|---|
| 481 | n/a |         eq(L, sorted(["A", "B", self.default_section, "a"])) | 
|---|
| 482 | n/a |         eq(cf["a"].keys(), {"b"}) | 
|---|
| 483 | n/a |         eq(cf["a"]["b"], "value", | 
|---|
| 484 | n/a |            "could not locate option, expecting case-insensitive option names") | 
|---|
| 485 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 486 | n/a |             # section names are case-sensitive | 
|---|
| 487 | n/a |             cf["b"]["A"] = "value" | 
|---|
| 488 | n/a |         self.assertTrue("b" in cf["a"]) | 
|---|
| 489 | n/a |         cf["A"]["A-B"] = "A-B value" | 
|---|
| 490 | n/a |         for opt in ("a-b", "A-b", "a-B", "A-B"): | 
|---|
| 491 | n/a |             self.assertTrue( | 
|---|
| 492 | n/a |                 opt in cf["A"], | 
|---|
| 493 | n/a |                 "has_option() returned false for option which should exist") | 
|---|
| 494 | n/a |         eq(cf["A"].keys(), {"a-b"}) | 
|---|
| 495 | n/a |         eq(cf["a"].keys(), {"b"}) | 
|---|
| 496 | n/a |         del cf["a"]["B"] | 
|---|
| 497 | n/a |         elem_eq(cf["a"].keys(), {}) | 
|---|
| 498 | n/a |  | 
|---|
| 499 | n/a |         # SF bug #432369: | 
|---|
| 500 | n/a |         cf = self.fromstring( | 
|---|
| 501 | n/a |             "[MySection]\nOption{} first line   \n\tsecond line   \n".format( | 
|---|
| 502 | n/a |                 self.delimiters[0])) | 
|---|
| 503 | n/a |         eq(cf["MySection"].keys(), {"option"}) | 
|---|
| 504 | n/a |         eq(cf["MySection"]["Option"], "first line\nsecond line") | 
|---|
| 505 | n/a |  | 
|---|
| 506 | n/a |         # SF bug #561822: | 
|---|
| 507 | n/a |         cf = self.fromstring("[section]\n" | 
|---|
| 508 | n/a |                              "nekey{}nevalue\n".format(self.delimiters[0]), | 
|---|
| 509 | n/a |                              defaults={"key":"value"}) | 
|---|
| 510 | n/a |         self.assertTrue("Key" in cf["section"]) | 
|---|
| 511 | n/a |  | 
|---|
| 512 | n/a |     def test_default_case_sensitivity(self): | 
|---|
| 513 | n/a |         cf = self.newconfig({"foo": "Bar"}) | 
|---|
| 514 | n/a |         self.assertEqual( | 
|---|
| 515 | n/a |             cf.get(self.default_section, "Foo"), "Bar", | 
|---|
| 516 | n/a |             "could not locate option, expecting case-insensitive option names") | 
|---|
| 517 | n/a |         cf = self.newconfig({"Foo": "Bar"}) | 
|---|
| 518 | n/a |         self.assertEqual( | 
|---|
| 519 | n/a |             cf.get(self.default_section, "Foo"), "Bar", | 
|---|
| 520 | n/a |             "could not locate option, expecting case-insensitive defaults") | 
|---|
| 521 | n/a |  | 
|---|
| 522 | n/a |     def test_parse_errors(self): | 
|---|
| 523 | n/a |         cf = self.newconfig() | 
|---|
| 524 | n/a |         self.parse_error(cf, configparser.ParsingError, | 
|---|
| 525 | n/a |                          "[Foo]\n" | 
|---|
| 526 | n/a |                          "{}val-without-opt-name\n".format(self.delimiters[0])) | 
|---|
| 527 | n/a |         self.parse_error(cf, configparser.ParsingError, | 
|---|
| 528 | n/a |                          "[Foo]\n" | 
|---|
| 529 | n/a |                          "{}val-without-opt-name\n".format(self.delimiters[1])) | 
|---|
| 530 | n/a |         e = self.parse_error(cf, configparser.MissingSectionHeaderError, | 
|---|
| 531 | n/a |                              "No Section!\n") | 
|---|
| 532 | n/a |         self.assertEqual(e.args, ('<???>', 1, "No Section!\n")) | 
|---|
| 533 | n/a |         if not self.allow_no_value: | 
|---|
| 534 | n/a |             e = self.parse_error(cf, configparser.ParsingError, | 
|---|
| 535 | n/a |                                 "[Foo]\n  wrong-indent\n") | 
|---|
| 536 | n/a |             self.assertEqual(e.args, ('<???>',)) | 
|---|
| 537 | n/a |             # read_file on a real file | 
|---|
| 538 | n/a |             tricky = support.findfile("cfgparser.3") | 
|---|
| 539 | n/a |             if self.delimiters[0] == '=': | 
|---|
| 540 | n/a |                 error = configparser.ParsingError | 
|---|
| 541 | n/a |                 expected = (tricky,) | 
|---|
| 542 | n/a |             else: | 
|---|
| 543 | n/a |                 error = configparser.MissingSectionHeaderError | 
|---|
| 544 | n/a |                 expected = (tricky, 1, | 
|---|
| 545 | n/a |                             '  # INI with as many tricky parts as possible\n') | 
|---|
| 546 | n/a |             with open(tricky, encoding='utf-8') as f: | 
|---|
| 547 | n/a |                 e = self.parse_error(cf, error, f) | 
|---|
| 548 | n/a |             self.assertEqual(e.args, expected) | 
|---|
| 549 | n/a |  | 
|---|
| 550 | n/a |     def parse_error(self, cf, exc, src): | 
|---|
| 551 | n/a |         if hasattr(src, 'readline'): | 
|---|
| 552 | n/a |             sio = src | 
|---|
| 553 | n/a |         else: | 
|---|
| 554 | n/a |             sio = io.StringIO(src) | 
|---|
| 555 | n/a |         with self.assertRaises(exc) as cm: | 
|---|
| 556 | n/a |             cf.read_file(sio) | 
|---|
| 557 | n/a |         return cm.exception | 
|---|
| 558 | n/a |  | 
|---|
| 559 | n/a |     def test_query_errors(self): | 
|---|
| 560 | n/a |         cf = self.newconfig() | 
|---|
| 561 | n/a |         self.assertEqual(cf.sections(), [], | 
|---|
| 562 | n/a |                          "new ConfigParser should have no defined sections") | 
|---|
| 563 | n/a |         self.assertFalse(cf.has_section("Foo"), | 
|---|
| 564 | n/a |                          "new ConfigParser should have no acknowledged " | 
|---|
| 565 | n/a |                          "sections") | 
|---|
| 566 | n/a |         with self.assertRaises(configparser.NoSectionError): | 
|---|
| 567 | n/a |             cf.options("Foo") | 
|---|
| 568 | n/a |         with self.assertRaises(configparser.NoSectionError): | 
|---|
| 569 | n/a |             cf.set("foo", "bar", "value") | 
|---|
| 570 | n/a |         e = self.get_error(cf, configparser.NoSectionError, "foo", "bar") | 
|---|
| 571 | n/a |         self.assertEqual(e.args, ("foo",)) | 
|---|
| 572 | n/a |         cf.add_section("foo") | 
|---|
| 573 | n/a |         e = self.get_error(cf, configparser.NoOptionError, "foo", "bar") | 
|---|
| 574 | n/a |         self.assertEqual(e.args, ("bar", "foo")) | 
|---|
| 575 | n/a |  | 
|---|
| 576 | n/a |     def get_error(self, cf, exc, section, option): | 
|---|
| 577 | n/a |         try: | 
|---|
| 578 | n/a |             cf.get(section, option) | 
|---|
| 579 | n/a |         except exc as e: | 
|---|
| 580 | n/a |             return e | 
|---|
| 581 | n/a |         else: | 
|---|
| 582 | n/a |             self.fail("expected exception type %s.%s" | 
|---|
| 583 | n/a |                       % (exc.__module__, exc.__qualname__)) | 
|---|
| 584 | n/a |  | 
|---|
| 585 | n/a |     def test_boolean(self): | 
|---|
| 586 | n/a |         cf = self.fromstring( | 
|---|
| 587 | n/a |             "[BOOLTEST]\n" | 
|---|
| 588 | n/a |             "T1{equals}1\n" | 
|---|
| 589 | n/a |             "T2{equals}TRUE\n" | 
|---|
| 590 | n/a |             "T3{equals}True\n" | 
|---|
| 591 | n/a |             "T4{equals}oN\n" | 
|---|
| 592 | n/a |             "T5{equals}yes\n" | 
|---|
| 593 | n/a |             "F1{equals}0\n" | 
|---|
| 594 | n/a |             "F2{equals}FALSE\n" | 
|---|
| 595 | n/a |             "F3{equals}False\n" | 
|---|
| 596 | n/a |             "F4{equals}oFF\n" | 
|---|
| 597 | n/a |             "F5{equals}nO\n" | 
|---|
| 598 | n/a |             "E1{equals}2\n" | 
|---|
| 599 | n/a |             "E2{equals}foo\n" | 
|---|
| 600 | n/a |             "E3{equals}-1\n" | 
|---|
| 601 | n/a |             "E4{equals}0.1\n" | 
|---|
| 602 | n/a |             "E5{equals}FALSE AND MORE".format(equals=self.delimiters[0]) | 
|---|
| 603 | n/a |             ) | 
|---|
| 604 | n/a |         for x in range(1, 5): | 
|---|
| 605 | n/a |             self.assertTrue(cf.getboolean('BOOLTEST', 't%d' % x)) | 
|---|
| 606 | n/a |             self.assertFalse(cf.getboolean('BOOLTEST', 'f%d' % x)) | 
|---|
| 607 | n/a |             self.assertRaises(ValueError, | 
|---|
| 608 | n/a |                               cf.getboolean, 'BOOLTEST', 'e%d' % x) | 
|---|
| 609 | n/a |  | 
|---|
| 610 | n/a |     def test_weird_errors(self): | 
|---|
| 611 | n/a |         cf = self.newconfig() | 
|---|
| 612 | n/a |         cf.add_section("Foo") | 
|---|
| 613 | n/a |         with self.assertRaises(configparser.DuplicateSectionError) as cm: | 
|---|
| 614 | n/a |             cf.add_section("Foo") | 
|---|
| 615 | n/a |         e = cm.exception | 
|---|
| 616 | n/a |         self.assertEqual(str(e), "Section 'Foo' already exists") | 
|---|
| 617 | n/a |         self.assertEqual(e.args, ("Foo", None, None)) | 
|---|
| 618 | n/a |  | 
|---|
| 619 | n/a |         if self.strict: | 
|---|
| 620 | n/a |             with self.assertRaises(configparser.DuplicateSectionError) as cm: | 
|---|
| 621 | n/a |                 cf.read_string(textwrap.dedent("""\ | 
|---|
| 622 | n/a |                     [Foo] | 
|---|
| 623 | n/a |                     will this be added{equals}True | 
|---|
| 624 | n/a |                     [Bar] | 
|---|
| 625 | n/a |                     what about this{equals}True | 
|---|
| 626 | n/a |                     [Foo] | 
|---|
| 627 | n/a |                     oops{equals}this won't | 
|---|
| 628 | n/a |                 """.format(equals=self.delimiters[0])), source='<foo-bar>') | 
|---|
| 629 | n/a |             e = cm.exception | 
|---|
| 630 | n/a |             self.assertEqual(str(e), "While reading from '<foo-bar>' " | 
|---|
| 631 | n/a |                                      "[line  5]: section 'Foo' already exists") | 
|---|
| 632 | n/a |             self.assertEqual(e.args, ("Foo", '<foo-bar>', 5)) | 
|---|
| 633 | n/a |  | 
|---|
| 634 | n/a |             with self.assertRaises(configparser.DuplicateOptionError) as cm: | 
|---|
| 635 | n/a |                 cf.read_dict({'Bar': {'opt': 'val', 'OPT': 'is really `opt`'}}) | 
|---|
| 636 | n/a |             e = cm.exception | 
|---|
| 637 | n/a |             self.assertEqual(str(e), "While reading from '<dict>': option " | 
|---|
| 638 | n/a |                                      "'opt' in section 'Bar' already exists") | 
|---|
| 639 | n/a |             self.assertEqual(e.args, ("Bar", "opt", "<dict>", None)) | 
|---|
| 640 | n/a |  | 
|---|
| 641 | n/a |     def test_write(self): | 
|---|
| 642 | n/a |         config_string = ( | 
|---|
| 643 | n/a |             "[Long Line]\n" | 
|---|
| 644 | n/a |             "foo{0[0]} this line is much, much longer than my editor\n" | 
|---|
| 645 | n/a |             "   likes it.\n" | 
|---|
| 646 | n/a |             "[{default_section}]\n" | 
|---|
| 647 | n/a |             "foo{0[1]} another very\n" | 
|---|
| 648 | n/a |             " long line\n" | 
|---|
| 649 | n/a |             "[Long Line - With Comments!]\n" | 
|---|
| 650 | n/a |             "test {0[1]} we        {comment} can\n" | 
|---|
| 651 | n/a |             "            also      {comment} place\n" | 
|---|
| 652 | n/a |             "            comments  {comment} in\n" | 
|---|
| 653 | n/a |             "            multiline {comment} values" | 
|---|
| 654 | n/a |             "\n".format(self.delimiters, comment=self.comment_prefixes[0], | 
|---|
| 655 | n/a |                         default_section=self.default_section) | 
|---|
| 656 | n/a |             ) | 
|---|
| 657 | n/a |         if self.allow_no_value: | 
|---|
| 658 | n/a |             config_string += ( | 
|---|
| 659 | n/a |             "[Valueless]\n" | 
|---|
| 660 | n/a |             "option-without-value\n" | 
|---|
| 661 | n/a |             ) | 
|---|
| 662 | n/a |  | 
|---|
| 663 | n/a |         cf = self.fromstring(config_string) | 
|---|
| 664 | n/a |         for space_around_delimiters in (True, False): | 
|---|
| 665 | n/a |             output = io.StringIO() | 
|---|
| 666 | n/a |             cf.write(output, space_around_delimiters=space_around_delimiters) | 
|---|
| 667 | n/a |             delimiter = self.delimiters[0] | 
|---|
| 668 | n/a |             if space_around_delimiters: | 
|---|
| 669 | n/a |                 delimiter = " {} ".format(delimiter) | 
|---|
| 670 | n/a |             expect_string = ( | 
|---|
| 671 | n/a |                 "[{default_section}]\n" | 
|---|
| 672 | n/a |                 "foo{equals}another very\n" | 
|---|
| 673 | n/a |                 "\tlong line\n" | 
|---|
| 674 | n/a |                 "\n" | 
|---|
| 675 | n/a |                 "[Long Line]\n" | 
|---|
| 676 | n/a |                 "foo{equals}this line is much, much longer than my editor\n" | 
|---|
| 677 | n/a |                 "\tlikes it.\n" | 
|---|
| 678 | n/a |                 "\n" | 
|---|
| 679 | n/a |                 "[Long Line - With Comments!]\n" | 
|---|
| 680 | n/a |                 "test{equals}we\n" | 
|---|
| 681 | n/a |                 "\talso\n" | 
|---|
| 682 | n/a |                 "\tcomments\n" | 
|---|
| 683 | n/a |                 "\tmultiline\n" | 
|---|
| 684 | n/a |                 "\n".format(equals=delimiter, | 
|---|
| 685 | n/a |                             default_section=self.default_section) | 
|---|
| 686 | n/a |                 ) | 
|---|
| 687 | n/a |             if self.allow_no_value: | 
|---|
| 688 | n/a |                 expect_string += ( | 
|---|
| 689 | n/a |                     "[Valueless]\n" | 
|---|
| 690 | n/a |                     "option-without-value\n" | 
|---|
| 691 | n/a |                     "\n" | 
|---|
| 692 | n/a |                     ) | 
|---|
| 693 | n/a |             self.assertEqual(output.getvalue(), expect_string) | 
|---|
| 694 | n/a |  | 
|---|
| 695 | n/a |     def test_set_string_types(self): | 
|---|
| 696 | n/a |         cf = self.fromstring("[sect]\n" | 
|---|
| 697 | n/a |                              "option1{eq}foo\n".format(eq=self.delimiters[0])) | 
|---|
| 698 | n/a |         # Check that we don't get an exception when setting values in | 
|---|
| 699 | n/a |         # an existing section using strings: | 
|---|
| 700 | n/a |         class mystr(str): | 
|---|
| 701 | n/a |             pass | 
|---|
| 702 | n/a |         cf.set("sect", "option1", "splat") | 
|---|
| 703 | n/a |         cf.set("sect", "option1", mystr("splat")) | 
|---|
| 704 | n/a |         cf.set("sect", "option2", "splat") | 
|---|
| 705 | n/a |         cf.set("sect", "option2", mystr("splat")) | 
|---|
| 706 | n/a |         cf.set("sect", "option1", "splat") | 
|---|
| 707 | n/a |         cf.set("sect", "option2", "splat") | 
|---|
| 708 | n/a |  | 
|---|
| 709 | n/a |     def test_read_returns_file_list(self): | 
|---|
| 710 | n/a |         if self.delimiters[0] != '=': | 
|---|
| 711 | n/a |             self.skipTest('incompatible format') | 
|---|
| 712 | n/a |         file1 = support.findfile("cfgparser.1") | 
|---|
| 713 | n/a |         # check when we pass a mix of readable and non-readable files: | 
|---|
| 714 | n/a |         cf = self.newconfig() | 
|---|
| 715 | n/a |         parsed_files = cf.read([file1, "nonexistent-file"]) | 
|---|
| 716 | n/a |         self.assertEqual(parsed_files, [file1]) | 
|---|
| 717 | n/a |         self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") | 
|---|
| 718 | n/a |         # check when we pass only a filename: | 
|---|
| 719 | n/a |         cf = self.newconfig() | 
|---|
| 720 | n/a |         parsed_files = cf.read(file1) | 
|---|
| 721 | n/a |         self.assertEqual(parsed_files, [file1]) | 
|---|
| 722 | n/a |         self.assertEqual(cf.get("Foo Bar", "foo"), "newbar") | 
|---|
| 723 | n/a |         # check when we pass only missing files: | 
|---|
| 724 | n/a |         cf = self.newconfig() | 
|---|
| 725 | n/a |         parsed_files = cf.read(["nonexistent-file"]) | 
|---|
| 726 | n/a |         self.assertEqual(parsed_files, []) | 
|---|
| 727 | n/a |         # check when we pass no files: | 
|---|
| 728 | n/a |         cf = self.newconfig() | 
|---|
| 729 | n/a |         parsed_files = cf.read([]) | 
|---|
| 730 | n/a |         self.assertEqual(parsed_files, []) | 
|---|
| 731 | n/a |  | 
|---|
| 732 | n/a |     # shared by subclasses | 
|---|
| 733 | n/a |     def get_interpolation_config(self): | 
|---|
| 734 | n/a |         return self.fromstring( | 
|---|
| 735 | n/a |             "[Foo]\n" | 
|---|
| 736 | n/a |             "bar{equals}something %(with1)s interpolation (1 step)\n" | 
|---|
| 737 | n/a |             "bar9{equals}something %(with9)s lots of interpolation (9 steps)\n" | 
|---|
| 738 | n/a |             "bar10{equals}something %(with10)s lots of interpolation (10 steps)\n" | 
|---|
| 739 | n/a |             "bar11{equals}something %(with11)s lots of interpolation (11 steps)\n" | 
|---|
| 740 | n/a |             "with11{equals}%(with10)s\n" | 
|---|
| 741 | n/a |             "with10{equals}%(with9)s\n" | 
|---|
| 742 | n/a |             "with9{equals}%(with8)s\n" | 
|---|
| 743 | n/a |             "with8{equals}%(With7)s\n" | 
|---|
| 744 | n/a |             "with7{equals}%(WITH6)s\n" | 
|---|
| 745 | n/a |             "with6{equals}%(with5)s\n" | 
|---|
| 746 | n/a |             "With5{equals}%(with4)s\n" | 
|---|
| 747 | n/a |             "WITH4{equals}%(with3)s\n" | 
|---|
| 748 | n/a |             "with3{equals}%(with2)s\n" | 
|---|
| 749 | n/a |             "with2{equals}%(with1)s\n" | 
|---|
| 750 | n/a |             "with1{equals}with\n" | 
|---|
| 751 | n/a |             "\n" | 
|---|
| 752 | n/a |             "[Mutual Recursion]\n" | 
|---|
| 753 | n/a |             "foo{equals}%(bar)s\n" | 
|---|
| 754 | n/a |             "bar{equals}%(foo)s\n" | 
|---|
| 755 | n/a |             "\n" | 
|---|
| 756 | n/a |             "[Interpolation Error]\n" | 
|---|
| 757 | n/a |             # no definition for 'reference' | 
|---|
| 758 | n/a |             "name{equals}%(reference)s\n".format(equals=self.delimiters[0])) | 
|---|
| 759 | n/a |  | 
|---|
| 760 | n/a |     def check_items_config(self, expected): | 
|---|
| 761 | n/a |         cf = self.fromstring(""" | 
|---|
| 762 | n/a |             [section] | 
|---|
| 763 | n/a |             name {0[0]} %(value)s | 
|---|
| 764 | n/a |             key{0[1]} |%(name)s| | 
|---|
| 765 | n/a |             getdefault{0[1]} |%(default)s| | 
|---|
| 766 | n/a |         """.format(self.delimiters), defaults={"default": "<default>"}) | 
|---|
| 767 | n/a |         L = list(cf.items("section", vars={'value': 'value'})) | 
|---|
| 768 | n/a |         L.sort() | 
|---|
| 769 | n/a |         self.assertEqual(L, expected) | 
|---|
| 770 | n/a |         with self.assertRaises(configparser.NoSectionError): | 
|---|
| 771 | n/a |             cf.items("no such section") | 
|---|
| 772 | n/a |  | 
|---|
| 773 | n/a |     def test_popitem(self): | 
|---|
| 774 | n/a |         cf = self.fromstring(""" | 
|---|
| 775 | n/a |             [section1] | 
|---|
| 776 | n/a |             name1 {0[0]} value1 | 
|---|
| 777 | n/a |             [section2] | 
|---|
| 778 | n/a |             name2 {0[0]} value2 | 
|---|
| 779 | n/a |             [section3] | 
|---|
| 780 | n/a |             name3 {0[0]} value3 | 
|---|
| 781 | n/a |         """.format(self.delimiters), defaults={"default": "<default>"}) | 
|---|
| 782 | n/a |         self.assertEqual(cf.popitem()[0], 'section1') | 
|---|
| 783 | n/a |         self.assertEqual(cf.popitem()[0], 'section2') | 
|---|
| 784 | n/a |         self.assertEqual(cf.popitem()[0], 'section3') | 
|---|
| 785 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 786 | n/a |             cf.popitem() | 
|---|
| 787 | n/a |  | 
|---|
| 788 | n/a |     def test_clear(self): | 
|---|
| 789 | n/a |         cf = self.newconfig({"foo": "Bar"}) | 
|---|
| 790 | n/a |         self.assertEqual( | 
|---|
| 791 | n/a |             cf.get(self.default_section, "Foo"), "Bar", | 
|---|
| 792 | n/a |             "could not locate option, expecting case-insensitive option names") | 
|---|
| 793 | n/a |         cf['zing'] = {'option1': 'value1', 'option2': 'value2'} | 
|---|
| 794 | n/a |         self.assertEqual(cf.sections(), ['zing']) | 
|---|
| 795 | n/a |         self.assertEqual(set(cf['zing'].keys()), {'option1', 'option2', 'foo'}) | 
|---|
| 796 | n/a |         cf.clear() | 
|---|
| 797 | n/a |         self.assertEqual(set(cf.sections()), set()) | 
|---|
| 798 | n/a |         self.assertEqual(set(cf[self.default_section].keys()), {'foo'}) | 
|---|
| 799 | n/a |  | 
|---|
| 800 | n/a |     def test_setitem(self): | 
|---|
| 801 | n/a |         cf = self.fromstring(""" | 
|---|
| 802 | n/a |             [section1] | 
|---|
| 803 | n/a |             name1 {0[0]} value1 | 
|---|
| 804 | n/a |             [section2] | 
|---|
| 805 | n/a |             name2 {0[0]} value2 | 
|---|
| 806 | n/a |             [section3] | 
|---|
| 807 | n/a |             name3 {0[0]} value3 | 
|---|
| 808 | n/a |         """.format(self.delimiters), defaults={"nameD": "valueD"}) | 
|---|
| 809 | n/a |         self.assertEqual(set(cf['section1'].keys()), {'name1', 'named'}) | 
|---|
| 810 | n/a |         self.assertEqual(set(cf['section2'].keys()), {'name2', 'named'}) | 
|---|
| 811 | n/a |         self.assertEqual(set(cf['section3'].keys()), {'name3', 'named'}) | 
|---|
| 812 | n/a |         self.assertEqual(cf['section1']['name1'], 'value1') | 
|---|
| 813 | n/a |         self.assertEqual(cf['section2']['name2'], 'value2') | 
|---|
| 814 | n/a |         self.assertEqual(cf['section3']['name3'], 'value3') | 
|---|
| 815 | n/a |         self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) | 
|---|
| 816 | n/a |         cf['section2'] = {'name22': 'value22'} | 
|---|
| 817 | n/a |         self.assertEqual(set(cf['section2'].keys()), {'name22', 'named'}) | 
|---|
| 818 | n/a |         self.assertEqual(cf['section2']['name22'], 'value22') | 
|---|
| 819 | n/a |         self.assertNotIn('name2', cf['section2']) | 
|---|
| 820 | n/a |         self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) | 
|---|
| 821 | n/a |         cf['section3'] = {} | 
|---|
| 822 | n/a |         self.assertEqual(set(cf['section3'].keys()), {'named'}) | 
|---|
| 823 | n/a |         self.assertNotIn('name3', cf['section3']) | 
|---|
| 824 | n/a |         self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) | 
|---|
| 825 | n/a |         cf[self.default_section] = {} | 
|---|
| 826 | n/a |         self.assertEqual(set(cf[self.default_section].keys()), set()) | 
|---|
| 827 | n/a |         self.assertEqual(set(cf['section1'].keys()), {'name1'}) | 
|---|
| 828 | n/a |         self.assertEqual(set(cf['section2'].keys()), {'name22'}) | 
|---|
| 829 | n/a |         self.assertEqual(set(cf['section3'].keys()), set()) | 
|---|
| 830 | n/a |         self.assertEqual(cf.sections(), ['section1', 'section2', 'section3']) | 
|---|
| 831 | n/a |  | 
|---|
| 832 | n/a |     def test_invalid_multiline_value(self): | 
|---|
| 833 | n/a |         if self.allow_no_value: | 
|---|
| 834 | n/a |             self.skipTest('if no_value is allowed, ParsingError is not raised') | 
|---|
| 835 | n/a |  | 
|---|
| 836 | n/a |         invalid = textwrap.dedent("""\ | 
|---|
| 837 | n/a |             [DEFAULT] | 
|---|
| 838 | n/a |             test {0} test | 
|---|
| 839 | n/a |             invalid""".format(self.delimiters[0]) | 
|---|
| 840 | n/a |         ) | 
|---|
| 841 | n/a |         cf = self.newconfig() | 
|---|
| 842 | n/a |         with self.assertRaises(configparser.ParsingError): | 
|---|
| 843 | n/a |             cf.read_string(invalid) | 
|---|
| 844 | n/a |         self.assertEqual(cf.get('DEFAULT', 'test'), 'test') | 
|---|
| 845 | n/a |         self.assertEqual(cf['DEFAULT']['test'], 'test') | 
|---|
| 846 | n/a |  | 
|---|
| 847 | n/a |  | 
|---|
| 848 | n/a | class StrictTestCase(BasicTestCase, unittest.TestCase): | 
|---|
| 849 | n/a |     config_class = configparser.RawConfigParser | 
|---|
| 850 | n/a |     strict = True | 
|---|
| 851 | n/a |  | 
|---|
| 852 | n/a |  | 
|---|
| 853 | n/a | class ConfigParserTestCase(BasicTestCase, unittest.TestCase): | 
|---|
| 854 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 855 | n/a |  | 
|---|
| 856 | n/a |     def test_interpolation(self): | 
|---|
| 857 | n/a |         cf = self.get_interpolation_config() | 
|---|
| 858 | n/a |         eq = self.assertEqual | 
|---|
| 859 | n/a |         eq(cf.get("Foo", "bar"), "something with interpolation (1 step)") | 
|---|
| 860 | n/a |         eq(cf.get("Foo", "bar9"), | 
|---|
| 861 | n/a |            "something with lots of interpolation (9 steps)") | 
|---|
| 862 | n/a |         eq(cf.get("Foo", "bar10"), | 
|---|
| 863 | n/a |            "something with lots of interpolation (10 steps)") | 
|---|
| 864 | n/a |         e = self.get_error(cf, configparser.InterpolationDepthError, "Foo", "bar11") | 
|---|
| 865 | n/a |         if self.interpolation == configparser._UNSET: | 
|---|
| 866 | n/a |             self.assertEqual(e.args, ("bar11", "Foo", | 
|---|
| 867 | n/a |                 "something %(with11)s lots of interpolation (11 steps)")) | 
|---|
| 868 | n/a |         elif isinstance(self.interpolation, configparser.LegacyInterpolation): | 
|---|
| 869 | n/a |             self.assertEqual(e.args, ("bar11", "Foo", | 
|---|
| 870 | n/a |                 "something %(with11)s lots of interpolation (11 steps)")) | 
|---|
| 871 | n/a |  | 
|---|
| 872 | n/a |     def test_interpolation_missing_value(self): | 
|---|
| 873 | n/a |         cf = self.get_interpolation_config() | 
|---|
| 874 | n/a |         e = self.get_error(cf, configparser.InterpolationMissingOptionError, | 
|---|
| 875 | n/a |                            "Interpolation Error", "name") | 
|---|
| 876 | n/a |         self.assertEqual(e.reference, "reference") | 
|---|
| 877 | n/a |         self.assertEqual(e.section, "Interpolation Error") | 
|---|
| 878 | n/a |         self.assertEqual(e.option, "name") | 
|---|
| 879 | n/a |         if self.interpolation == configparser._UNSET: | 
|---|
| 880 | n/a |             self.assertEqual(e.args, ('name', 'Interpolation Error', | 
|---|
| 881 | n/a |                                     '%(reference)s', 'reference')) | 
|---|
| 882 | n/a |         elif isinstance(self.interpolation, configparser.LegacyInterpolation): | 
|---|
| 883 | n/a |             self.assertEqual(e.args, ('name', 'Interpolation Error', | 
|---|
| 884 | n/a |                                     '%(reference)s', 'reference')) | 
|---|
| 885 | n/a |  | 
|---|
| 886 | n/a |     def test_items(self): | 
|---|
| 887 | n/a |         self.check_items_config([('default', '<default>'), | 
|---|
| 888 | n/a |                                  ('getdefault', '|<default>|'), | 
|---|
| 889 | n/a |                                  ('key', '|value|'), | 
|---|
| 890 | n/a |                                  ('name', 'value'), | 
|---|
| 891 | n/a |                                  ('value', 'value')]) | 
|---|
| 892 | n/a |  | 
|---|
| 893 | n/a |     def test_safe_interpolation(self): | 
|---|
| 894 | n/a |         # See http://www.python.org/sf/511737 | 
|---|
| 895 | n/a |         cf = self.fromstring("[section]\n" | 
|---|
| 896 | n/a |                              "option1{eq}xxx\n" | 
|---|
| 897 | n/a |                              "option2{eq}%(option1)s/xxx\n" | 
|---|
| 898 | n/a |                              "ok{eq}%(option1)s/%%s\n" | 
|---|
| 899 | n/a |                              "not_ok{eq}%(option2)s/%%s".format( | 
|---|
| 900 | n/a |                                  eq=self.delimiters[0])) | 
|---|
| 901 | n/a |         self.assertEqual(cf.get("section", "ok"), "xxx/%s") | 
|---|
| 902 | n/a |         if self.interpolation == configparser._UNSET: | 
|---|
| 903 | n/a |             self.assertEqual(cf.get("section", "not_ok"), "xxx/xxx/%s") | 
|---|
| 904 | n/a |         elif isinstance(self.interpolation, configparser.LegacyInterpolation): | 
|---|
| 905 | n/a |             with self.assertRaises(TypeError): | 
|---|
| 906 | n/a |                 cf.get("section", "not_ok") | 
|---|
| 907 | n/a |  | 
|---|
| 908 | n/a |     def test_set_malformatted_interpolation(self): | 
|---|
| 909 | n/a |         cf = self.fromstring("[sect]\n" | 
|---|
| 910 | n/a |                              "option1{eq}foo\n".format(eq=self.delimiters[0])) | 
|---|
| 911 | n/a |  | 
|---|
| 912 | n/a |         self.assertEqual(cf.get('sect', "option1"), "foo") | 
|---|
| 913 | n/a |  | 
|---|
| 914 | n/a |         self.assertRaises(ValueError, cf.set, "sect", "option1", "%foo") | 
|---|
| 915 | n/a |         self.assertRaises(ValueError, cf.set, "sect", "option1", "foo%") | 
|---|
| 916 | n/a |         self.assertRaises(ValueError, cf.set, "sect", "option1", "f%oo") | 
|---|
| 917 | n/a |  | 
|---|
| 918 | n/a |         self.assertEqual(cf.get('sect', "option1"), "foo") | 
|---|
| 919 | n/a |  | 
|---|
| 920 | n/a |         # bug #5741: double percents are *not* malformed | 
|---|
| 921 | n/a |         cf.set("sect", "option2", "foo%%bar") | 
|---|
| 922 | n/a |         self.assertEqual(cf.get("sect", "option2"), "foo%bar") | 
|---|
| 923 | n/a |  | 
|---|
| 924 | n/a |     def test_set_nonstring_types(self): | 
|---|
| 925 | n/a |         cf = self.fromstring("[sect]\n" | 
|---|
| 926 | n/a |                              "option1{eq}foo\n".format(eq=self.delimiters[0])) | 
|---|
| 927 | n/a |         # Check that we get a TypeError when setting non-string values | 
|---|
| 928 | n/a |         # in an existing section: | 
|---|
| 929 | n/a |         self.assertRaises(TypeError, cf.set, "sect", "option1", 1) | 
|---|
| 930 | n/a |         self.assertRaises(TypeError, cf.set, "sect", "option1", 1.0) | 
|---|
| 931 | n/a |         self.assertRaises(TypeError, cf.set, "sect", "option1", object()) | 
|---|
| 932 | n/a |         self.assertRaises(TypeError, cf.set, "sect", "option2", 1) | 
|---|
| 933 | n/a |         self.assertRaises(TypeError, cf.set, "sect", "option2", 1.0) | 
|---|
| 934 | n/a |         self.assertRaises(TypeError, cf.set, "sect", "option2", object()) | 
|---|
| 935 | n/a |         self.assertRaises(TypeError, cf.set, "sect", 123, "invalid opt name!") | 
|---|
| 936 | n/a |         self.assertRaises(TypeError, cf.add_section, 123) | 
|---|
| 937 | n/a |  | 
|---|
| 938 | n/a |     def test_add_section_default(self): | 
|---|
| 939 | n/a |         cf = self.newconfig() | 
|---|
| 940 | n/a |         self.assertRaises(ValueError, cf.add_section, self.default_section) | 
|---|
| 941 | n/a |  | 
|---|
| 942 | n/a |  | 
|---|
| 943 | n/a | class ConfigParserTestCaseNoInterpolation(BasicTestCase, unittest.TestCase): | 
|---|
| 944 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 945 | n/a |     interpolation = None | 
|---|
| 946 | n/a |     ini = textwrap.dedent(""" | 
|---|
| 947 | n/a |         [numbers] | 
|---|
| 948 | n/a |         one = 1 | 
|---|
| 949 | n/a |         two = %(one)s * 2 | 
|---|
| 950 | n/a |         three = ${common:one} * 3 | 
|---|
| 951 | n/a |  | 
|---|
| 952 | n/a |         [hexen] | 
|---|
| 953 | n/a |         sixteen = ${numbers:two} * 8 | 
|---|
| 954 | n/a |     """).strip() | 
|---|
| 955 | n/a |  | 
|---|
| 956 | n/a |     def assertMatchesIni(self, cf): | 
|---|
| 957 | n/a |         self.assertEqual(cf['numbers']['one'], '1') | 
|---|
| 958 | n/a |         self.assertEqual(cf['numbers']['two'], '%(one)s * 2') | 
|---|
| 959 | n/a |         self.assertEqual(cf['numbers']['three'], '${common:one} * 3') | 
|---|
| 960 | n/a |         self.assertEqual(cf['hexen']['sixteen'], '${numbers:two} * 8') | 
|---|
| 961 | n/a |  | 
|---|
| 962 | n/a |     def test_no_interpolation(self): | 
|---|
| 963 | n/a |         cf = self.fromstring(self.ini) | 
|---|
| 964 | n/a |         self.assertMatchesIni(cf) | 
|---|
| 965 | n/a |  | 
|---|
| 966 | n/a |     def test_empty_case(self): | 
|---|
| 967 | n/a |         cf = self.newconfig() | 
|---|
| 968 | n/a |         self.assertIsNone(cf.read_string("")) | 
|---|
| 969 | n/a |  | 
|---|
| 970 | n/a |     def test_none_as_default_interpolation(self): | 
|---|
| 971 | n/a |         class CustomConfigParser(configparser.ConfigParser): | 
|---|
| 972 | n/a |             _DEFAULT_INTERPOLATION = None | 
|---|
| 973 | n/a |  | 
|---|
| 974 | n/a |         cf = CustomConfigParser() | 
|---|
| 975 | n/a |         cf.read_string(self.ini) | 
|---|
| 976 | n/a |         self.assertMatchesIni(cf) | 
|---|
| 977 | n/a |  | 
|---|
| 978 | n/a |  | 
|---|
| 979 | n/a | class ConfigParserTestCaseLegacyInterpolation(ConfigParserTestCase): | 
|---|
| 980 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 981 | n/a |     interpolation = configparser.LegacyInterpolation() | 
|---|
| 982 | n/a |  | 
|---|
| 983 | n/a |     def test_set_malformatted_interpolation(self): | 
|---|
| 984 | n/a |         cf = self.fromstring("[sect]\n" | 
|---|
| 985 | n/a |                              "option1{eq}foo\n".format(eq=self.delimiters[0])) | 
|---|
| 986 | n/a |  | 
|---|
| 987 | n/a |         self.assertEqual(cf.get('sect', "option1"), "foo") | 
|---|
| 988 | n/a |  | 
|---|
| 989 | n/a |         cf.set("sect", "option1", "%foo") | 
|---|
| 990 | n/a |         self.assertEqual(cf.get('sect', "option1"), "%foo") | 
|---|
| 991 | n/a |         cf.set("sect", "option1", "foo%") | 
|---|
| 992 | n/a |         self.assertEqual(cf.get('sect', "option1"), "foo%") | 
|---|
| 993 | n/a |         cf.set("sect", "option1", "f%oo") | 
|---|
| 994 | n/a |         self.assertEqual(cf.get('sect', "option1"), "f%oo") | 
|---|
| 995 | n/a |  | 
|---|
| 996 | n/a |         # bug #5741: double percents are *not* malformed | 
|---|
| 997 | n/a |         cf.set("sect", "option2", "foo%%bar") | 
|---|
| 998 | n/a |         self.assertEqual(cf.get("sect", "option2"), "foo%%bar") | 
|---|
| 999 | n/a |  | 
|---|
| 1000 | n/a |  | 
|---|
| 1001 | n/a | class ConfigParserTestCaseNonStandardDelimiters(ConfigParserTestCase): | 
|---|
| 1002 | n/a |     delimiters = (':=', '$') | 
|---|
| 1003 | n/a |     comment_prefixes = ('//', '"') | 
|---|
| 1004 | n/a |     inline_comment_prefixes = ('//', '"') | 
|---|
| 1005 | n/a |  | 
|---|
| 1006 | n/a |  | 
|---|
| 1007 | n/a | class ConfigParserTestCaseNonStandardDefaultSection(ConfigParserTestCase): | 
|---|
| 1008 | n/a |     default_section = 'general' | 
|---|
| 1009 | n/a |  | 
|---|
| 1010 | n/a |  | 
|---|
| 1011 | n/a | class MultilineValuesTestCase(BasicTestCase, unittest.TestCase): | 
|---|
| 1012 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 1013 | n/a |     wonderful_spam = ("I'm having spam spam spam spam " | 
|---|
| 1014 | n/a |                       "spam spam spam beaked beans spam " | 
|---|
| 1015 | n/a |                       "spam spam and spam!").replace(' ', '\t\n') | 
|---|
| 1016 | n/a |  | 
|---|
| 1017 | n/a |     def setUp(self): | 
|---|
| 1018 | n/a |         cf = self.newconfig() | 
|---|
| 1019 | n/a |         for i in range(100): | 
|---|
| 1020 | n/a |             s = 'section{}'.format(i) | 
|---|
| 1021 | n/a |             cf.add_section(s) | 
|---|
| 1022 | n/a |             for j in range(10): | 
|---|
| 1023 | n/a |                 cf.set(s, 'lovely_spam{}'.format(j), self.wonderful_spam) | 
|---|
| 1024 | n/a |         with open(support.TESTFN, 'w') as f: | 
|---|
| 1025 | n/a |             cf.write(f) | 
|---|
| 1026 | n/a |  | 
|---|
| 1027 | n/a |     def tearDown(self): | 
|---|
| 1028 | n/a |         os.unlink(support.TESTFN) | 
|---|
| 1029 | n/a |  | 
|---|
| 1030 | n/a |     def test_dominating_multiline_values(self): | 
|---|
| 1031 | n/a |         # We're reading from file because this is where the code changed | 
|---|
| 1032 | n/a |         # during performance updates in Python 3.2 | 
|---|
| 1033 | n/a |         cf_from_file = self.newconfig() | 
|---|
| 1034 | n/a |         with open(support.TESTFN) as f: | 
|---|
| 1035 | n/a |             cf_from_file.read_file(f) | 
|---|
| 1036 | n/a |         self.assertEqual(cf_from_file.get('section8', 'lovely_spam4'), | 
|---|
| 1037 | n/a |                          self.wonderful_spam.replace('\t\n', '\n')) | 
|---|
| 1038 | n/a |  | 
|---|
| 1039 | n/a |  | 
|---|
| 1040 | n/a | class RawConfigParserTestCase(BasicTestCase, unittest.TestCase): | 
|---|
| 1041 | n/a |     config_class = configparser.RawConfigParser | 
|---|
| 1042 | n/a |  | 
|---|
| 1043 | n/a |     def test_interpolation(self): | 
|---|
| 1044 | n/a |         cf = self.get_interpolation_config() | 
|---|
| 1045 | n/a |         eq = self.assertEqual | 
|---|
| 1046 | n/a |         eq(cf.get("Foo", "bar"), | 
|---|
| 1047 | n/a |            "something %(with1)s interpolation (1 step)") | 
|---|
| 1048 | n/a |         eq(cf.get("Foo", "bar9"), | 
|---|
| 1049 | n/a |            "something %(with9)s lots of interpolation (9 steps)") | 
|---|
| 1050 | n/a |         eq(cf.get("Foo", "bar10"), | 
|---|
| 1051 | n/a |            "something %(with10)s lots of interpolation (10 steps)") | 
|---|
| 1052 | n/a |         eq(cf.get("Foo", "bar11"), | 
|---|
| 1053 | n/a |            "something %(with11)s lots of interpolation (11 steps)") | 
|---|
| 1054 | n/a |  | 
|---|
| 1055 | n/a |     def test_items(self): | 
|---|
| 1056 | n/a |         self.check_items_config([('default', '<default>'), | 
|---|
| 1057 | n/a |                                  ('getdefault', '|%(default)s|'), | 
|---|
| 1058 | n/a |                                  ('key', '|%(name)s|'), | 
|---|
| 1059 | n/a |                                  ('name', '%(value)s'), | 
|---|
| 1060 | n/a |                                  ('value', 'value')]) | 
|---|
| 1061 | n/a |  | 
|---|
| 1062 | n/a |     def test_set_nonstring_types(self): | 
|---|
| 1063 | n/a |         cf = self.newconfig() | 
|---|
| 1064 | n/a |         cf.add_section('non-string') | 
|---|
| 1065 | n/a |         cf.set('non-string', 'int', 1) | 
|---|
| 1066 | n/a |         cf.set('non-string', 'list', [0, 1, 1, 2, 3, 5, 8, 13]) | 
|---|
| 1067 | n/a |         cf.set('non-string', 'dict', {'pi': 3.14159}) | 
|---|
| 1068 | n/a |         self.assertEqual(cf.get('non-string', 'int'), 1) | 
|---|
| 1069 | n/a |         self.assertEqual(cf.get('non-string', 'list'), | 
|---|
| 1070 | n/a |                          [0, 1, 1, 2, 3, 5, 8, 13]) | 
|---|
| 1071 | n/a |         self.assertEqual(cf.get('non-string', 'dict'), {'pi': 3.14159}) | 
|---|
| 1072 | n/a |         cf.add_section(123) | 
|---|
| 1073 | n/a |         cf.set(123, 'this is sick', True) | 
|---|
| 1074 | n/a |         self.assertEqual(cf.get(123, 'this is sick'), True) | 
|---|
| 1075 | n/a |         if cf._dict is configparser._default_dict: | 
|---|
| 1076 | n/a |             # would not work for SortedDict; only checking for the most common | 
|---|
| 1077 | n/a |             # default dictionary (OrderedDict) | 
|---|
| 1078 | n/a |             cf.optionxform = lambda x: x | 
|---|
| 1079 | n/a |             cf.set('non-string', 1, 1) | 
|---|
| 1080 | n/a |             self.assertEqual(cf.get('non-string', 1), 1) | 
|---|
| 1081 | n/a |  | 
|---|
| 1082 | n/a |  | 
|---|
| 1083 | n/a | class RawConfigParserTestCaseNonStandardDelimiters(RawConfigParserTestCase): | 
|---|
| 1084 | n/a |     delimiters = (':=', '$') | 
|---|
| 1085 | n/a |     comment_prefixes = ('//', '"') | 
|---|
| 1086 | n/a |     inline_comment_prefixes = ('//', '"') | 
|---|
| 1087 | n/a |  | 
|---|
| 1088 | n/a |  | 
|---|
| 1089 | n/a | class RawConfigParserTestSambaConf(CfgParserTestCaseClass, unittest.TestCase): | 
|---|
| 1090 | n/a |     config_class = configparser.RawConfigParser | 
|---|
| 1091 | n/a |     comment_prefixes = ('#', ';', '----') | 
|---|
| 1092 | n/a |     inline_comment_prefixes = ('//',) | 
|---|
| 1093 | n/a |     empty_lines_in_values = False | 
|---|
| 1094 | n/a |  | 
|---|
| 1095 | n/a |     def test_reading(self): | 
|---|
| 1096 | n/a |         smbconf = support.findfile("cfgparser.2") | 
|---|
| 1097 | n/a |         # check when we pass a mix of readable and non-readable files: | 
|---|
| 1098 | n/a |         cf = self.newconfig() | 
|---|
| 1099 | n/a |         parsed_files = cf.read([smbconf, "nonexistent-file"], encoding='utf-8') | 
|---|
| 1100 | n/a |         self.assertEqual(parsed_files, [smbconf]) | 
|---|
| 1101 | n/a |         sections = ['global', 'homes', 'printers', | 
|---|
| 1102 | n/a |                     'print$', 'pdf-generator', 'tmp', 'Agustin'] | 
|---|
| 1103 | n/a |         self.assertEqual(cf.sections(), sections) | 
|---|
| 1104 | n/a |         self.assertEqual(cf.get("global", "workgroup"), "MDKGROUP") | 
|---|
| 1105 | n/a |         self.assertEqual(cf.getint("global", "max log size"), 50) | 
|---|
| 1106 | n/a |         self.assertEqual(cf.get("global", "hosts allow"), "127.") | 
|---|
| 1107 | n/a |         self.assertEqual(cf.get("tmp", "echo command"), "cat %s; rm %s") | 
|---|
| 1108 | n/a |  | 
|---|
| 1109 | n/a | class ConfigParserTestCaseExtendedInterpolation(BasicTestCase, unittest.TestCase): | 
|---|
| 1110 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 1111 | n/a |     interpolation = configparser.ExtendedInterpolation() | 
|---|
| 1112 | n/a |     default_section = 'common' | 
|---|
| 1113 | n/a |     strict = True | 
|---|
| 1114 | n/a |  | 
|---|
| 1115 | n/a |     def fromstring(self, string, defaults=None, optionxform=None): | 
|---|
| 1116 | n/a |         cf = self.newconfig(defaults) | 
|---|
| 1117 | n/a |         if optionxform: | 
|---|
| 1118 | n/a |             cf.optionxform = optionxform | 
|---|
| 1119 | n/a |         cf.read_string(string) | 
|---|
| 1120 | n/a |         return cf | 
|---|
| 1121 | n/a |  | 
|---|
| 1122 | n/a |     def test_extended_interpolation(self): | 
|---|
| 1123 | n/a |         cf = self.fromstring(textwrap.dedent(""" | 
|---|
| 1124 | n/a |             [common] | 
|---|
| 1125 | n/a |             favourite Beatle = Paul | 
|---|
| 1126 | n/a |             favourite color = green | 
|---|
| 1127 | n/a |  | 
|---|
| 1128 | n/a |             [tom] | 
|---|
| 1129 | n/a |             favourite band = ${favourite color} day | 
|---|
| 1130 | n/a |             favourite pope = John ${favourite Beatle} II | 
|---|
| 1131 | n/a |             sequel = ${favourite pope}I | 
|---|
| 1132 | n/a |  | 
|---|
| 1133 | n/a |             [ambv] | 
|---|
| 1134 | n/a |             favourite Beatle = George | 
|---|
| 1135 | n/a |             son of Edward VII = ${favourite Beatle} V | 
|---|
| 1136 | n/a |             son of George V = ${son of Edward VII}I | 
|---|
| 1137 | n/a |  | 
|---|
| 1138 | n/a |             [stanley] | 
|---|
| 1139 | n/a |             favourite Beatle = ${ambv:favourite Beatle} | 
|---|
| 1140 | n/a |             favourite pope = ${tom:favourite pope} | 
|---|
| 1141 | n/a |             favourite color = black | 
|---|
| 1142 | n/a |             favourite state of mind = paranoid | 
|---|
| 1143 | n/a |             favourite movie = soylent ${common:favourite color} | 
|---|
| 1144 | n/a |             favourite song = ${favourite color} sabbath - ${favourite state of mind} | 
|---|
| 1145 | n/a |         """).strip()) | 
|---|
| 1146 | n/a |  | 
|---|
| 1147 | n/a |         eq = self.assertEqual | 
|---|
| 1148 | n/a |         eq(cf['common']['favourite Beatle'], 'Paul') | 
|---|
| 1149 | n/a |         eq(cf['common']['favourite color'], 'green') | 
|---|
| 1150 | n/a |         eq(cf['tom']['favourite Beatle'], 'Paul') | 
|---|
| 1151 | n/a |         eq(cf['tom']['favourite color'], 'green') | 
|---|
| 1152 | n/a |         eq(cf['tom']['favourite band'], 'green day') | 
|---|
| 1153 | n/a |         eq(cf['tom']['favourite pope'], 'John Paul II') | 
|---|
| 1154 | n/a |         eq(cf['tom']['sequel'], 'John Paul III') | 
|---|
| 1155 | n/a |         eq(cf['ambv']['favourite Beatle'], 'George') | 
|---|
| 1156 | n/a |         eq(cf['ambv']['favourite color'], 'green') | 
|---|
| 1157 | n/a |         eq(cf['ambv']['son of Edward VII'], 'George V') | 
|---|
| 1158 | n/a |         eq(cf['ambv']['son of George V'], 'George VI') | 
|---|
| 1159 | n/a |         eq(cf['stanley']['favourite Beatle'], 'George') | 
|---|
| 1160 | n/a |         eq(cf['stanley']['favourite color'], 'black') | 
|---|
| 1161 | n/a |         eq(cf['stanley']['favourite state of mind'], 'paranoid') | 
|---|
| 1162 | n/a |         eq(cf['stanley']['favourite movie'], 'soylent green') | 
|---|
| 1163 | n/a |         eq(cf['stanley']['favourite pope'], 'John Paul II') | 
|---|
| 1164 | n/a |         eq(cf['stanley']['favourite song'], | 
|---|
| 1165 | n/a |            'black sabbath - paranoid') | 
|---|
| 1166 | n/a |  | 
|---|
| 1167 | n/a |     def test_endless_loop(self): | 
|---|
| 1168 | n/a |         cf = self.fromstring(textwrap.dedent(""" | 
|---|
| 1169 | n/a |             [one for you] | 
|---|
| 1170 | n/a |             ping = ${one for me:pong} | 
|---|
| 1171 | n/a |  | 
|---|
| 1172 | n/a |             [one for me] | 
|---|
| 1173 | n/a |             pong = ${one for you:ping} | 
|---|
| 1174 | n/a |  | 
|---|
| 1175 | n/a |             [selfish] | 
|---|
| 1176 | n/a |             me = ${me} | 
|---|
| 1177 | n/a |         """).strip()) | 
|---|
| 1178 | n/a |  | 
|---|
| 1179 | n/a |         with self.assertRaises(configparser.InterpolationDepthError): | 
|---|
| 1180 | n/a |             cf['one for you']['ping'] | 
|---|
| 1181 | n/a |         with self.assertRaises(configparser.InterpolationDepthError): | 
|---|
| 1182 | n/a |             cf['selfish']['me'] | 
|---|
| 1183 | n/a |  | 
|---|
| 1184 | n/a |     def test_strange_options(self): | 
|---|
| 1185 | n/a |         cf = self.fromstring(""" | 
|---|
| 1186 | n/a |             [dollars] | 
|---|
| 1187 | n/a |             $var = $$value | 
|---|
| 1188 | n/a |             $var2 = ${$var} | 
|---|
| 1189 | n/a |             ${sick} = cannot interpolate me | 
|---|
| 1190 | n/a |  | 
|---|
| 1191 | n/a |             [interpolated] | 
|---|
| 1192 | n/a |             $other = ${dollars:$var} | 
|---|
| 1193 | n/a |             $trying = ${dollars:${sick}} | 
|---|
| 1194 | n/a |         """) | 
|---|
| 1195 | n/a |  | 
|---|
| 1196 | n/a |         self.assertEqual(cf['dollars']['$var'], '$value') | 
|---|
| 1197 | n/a |         self.assertEqual(cf['interpolated']['$other'], '$value') | 
|---|
| 1198 | n/a |         self.assertEqual(cf['dollars']['${sick}'], 'cannot interpolate me') | 
|---|
| 1199 | n/a |         exception_class = configparser.InterpolationMissingOptionError | 
|---|
| 1200 | n/a |         with self.assertRaises(exception_class) as cm: | 
|---|
| 1201 | n/a |             cf['interpolated']['$trying'] | 
|---|
| 1202 | n/a |         self.assertEqual(cm.exception.reference, 'dollars:${sick') | 
|---|
| 1203 | n/a |         self.assertEqual(cm.exception.args[2], '${dollars:${sick}}') #rawval | 
|---|
| 1204 | n/a |  | 
|---|
| 1205 | n/a |     def test_case_sensitivity_basic(self): | 
|---|
| 1206 | n/a |         ini = textwrap.dedent(""" | 
|---|
| 1207 | n/a |             [common] | 
|---|
| 1208 | n/a |             optionlower = value | 
|---|
| 1209 | n/a |             OptionUpper = Value | 
|---|
| 1210 | n/a |  | 
|---|
| 1211 | n/a |             [Common] | 
|---|
| 1212 | n/a |             optionlower = a better ${common:optionlower} | 
|---|
| 1213 | n/a |             OptionUpper = A Better ${common:OptionUpper} | 
|---|
| 1214 | n/a |  | 
|---|
| 1215 | n/a |             [random] | 
|---|
| 1216 | n/a |             foolower = ${common:optionlower} redefined | 
|---|
| 1217 | n/a |             FooUpper = ${Common:OptionUpper} Redefined | 
|---|
| 1218 | n/a |         """).strip() | 
|---|
| 1219 | n/a |  | 
|---|
| 1220 | n/a |         cf = self.fromstring(ini) | 
|---|
| 1221 | n/a |         eq = self.assertEqual | 
|---|
| 1222 | n/a |         eq(cf['common']['optionlower'], 'value') | 
|---|
| 1223 | n/a |         eq(cf['common']['OptionUpper'], 'Value') | 
|---|
| 1224 | n/a |         eq(cf['Common']['optionlower'], 'a better value') | 
|---|
| 1225 | n/a |         eq(cf['Common']['OptionUpper'], 'A Better Value') | 
|---|
| 1226 | n/a |         eq(cf['random']['foolower'], 'value redefined') | 
|---|
| 1227 | n/a |         eq(cf['random']['FooUpper'], 'A Better Value Redefined') | 
|---|
| 1228 | n/a |  | 
|---|
| 1229 | n/a |     def test_case_sensitivity_conflicts(self): | 
|---|
| 1230 | n/a |         ini = textwrap.dedent(""" | 
|---|
| 1231 | n/a |             [common] | 
|---|
| 1232 | n/a |             option = value | 
|---|
| 1233 | n/a |             Option = Value | 
|---|
| 1234 | n/a |  | 
|---|
| 1235 | n/a |             [Common] | 
|---|
| 1236 | n/a |             option = a better ${common:option} | 
|---|
| 1237 | n/a |             Option = A Better ${common:Option} | 
|---|
| 1238 | n/a |  | 
|---|
| 1239 | n/a |             [random] | 
|---|
| 1240 | n/a |             foo = ${common:option} redefined | 
|---|
| 1241 | n/a |             Foo = ${Common:Option} Redefined | 
|---|
| 1242 | n/a |         """).strip() | 
|---|
| 1243 | n/a |         with self.assertRaises(configparser.DuplicateOptionError): | 
|---|
| 1244 | n/a |             cf = self.fromstring(ini) | 
|---|
| 1245 | n/a |  | 
|---|
| 1246 | n/a |         # raw options | 
|---|
| 1247 | n/a |         cf = self.fromstring(ini, optionxform=lambda opt: opt) | 
|---|
| 1248 | n/a |         eq = self.assertEqual | 
|---|
| 1249 | n/a |         eq(cf['common']['option'], 'value') | 
|---|
| 1250 | n/a |         eq(cf['common']['Option'], 'Value') | 
|---|
| 1251 | n/a |         eq(cf['Common']['option'], 'a better value') | 
|---|
| 1252 | n/a |         eq(cf['Common']['Option'], 'A Better Value') | 
|---|
| 1253 | n/a |         eq(cf['random']['foo'], 'value redefined') | 
|---|
| 1254 | n/a |         eq(cf['random']['Foo'], 'A Better Value Redefined') | 
|---|
| 1255 | n/a |  | 
|---|
| 1256 | n/a |     def test_other_errors(self): | 
|---|
| 1257 | n/a |         cf = self.fromstring(""" | 
|---|
| 1258 | n/a |             [interpolation fail] | 
|---|
| 1259 | n/a |             case1 = ${where's the brace | 
|---|
| 1260 | n/a |             case2 = ${does_not_exist} | 
|---|
| 1261 | n/a |             case3 = ${wrong_section:wrong_value} | 
|---|
| 1262 | n/a |             case4 = ${i:like:colon:characters} | 
|---|
| 1263 | n/a |             case5 = $100 for Fail No 5! | 
|---|
| 1264 | n/a |         """) | 
|---|
| 1265 | n/a |  | 
|---|
| 1266 | n/a |         with self.assertRaises(configparser.InterpolationSyntaxError): | 
|---|
| 1267 | n/a |             cf['interpolation fail']['case1'] | 
|---|
| 1268 | n/a |         with self.assertRaises(configparser.InterpolationMissingOptionError): | 
|---|
| 1269 | n/a |             cf['interpolation fail']['case2'] | 
|---|
| 1270 | n/a |         with self.assertRaises(configparser.InterpolationMissingOptionError): | 
|---|
| 1271 | n/a |             cf['interpolation fail']['case3'] | 
|---|
| 1272 | n/a |         with self.assertRaises(configparser.InterpolationSyntaxError): | 
|---|
| 1273 | n/a |             cf['interpolation fail']['case4'] | 
|---|
| 1274 | n/a |         with self.assertRaises(configparser.InterpolationSyntaxError): | 
|---|
| 1275 | n/a |             cf['interpolation fail']['case5'] | 
|---|
| 1276 | n/a |         with self.assertRaises(ValueError): | 
|---|
| 1277 | n/a |             cf['interpolation fail']['case6'] = "BLACK $ABBATH" | 
|---|
| 1278 | n/a |  | 
|---|
| 1279 | n/a |  | 
|---|
| 1280 | n/a | class ConfigParserTestCaseNoValue(ConfigParserTestCase): | 
|---|
| 1281 | n/a |     allow_no_value = True | 
|---|
| 1282 | n/a |  | 
|---|
| 1283 | n/a |  | 
|---|
| 1284 | n/a | class ConfigParserTestCaseTrickyFile(CfgParserTestCaseClass, unittest.TestCase): | 
|---|
| 1285 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 1286 | n/a |     delimiters = {'='} | 
|---|
| 1287 | n/a |     comment_prefixes = {'#'} | 
|---|
| 1288 | n/a |     allow_no_value = True | 
|---|
| 1289 | n/a |  | 
|---|
| 1290 | n/a |     def test_cfgparser_dot_3(self): | 
|---|
| 1291 | n/a |         tricky = support.findfile("cfgparser.3") | 
|---|
| 1292 | n/a |         cf = self.newconfig() | 
|---|
| 1293 | n/a |         self.assertEqual(len(cf.read(tricky, encoding='utf-8')), 1) | 
|---|
| 1294 | n/a |         self.assertEqual(cf.sections(), ['strange', | 
|---|
| 1295 | n/a |                                          'corruption', | 
|---|
| 1296 | n/a |                                          'yeah, sections can be ' | 
|---|
| 1297 | n/a |                                          'indented as well', | 
|---|
| 1298 | n/a |                                          'another one!', | 
|---|
| 1299 | n/a |                                          'no values here', | 
|---|
| 1300 | n/a |                                          'tricky interpolation', | 
|---|
| 1301 | n/a |                                          'more interpolation']) | 
|---|
| 1302 | n/a |         self.assertEqual(cf.getint(self.default_section, 'go', | 
|---|
| 1303 | n/a |                                    vars={'interpolate': '-1'}), -1) | 
|---|
| 1304 | n/a |         with self.assertRaises(ValueError): | 
|---|
| 1305 | n/a |             # no interpolation will happen | 
|---|
| 1306 | n/a |             cf.getint(self.default_section, 'go', raw=True, | 
|---|
| 1307 | n/a |                       vars={'interpolate': '-1'}) | 
|---|
| 1308 | n/a |         self.assertEqual(len(cf.get('strange', 'other').split('\n')), 4) | 
|---|
| 1309 | n/a |         self.assertEqual(len(cf.get('corruption', 'value').split('\n')), 10) | 
|---|
| 1310 | n/a |         longname = 'yeah, sections can be indented as well' | 
|---|
| 1311 | n/a |         self.assertFalse(cf.getboolean(longname, 'are they subsections')) | 
|---|
| 1312 | n/a |         self.assertEqual(cf.get(longname, 'lets use some Unicode'), 'รงรคยปยฎรฅ') | 
|---|
| 1313 | n/a |         self.assertEqual(len(cf.items('another one!')), 5) # 4 in section and | 
|---|
| 1314 | n/a |                                                            # `go` from DEFAULT | 
|---|
| 1315 | n/a |         with self.assertRaises(configparser.InterpolationMissingOptionError): | 
|---|
| 1316 | n/a |             cf.items('no values here') | 
|---|
| 1317 | n/a |         self.assertEqual(cf.get('tricky interpolation', 'lets'), 'do this') | 
|---|
| 1318 | n/a |         self.assertEqual(cf.get('tricky interpolation', 'lets'), | 
|---|
| 1319 | n/a |                          cf.get('tricky interpolation', 'go')) | 
|---|
| 1320 | n/a |         self.assertEqual(cf.get('more interpolation', 'lets'), 'go shopping') | 
|---|
| 1321 | n/a |  | 
|---|
| 1322 | n/a |     def test_unicode_failure(self): | 
|---|
| 1323 | n/a |         tricky = support.findfile("cfgparser.3") | 
|---|
| 1324 | n/a |         cf = self.newconfig() | 
|---|
| 1325 | n/a |         with self.assertRaises(UnicodeDecodeError): | 
|---|
| 1326 | n/a |             cf.read(tricky, encoding='ascii') | 
|---|
| 1327 | n/a |  | 
|---|
| 1328 | n/a |  | 
|---|
| 1329 | n/a | class Issue7005TestCase(unittest.TestCase): | 
|---|
| 1330 | n/a |     """Test output when None is set() as a value and allow_no_value == False. | 
|---|
| 1331 | n/a |  | 
|---|
| 1332 | n/a |     http://bugs.python.org/issue7005 | 
|---|
| 1333 | n/a |  | 
|---|
| 1334 | n/a |     """ | 
|---|
| 1335 | n/a |  | 
|---|
| 1336 | n/a |     expected_output = "[section]\noption = None\n\n" | 
|---|
| 1337 | n/a |  | 
|---|
| 1338 | n/a |     def prepare(self, config_class): | 
|---|
| 1339 | n/a |         # This is the default, but that's the point. | 
|---|
| 1340 | n/a |         cp = config_class(allow_no_value=False) | 
|---|
| 1341 | n/a |         cp.add_section("section") | 
|---|
| 1342 | n/a |         cp.set("section", "option", None) | 
|---|
| 1343 | n/a |         sio = io.StringIO() | 
|---|
| 1344 | n/a |         cp.write(sio) | 
|---|
| 1345 | n/a |         return sio.getvalue() | 
|---|
| 1346 | n/a |  | 
|---|
| 1347 | n/a |     def test_none_as_value_stringified(self): | 
|---|
| 1348 | n/a |         cp = configparser.ConfigParser(allow_no_value=False) | 
|---|
| 1349 | n/a |         cp.add_section("section") | 
|---|
| 1350 | n/a |         with self.assertRaises(TypeError): | 
|---|
| 1351 | n/a |             cp.set("section", "option", None) | 
|---|
| 1352 | n/a |  | 
|---|
| 1353 | n/a |     def test_none_as_value_stringified_raw(self): | 
|---|
| 1354 | n/a |         output = self.prepare(configparser.RawConfigParser) | 
|---|
| 1355 | n/a |         self.assertEqual(output, self.expected_output) | 
|---|
| 1356 | n/a |  | 
|---|
| 1357 | n/a |  | 
|---|
| 1358 | n/a | class SortedTestCase(RawConfigParserTestCase): | 
|---|
| 1359 | n/a |     dict_type = SortedDict | 
|---|
| 1360 | n/a |  | 
|---|
| 1361 | n/a |     def test_sorted(self): | 
|---|
| 1362 | n/a |         cf = self.fromstring("[b]\n" | 
|---|
| 1363 | n/a |                              "o4=1\n" | 
|---|
| 1364 | n/a |                              "o3=2\n" | 
|---|
| 1365 | n/a |                              "o2=3\n" | 
|---|
| 1366 | n/a |                              "o1=4\n" | 
|---|
| 1367 | n/a |                              "[a]\n" | 
|---|
| 1368 | n/a |                              "k=v\n") | 
|---|
| 1369 | n/a |         output = io.StringIO() | 
|---|
| 1370 | n/a |         cf.write(output) | 
|---|
| 1371 | n/a |         self.assertEqual(output.getvalue(), | 
|---|
| 1372 | n/a |                          "[a]\n" | 
|---|
| 1373 | n/a |                          "k = v\n\n" | 
|---|
| 1374 | n/a |                          "[b]\n" | 
|---|
| 1375 | n/a |                          "o1 = 4\n" | 
|---|
| 1376 | n/a |                          "o2 = 3\n" | 
|---|
| 1377 | n/a |                          "o3 = 2\n" | 
|---|
| 1378 | n/a |                          "o4 = 1\n\n") | 
|---|
| 1379 | n/a |  | 
|---|
| 1380 | n/a |  | 
|---|
| 1381 | n/a | class CompatibleTestCase(CfgParserTestCaseClass, unittest.TestCase): | 
|---|
| 1382 | n/a |     config_class = configparser.RawConfigParser | 
|---|
| 1383 | n/a |     comment_prefixes = '#;' | 
|---|
| 1384 | n/a |     inline_comment_prefixes = ';' | 
|---|
| 1385 | n/a |  | 
|---|
| 1386 | n/a |     def test_comment_handling(self): | 
|---|
| 1387 | n/a |         config_string = textwrap.dedent("""\ | 
|---|
| 1388 | n/a |         [Commented Bar] | 
|---|
| 1389 | n/a |         baz=qwe ; a comment | 
|---|
| 1390 | n/a |         foo: bar # not a comment! | 
|---|
| 1391 | n/a |         # but this is a comment | 
|---|
| 1392 | n/a |         ; another comment | 
|---|
| 1393 | n/a |         quirk: this;is not a comment | 
|---|
| 1394 | n/a |         ; a space must precede an inline comment | 
|---|
| 1395 | n/a |         """) | 
|---|
| 1396 | n/a |         cf = self.fromstring(config_string) | 
|---|
| 1397 | n/a |         self.assertEqual(cf.get('Commented Bar', 'foo'), | 
|---|
| 1398 | n/a |                          'bar # not a comment!') | 
|---|
| 1399 | n/a |         self.assertEqual(cf.get('Commented Bar', 'baz'), 'qwe') | 
|---|
| 1400 | n/a |         self.assertEqual(cf.get('Commented Bar', 'quirk'), | 
|---|
| 1401 | n/a |                          'this;is not a comment') | 
|---|
| 1402 | n/a |  | 
|---|
| 1403 | n/a | class CopyTestCase(BasicTestCase, unittest.TestCase): | 
|---|
| 1404 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 1405 | n/a |  | 
|---|
| 1406 | n/a |     def fromstring(self, string, defaults=None): | 
|---|
| 1407 | n/a |         cf = self.newconfig(defaults) | 
|---|
| 1408 | n/a |         cf.read_string(string) | 
|---|
| 1409 | n/a |         cf_copy = self.newconfig() | 
|---|
| 1410 | n/a |         cf_copy.read_dict(cf) | 
|---|
| 1411 | n/a |         # we have to clean up option duplicates that appeared because of | 
|---|
| 1412 | n/a |         # the magic DEFAULTSECT behaviour. | 
|---|
| 1413 | n/a |         for section in cf_copy.values(): | 
|---|
| 1414 | n/a |             if section.name == self.default_section: | 
|---|
| 1415 | n/a |                 continue | 
|---|
| 1416 | n/a |             for default, value in cf[self.default_section].items(): | 
|---|
| 1417 | n/a |                 if section[default] == value: | 
|---|
| 1418 | n/a |                     del section[default] | 
|---|
| 1419 | n/a |         return cf_copy | 
|---|
| 1420 | n/a |  | 
|---|
| 1421 | n/a |  | 
|---|
| 1422 | n/a | class FakeFile: | 
|---|
| 1423 | n/a |     def __init__(self): | 
|---|
| 1424 | n/a |         file_path = support.findfile("cfgparser.1") | 
|---|
| 1425 | n/a |         with open(file_path) as f: | 
|---|
| 1426 | n/a |             self.lines = f.readlines() | 
|---|
| 1427 | n/a |             self.lines.reverse() | 
|---|
| 1428 | n/a |  | 
|---|
| 1429 | n/a |     def readline(self): | 
|---|
| 1430 | n/a |         if len(self.lines): | 
|---|
| 1431 | n/a |             return self.lines.pop() | 
|---|
| 1432 | n/a |         return '' | 
|---|
| 1433 | n/a |  | 
|---|
| 1434 | n/a |  | 
|---|
| 1435 | n/a | def readline_generator(f): | 
|---|
| 1436 | n/a |     """As advised in Doc/library/configparser.rst.""" | 
|---|
| 1437 | n/a |     line = f.readline() | 
|---|
| 1438 | n/a |     while line: | 
|---|
| 1439 | n/a |         yield line | 
|---|
| 1440 | n/a |         line = f.readline() | 
|---|
| 1441 | n/a |  | 
|---|
| 1442 | n/a |  | 
|---|
| 1443 | n/a | class ReadFileTestCase(unittest.TestCase): | 
|---|
| 1444 | n/a |     def test_file(self): | 
|---|
| 1445 | n/a |         file_paths = [support.findfile("cfgparser.1")] | 
|---|
| 1446 | n/a |         try: | 
|---|
| 1447 | n/a |             file_paths.append(file_paths[0].encode('utf8')) | 
|---|
| 1448 | n/a |         except UnicodeEncodeError: | 
|---|
| 1449 | n/a |             pass   # unfortunately we can't test bytes on this path | 
|---|
| 1450 | n/a |         for file_path in file_paths: | 
|---|
| 1451 | n/a |             parser = configparser.ConfigParser() | 
|---|
| 1452 | n/a |             with open(file_path) as f: | 
|---|
| 1453 | n/a |                 parser.read_file(f) | 
|---|
| 1454 | n/a |             self.assertIn("Foo Bar", parser) | 
|---|
| 1455 | n/a |             self.assertIn("foo", parser["Foo Bar"]) | 
|---|
| 1456 | n/a |             self.assertEqual(parser["Foo Bar"]["foo"], "newbar") | 
|---|
| 1457 | n/a |  | 
|---|
| 1458 | n/a |     def test_iterable(self): | 
|---|
| 1459 | n/a |         lines = textwrap.dedent(""" | 
|---|
| 1460 | n/a |         [Foo Bar] | 
|---|
| 1461 | n/a |         foo=newbar""").strip().split('\n') | 
|---|
| 1462 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1463 | n/a |         parser.read_file(lines) | 
|---|
| 1464 | n/a |         self.assertIn("Foo Bar", parser) | 
|---|
| 1465 | n/a |         self.assertIn("foo", parser["Foo Bar"]) | 
|---|
| 1466 | n/a |         self.assertEqual(parser["Foo Bar"]["foo"], "newbar") | 
|---|
| 1467 | n/a |  | 
|---|
| 1468 | n/a |     def test_readline_generator(self): | 
|---|
| 1469 | n/a |         """Issue #11670.""" | 
|---|
| 1470 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1471 | n/a |         with self.assertRaises(TypeError): | 
|---|
| 1472 | n/a |             parser.read_file(FakeFile()) | 
|---|
| 1473 | n/a |         parser.read_file(readline_generator(FakeFile())) | 
|---|
| 1474 | n/a |         self.assertIn("Foo Bar", parser) | 
|---|
| 1475 | n/a |         self.assertIn("foo", parser["Foo Bar"]) | 
|---|
| 1476 | n/a |         self.assertEqual(parser["Foo Bar"]["foo"], "newbar") | 
|---|
| 1477 | n/a |  | 
|---|
| 1478 | n/a |     def test_source_as_bytes(self): | 
|---|
| 1479 | n/a |         """Issue #18260.""" | 
|---|
| 1480 | n/a |         lines = textwrap.dedent(""" | 
|---|
| 1481 | n/a |         [badbad] | 
|---|
| 1482 | n/a |         [badbad]""").strip().split('\n') | 
|---|
| 1483 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1484 | n/a |         with self.assertRaises(configparser.DuplicateSectionError) as dse: | 
|---|
| 1485 | n/a |             parser.read_file(lines, source=b"badbad") | 
|---|
| 1486 | n/a |         self.assertEqual( | 
|---|
| 1487 | n/a |             str(dse.exception), | 
|---|
| 1488 | n/a |             "While reading from b'badbad' [line  2]: section 'badbad' " | 
|---|
| 1489 | n/a |             "already exists" | 
|---|
| 1490 | n/a |         ) | 
|---|
| 1491 | n/a |         lines = textwrap.dedent(""" | 
|---|
| 1492 | n/a |         [badbad] | 
|---|
| 1493 | n/a |         bad = bad | 
|---|
| 1494 | n/a |         bad = bad""").strip().split('\n') | 
|---|
| 1495 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1496 | n/a |         with self.assertRaises(configparser.DuplicateOptionError) as dse: | 
|---|
| 1497 | n/a |             parser.read_file(lines, source=b"badbad") | 
|---|
| 1498 | n/a |         self.assertEqual( | 
|---|
| 1499 | n/a |             str(dse.exception), | 
|---|
| 1500 | n/a |             "While reading from b'badbad' [line  3]: option 'bad' in section " | 
|---|
| 1501 | n/a |             "'badbad' already exists" | 
|---|
| 1502 | n/a |         ) | 
|---|
| 1503 | n/a |         lines = textwrap.dedent(""" | 
|---|
| 1504 | n/a |         [badbad] | 
|---|
| 1505 | n/a |         = bad""").strip().split('\n') | 
|---|
| 1506 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1507 | n/a |         with self.assertRaises(configparser.ParsingError) as dse: | 
|---|
| 1508 | n/a |             parser.read_file(lines, source=b"badbad") | 
|---|
| 1509 | n/a |         self.assertEqual( | 
|---|
| 1510 | n/a |             str(dse.exception), | 
|---|
| 1511 | n/a |             "Source contains parsing errors: b'badbad'\n\t[line  2]: '= bad'" | 
|---|
| 1512 | n/a |         ) | 
|---|
| 1513 | n/a |         lines = textwrap.dedent(""" | 
|---|
| 1514 | n/a |         [badbad | 
|---|
| 1515 | n/a |         bad = bad""").strip().split('\n') | 
|---|
| 1516 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1517 | n/a |         with self.assertRaises(configparser.MissingSectionHeaderError) as dse: | 
|---|
| 1518 | n/a |             parser.read_file(lines, source=b"badbad") | 
|---|
| 1519 | n/a |         self.assertEqual( | 
|---|
| 1520 | n/a |             str(dse.exception), | 
|---|
| 1521 | n/a |             "File contains no section headers.\nfile: b'badbad', line: 1\n" | 
|---|
| 1522 | n/a |             "'[badbad'" | 
|---|
| 1523 | n/a |         ) | 
|---|
| 1524 | n/a |  | 
|---|
| 1525 | n/a |  | 
|---|
| 1526 | n/a | class CoverageOneHundredTestCase(unittest.TestCase): | 
|---|
| 1527 | n/a |     """Covers edge cases in the codebase.""" | 
|---|
| 1528 | n/a |  | 
|---|
| 1529 | n/a |     def test_duplicate_option_error(self): | 
|---|
| 1530 | n/a |         error = configparser.DuplicateOptionError('section', 'option') | 
|---|
| 1531 | n/a |         self.assertEqual(error.section, 'section') | 
|---|
| 1532 | n/a |         self.assertEqual(error.option, 'option') | 
|---|
| 1533 | n/a |         self.assertEqual(error.source, None) | 
|---|
| 1534 | n/a |         self.assertEqual(error.lineno, None) | 
|---|
| 1535 | n/a |         self.assertEqual(error.args, ('section', 'option', None, None)) | 
|---|
| 1536 | n/a |         self.assertEqual(str(error), "Option 'option' in section 'section' " | 
|---|
| 1537 | n/a |                                      "already exists") | 
|---|
| 1538 | n/a |  | 
|---|
| 1539 | n/a |     def test_interpolation_depth_error(self): | 
|---|
| 1540 | n/a |         error = configparser.InterpolationDepthError('option', 'section', | 
|---|
| 1541 | n/a |                                                      'rawval') | 
|---|
| 1542 | n/a |         self.assertEqual(error.args, ('option', 'section', 'rawval')) | 
|---|
| 1543 | n/a |         self.assertEqual(error.option, 'option') | 
|---|
| 1544 | n/a |         self.assertEqual(error.section, 'section') | 
|---|
| 1545 | n/a |  | 
|---|
| 1546 | n/a |     def test_parsing_error(self): | 
|---|
| 1547 | n/a |         with self.assertRaises(ValueError) as cm: | 
|---|
| 1548 | n/a |             configparser.ParsingError() | 
|---|
| 1549 | n/a |         self.assertEqual(str(cm.exception), "Required argument `source' not " | 
|---|
| 1550 | n/a |                                             "given.") | 
|---|
| 1551 | n/a |         with self.assertRaises(ValueError) as cm: | 
|---|
| 1552 | n/a |             configparser.ParsingError(source='source', filename='filename') | 
|---|
| 1553 | n/a |         self.assertEqual(str(cm.exception), "Cannot specify both `filename' " | 
|---|
| 1554 | n/a |                                             "and `source'. Use `source'.") | 
|---|
| 1555 | n/a |         error = configparser.ParsingError(filename='source') | 
|---|
| 1556 | n/a |         self.assertEqual(error.source, 'source') | 
|---|
| 1557 | n/a |         with warnings.catch_warnings(record=True) as w: | 
|---|
| 1558 | n/a |             warnings.simplefilter("always", DeprecationWarning) | 
|---|
| 1559 | n/a |             self.assertEqual(error.filename, 'source') | 
|---|
| 1560 | n/a |             error.filename = 'filename' | 
|---|
| 1561 | n/a |             self.assertEqual(error.source, 'filename') | 
|---|
| 1562 | n/a |         for warning in w: | 
|---|
| 1563 | n/a |             self.assertTrue(warning.category is DeprecationWarning) | 
|---|
| 1564 | n/a |  | 
|---|
| 1565 | n/a |     def test_interpolation_validation(self): | 
|---|
| 1566 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1567 | n/a |         parser.read_string(""" | 
|---|
| 1568 | n/a |             [section] | 
|---|
| 1569 | n/a |             invalid_percent = % | 
|---|
| 1570 | n/a |             invalid_reference = %(() | 
|---|
| 1571 | n/a |             invalid_variable = %(does_not_exist)s | 
|---|
| 1572 | n/a |         """) | 
|---|
| 1573 | n/a |         with self.assertRaises(configparser.InterpolationSyntaxError) as cm: | 
|---|
| 1574 | n/a |             parser['section']['invalid_percent'] | 
|---|
| 1575 | n/a |         self.assertEqual(str(cm.exception), "'%' must be followed by '%' or " | 
|---|
| 1576 | n/a |                                             "'(', found: '%'") | 
|---|
| 1577 | n/a |         with self.assertRaises(configparser.InterpolationSyntaxError) as cm: | 
|---|
| 1578 | n/a |             parser['section']['invalid_reference'] | 
|---|
| 1579 | n/a |         self.assertEqual(str(cm.exception), "bad interpolation variable " | 
|---|
| 1580 | n/a |                                             "reference '%(()'") | 
|---|
| 1581 | n/a |  | 
|---|
| 1582 | n/a |     def test_readfp_deprecation(self): | 
|---|
| 1583 | n/a |         sio = io.StringIO(""" | 
|---|
| 1584 | n/a |         [section] | 
|---|
| 1585 | n/a |         option = value | 
|---|
| 1586 | n/a |         """) | 
|---|
| 1587 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1588 | n/a |         with warnings.catch_warnings(record=True) as w: | 
|---|
| 1589 | n/a |             warnings.simplefilter("always", DeprecationWarning) | 
|---|
| 1590 | n/a |             parser.readfp(sio, filename='StringIO') | 
|---|
| 1591 | n/a |         for warning in w: | 
|---|
| 1592 | n/a |             self.assertTrue(warning.category is DeprecationWarning) | 
|---|
| 1593 | n/a |         self.assertEqual(len(parser), 2) | 
|---|
| 1594 | n/a |         self.assertEqual(parser['section']['option'], 'value') | 
|---|
| 1595 | n/a |  | 
|---|
| 1596 | n/a |     def test_safeconfigparser_deprecation(self): | 
|---|
| 1597 | n/a |         with warnings.catch_warnings(record=True) as w: | 
|---|
| 1598 | n/a |             warnings.simplefilter("always", DeprecationWarning) | 
|---|
| 1599 | n/a |             parser = configparser.SafeConfigParser() | 
|---|
| 1600 | n/a |         for warning in w: | 
|---|
| 1601 | n/a |             self.assertTrue(warning.category is DeprecationWarning) | 
|---|
| 1602 | n/a |  | 
|---|
| 1603 | n/a |     def test_sectionproxy_repr(self): | 
|---|
| 1604 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1605 | n/a |         parser.read_string(""" | 
|---|
| 1606 | n/a |             [section] | 
|---|
| 1607 | n/a |             key = value | 
|---|
| 1608 | n/a |         """) | 
|---|
| 1609 | n/a |         self.assertEqual(repr(parser['section']), '<Section: section>') | 
|---|
| 1610 | n/a |  | 
|---|
| 1611 | n/a |     def test_inconsistent_converters_state(self): | 
|---|
| 1612 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1613 | n/a |         import decimal | 
|---|
| 1614 | n/a |         parser.converters['decimal'] = decimal.Decimal | 
|---|
| 1615 | n/a |         parser.read_string(""" | 
|---|
| 1616 | n/a |             [s1] | 
|---|
| 1617 | n/a |             one = 1 | 
|---|
| 1618 | n/a |             [s2] | 
|---|
| 1619 | n/a |             two = 2 | 
|---|
| 1620 | n/a |         """) | 
|---|
| 1621 | n/a |         self.assertIn('decimal', parser.converters) | 
|---|
| 1622 | n/a |         self.assertEqual(parser.getdecimal('s1', 'one'), 1) | 
|---|
| 1623 | n/a |         self.assertEqual(parser.getdecimal('s2', 'two'), 2) | 
|---|
| 1624 | n/a |         self.assertEqual(parser['s1'].getdecimal('one'), 1) | 
|---|
| 1625 | n/a |         self.assertEqual(parser['s2'].getdecimal('two'), 2) | 
|---|
| 1626 | n/a |         del parser.getdecimal | 
|---|
| 1627 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1628 | n/a |             parser.getdecimal('s1', 'one') | 
|---|
| 1629 | n/a |         self.assertIn('decimal', parser.converters) | 
|---|
| 1630 | n/a |         del parser.converters['decimal'] | 
|---|
| 1631 | n/a |         self.assertNotIn('decimal', parser.converters) | 
|---|
| 1632 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1633 | n/a |             parser.getdecimal('s1', 'one') | 
|---|
| 1634 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1635 | n/a |             parser['s1'].getdecimal('one') | 
|---|
| 1636 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1637 | n/a |             parser['s2'].getdecimal('two') | 
|---|
| 1638 | n/a |  | 
|---|
| 1639 | n/a |  | 
|---|
| 1640 | n/a | class ExceptionPicklingTestCase(unittest.TestCase): | 
|---|
| 1641 | n/a |     """Tests for issue #13760: ConfigParser exceptions are not picklable.""" | 
|---|
| 1642 | n/a |  | 
|---|
| 1643 | n/a |     def test_error(self): | 
|---|
| 1644 | n/a |         import pickle | 
|---|
| 1645 | n/a |         e1 = configparser.Error('value') | 
|---|
| 1646 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1647 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1648 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1649 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1650 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1651 | n/a |  | 
|---|
| 1652 | n/a |     def test_nosectionerror(self): | 
|---|
| 1653 | n/a |         import pickle | 
|---|
| 1654 | n/a |         e1 = configparser.NoSectionError('section') | 
|---|
| 1655 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1656 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1657 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1658 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1659 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1660 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1661 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1662 | n/a |  | 
|---|
| 1663 | n/a |     def test_nooptionerror(self): | 
|---|
| 1664 | n/a |         import pickle | 
|---|
| 1665 | n/a |         e1 = configparser.NoOptionError('option', 'section') | 
|---|
| 1666 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1667 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1668 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1669 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1670 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1671 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1672 | n/a |             self.assertEqual(e1.option, e2.option) | 
|---|
| 1673 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1674 | n/a |  | 
|---|
| 1675 | n/a |     def test_duplicatesectionerror(self): | 
|---|
| 1676 | n/a |         import pickle | 
|---|
| 1677 | n/a |         e1 = configparser.DuplicateSectionError('section', 'source', 123) | 
|---|
| 1678 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1679 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1680 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1681 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1682 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1683 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1684 | n/a |             self.assertEqual(e1.source, e2.source) | 
|---|
| 1685 | n/a |             self.assertEqual(e1.lineno, e2.lineno) | 
|---|
| 1686 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1687 | n/a |  | 
|---|
| 1688 | n/a |     def test_duplicateoptionerror(self): | 
|---|
| 1689 | n/a |         import pickle | 
|---|
| 1690 | n/a |         e1 = configparser.DuplicateOptionError('section', 'option', 'source', | 
|---|
| 1691 | n/a |             123) | 
|---|
| 1692 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1693 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1694 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1695 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1696 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1697 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1698 | n/a |             self.assertEqual(e1.option, e2.option) | 
|---|
| 1699 | n/a |             self.assertEqual(e1.source, e2.source) | 
|---|
| 1700 | n/a |             self.assertEqual(e1.lineno, e2.lineno) | 
|---|
| 1701 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1702 | n/a |  | 
|---|
| 1703 | n/a |     def test_interpolationerror(self): | 
|---|
| 1704 | n/a |         import pickle | 
|---|
| 1705 | n/a |         e1 = configparser.InterpolationError('option', 'section', 'msg') | 
|---|
| 1706 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1707 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1708 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1709 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1710 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1711 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1712 | n/a |             self.assertEqual(e1.option, e2.option) | 
|---|
| 1713 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1714 | n/a |  | 
|---|
| 1715 | n/a |     def test_interpolationmissingoptionerror(self): | 
|---|
| 1716 | n/a |         import pickle | 
|---|
| 1717 | n/a |         e1 = configparser.InterpolationMissingOptionError('option', 'section', | 
|---|
| 1718 | n/a |             'rawval', 'reference') | 
|---|
| 1719 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1720 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1721 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1722 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1723 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1724 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1725 | n/a |             self.assertEqual(e1.option, e2.option) | 
|---|
| 1726 | n/a |             self.assertEqual(e1.reference, e2.reference) | 
|---|
| 1727 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1728 | n/a |  | 
|---|
| 1729 | n/a |     def test_interpolationsyntaxerror(self): | 
|---|
| 1730 | n/a |         import pickle | 
|---|
| 1731 | n/a |         e1 = configparser.InterpolationSyntaxError('option', 'section', 'msg') | 
|---|
| 1732 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1733 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1734 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1735 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1736 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1737 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1738 | n/a |             self.assertEqual(e1.option, e2.option) | 
|---|
| 1739 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1740 | n/a |  | 
|---|
| 1741 | n/a |     def test_interpolationdeptherror(self): | 
|---|
| 1742 | n/a |         import pickle | 
|---|
| 1743 | n/a |         e1 = configparser.InterpolationDepthError('option', 'section', | 
|---|
| 1744 | n/a |             'rawval') | 
|---|
| 1745 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1746 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1747 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1748 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1749 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1750 | n/a |             self.assertEqual(e1.section, e2.section) | 
|---|
| 1751 | n/a |             self.assertEqual(e1.option, e2.option) | 
|---|
| 1752 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1753 | n/a |  | 
|---|
| 1754 | n/a |     def test_parsingerror(self): | 
|---|
| 1755 | n/a |         import pickle | 
|---|
| 1756 | n/a |         e1 = configparser.ParsingError('source') | 
|---|
| 1757 | n/a |         e1.append(1, 'line1') | 
|---|
| 1758 | n/a |         e1.append(2, 'line2') | 
|---|
| 1759 | n/a |         e1.append(3, 'line3') | 
|---|
| 1760 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1761 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1762 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1763 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1764 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1765 | n/a |             self.assertEqual(e1.source, e2.source) | 
|---|
| 1766 | n/a |             self.assertEqual(e1.errors, e2.errors) | 
|---|
| 1767 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1768 | n/a |         e1 = configparser.ParsingError(filename='filename') | 
|---|
| 1769 | n/a |         e1.append(1, 'line1') | 
|---|
| 1770 | n/a |         e1.append(2, 'line2') | 
|---|
| 1771 | n/a |         e1.append(3, 'line3') | 
|---|
| 1772 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1773 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1774 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1775 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1776 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1777 | n/a |             self.assertEqual(e1.source, e2.source) | 
|---|
| 1778 | n/a |             self.assertEqual(e1.errors, e2.errors) | 
|---|
| 1779 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1780 | n/a |  | 
|---|
| 1781 | n/a |     def test_missingsectionheadererror(self): | 
|---|
| 1782 | n/a |         import pickle | 
|---|
| 1783 | n/a |         e1 = configparser.MissingSectionHeaderError('filename', 123, 'line') | 
|---|
| 1784 | n/a |         for proto in range(pickle.HIGHEST_PROTOCOL + 1): | 
|---|
| 1785 | n/a |             pickled = pickle.dumps(e1, proto) | 
|---|
| 1786 | n/a |             e2 = pickle.loads(pickled) | 
|---|
| 1787 | n/a |             self.assertEqual(e1.message, e2.message) | 
|---|
| 1788 | n/a |             self.assertEqual(e1.args, e2.args) | 
|---|
| 1789 | n/a |             self.assertEqual(e1.line, e2.line) | 
|---|
| 1790 | n/a |             self.assertEqual(e1.source, e2.source) | 
|---|
| 1791 | n/a |             self.assertEqual(e1.lineno, e2.lineno) | 
|---|
| 1792 | n/a |             self.assertEqual(repr(e1), repr(e2)) | 
|---|
| 1793 | n/a |  | 
|---|
| 1794 | n/a |  | 
|---|
| 1795 | n/a | class InlineCommentStrippingTestCase(unittest.TestCase): | 
|---|
| 1796 | n/a |     """Tests for issue #14590: ConfigParser doesn't strip inline comment when | 
|---|
| 1797 | n/a |     delimiter occurs earlier without preceding space..""" | 
|---|
| 1798 | n/a |  | 
|---|
| 1799 | n/a |     def test_stripping(self): | 
|---|
| 1800 | n/a |         cfg = configparser.ConfigParser(inline_comment_prefixes=(';', '#', | 
|---|
| 1801 | n/a |                 '//')) | 
|---|
| 1802 | n/a |         cfg.read_string(""" | 
|---|
| 1803 | n/a |         [section] | 
|---|
| 1804 | n/a |         k1 = v1;still v1 | 
|---|
| 1805 | n/a |         k2 = v2 ;a comment | 
|---|
| 1806 | n/a |         k3 = v3 ; also a comment | 
|---|
| 1807 | n/a |         k4 = v4;still v4 ;a comment | 
|---|
| 1808 | n/a |         k5 = v5;still v5 ; also a comment | 
|---|
| 1809 | n/a |         k6 = v6;still v6; and still v6 ;a comment | 
|---|
| 1810 | n/a |         k7 = v7;still v7; and still v7 ; also a comment | 
|---|
| 1811 | n/a |  | 
|---|
| 1812 | n/a |         [multiprefix] | 
|---|
| 1813 | n/a |         k1 = v1;still v1 #a comment ; yeah, pretty much | 
|---|
| 1814 | n/a |         k2 = v2 // this already is a comment ; continued | 
|---|
| 1815 | n/a |         k3 = v3;#//still v3# and still v3 ; a comment | 
|---|
| 1816 | n/a |         """) | 
|---|
| 1817 | n/a |         s = cfg['section'] | 
|---|
| 1818 | n/a |         self.assertEqual(s['k1'], 'v1;still v1') | 
|---|
| 1819 | n/a |         self.assertEqual(s['k2'], 'v2') | 
|---|
| 1820 | n/a |         self.assertEqual(s['k3'], 'v3') | 
|---|
| 1821 | n/a |         self.assertEqual(s['k4'], 'v4;still v4') | 
|---|
| 1822 | n/a |         self.assertEqual(s['k5'], 'v5;still v5') | 
|---|
| 1823 | n/a |         self.assertEqual(s['k6'], 'v6;still v6; and still v6') | 
|---|
| 1824 | n/a |         self.assertEqual(s['k7'], 'v7;still v7; and still v7') | 
|---|
| 1825 | n/a |         s = cfg['multiprefix'] | 
|---|
| 1826 | n/a |         self.assertEqual(s['k1'], 'v1;still v1') | 
|---|
| 1827 | n/a |         self.assertEqual(s['k2'], 'v2') | 
|---|
| 1828 | n/a |         self.assertEqual(s['k3'], 'v3;#//still v3# and still v3') | 
|---|
| 1829 | n/a |  | 
|---|
| 1830 | n/a |  | 
|---|
| 1831 | n/a | class ExceptionContextTestCase(unittest.TestCase): | 
|---|
| 1832 | n/a |     """ Test that implementation details doesn't leak | 
|---|
| 1833 | n/a |     through raising exceptions. """ | 
|---|
| 1834 | n/a |  | 
|---|
| 1835 | n/a |     def test_get_basic_interpolation(self): | 
|---|
| 1836 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1837 | n/a |         parser.read_string(""" | 
|---|
| 1838 | n/a |         [Paths] | 
|---|
| 1839 | n/a |         home_dir: /Users | 
|---|
| 1840 | n/a |         my_dir: %(home_dir1)s/lumberjack | 
|---|
| 1841 | n/a |         my_pictures: %(my_dir)s/Pictures | 
|---|
| 1842 | n/a |         """) | 
|---|
| 1843 | n/a |         cm = self.assertRaises(configparser.InterpolationMissingOptionError) | 
|---|
| 1844 | n/a |         with cm: | 
|---|
| 1845 | n/a |             parser.get('Paths', 'my_dir') | 
|---|
| 1846 | n/a |         self.assertIs(cm.exception.__suppress_context__, True) | 
|---|
| 1847 | n/a |  | 
|---|
| 1848 | n/a |     def test_get_extended_interpolation(self): | 
|---|
| 1849 | n/a |         parser = configparser.ConfigParser( | 
|---|
| 1850 | n/a |           interpolation=configparser.ExtendedInterpolation()) | 
|---|
| 1851 | n/a |         parser.read_string(""" | 
|---|
| 1852 | n/a |         [Paths] | 
|---|
| 1853 | n/a |         home_dir: /Users | 
|---|
| 1854 | n/a |         my_dir: ${home_dir1}/lumberjack | 
|---|
| 1855 | n/a |         my_pictures: ${my_dir}/Pictures | 
|---|
| 1856 | n/a |         """) | 
|---|
| 1857 | n/a |         cm = self.assertRaises(configparser.InterpolationMissingOptionError) | 
|---|
| 1858 | n/a |         with cm: | 
|---|
| 1859 | n/a |             parser.get('Paths', 'my_dir') | 
|---|
| 1860 | n/a |         self.assertIs(cm.exception.__suppress_context__, True) | 
|---|
| 1861 | n/a |  | 
|---|
| 1862 | n/a |     def test_missing_options(self): | 
|---|
| 1863 | n/a |         parser = configparser.ConfigParser() | 
|---|
| 1864 | n/a |         parser.read_string(""" | 
|---|
| 1865 | n/a |         [Paths] | 
|---|
| 1866 | n/a |         home_dir: /Users | 
|---|
| 1867 | n/a |         """) | 
|---|
| 1868 | n/a |         with self.assertRaises(configparser.NoSectionError) as cm: | 
|---|
| 1869 | n/a |             parser.options('test') | 
|---|
| 1870 | n/a |         self.assertIs(cm.exception.__suppress_context__, True) | 
|---|
| 1871 | n/a |  | 
|---|
| 1872 | n/a |     def test_missing_section(self): | 
|---|
| 1873 | n/a |         config = configparser.ConfigParser() | 
|---|
| 1874 | n/a |         with self.assertRaises(configparser.NoSectionError) as cm: | 
|---|
| 1875 | n/a |             config.set('Section1', 'an_int', '15') | 
|---|
| 1876 | n/a |         self.assertIs(cm.exception.__suppress_context__, True) | 
|---|
| 1877 | n/a |  | 
|---|
| 1878 | n/a |     def test_remove_option(self): | 
|---|
| 1879 | n/a |         config = configparser.ConfigParser() | 
|---|
| 1880 | n/a |         with self.assertRaises(configparser.NoSectionError) as cm: | 
|---|
| 1881 | n/a |             config.remove_option('Section1', 'an_int') | 
|---|
| 1882 | n/a |         self.assertIs(cm.exception.__suppress_context__, True) | 
|---|
| 1883 | n/a |  | 
|---|
| 1884 | n/a |  | 
|---|
| 1885 | n/a | class ConvertersTestCase(BasicTestCase, unittest.TestCase): | 
|---|
| 1886 | n/a |     """Introduced in 3.5, issue #18159.""" | 
|---|
| 1887 | n/a |  | 
|---|
| 1888 | n/a |     config_class = configparser.ConfigParser | 
|---|
| 1889 | n/a |  | 
|---|
| 1890 | n/a |     def newconfig(self, defaults=None): | 
|---|
| 1891 | n/a |         instance = super().newconfig(defaults=defaults) | 
|---|
| 1892 | n/a |         instance.converters['list'] = lambda v: [e.strip() for e in v.split() | 
|---|
| 1893 | n/a |                                                  if e.strip()] | 
|---|
| 1894 | n/a |         return instance | 
|---|
| 1895 | n/a |  | 
|---|
| 1896 | n/a |     def test_converters(self): | 
|---|
| 1897 | n/a |         cfg = self.newconfig() | 
|---|
| 1898 | n/a |         self.assertIn('boolean', cfg.converters) | 
|---|
| 1899 | n/a |         self.assertIn('list', cfg.converters) | 
|---|
| 1900 | n/a |         self.assertIsNone(cfg.converters['int']) | 
|---|
| 1901 | n/a |         self.assertIsNone(cfg.converters['float']) | 
|---|
| 1902 | n/a |         self.assertIsNone(cfg.converters['boolean']) | 
|---|
| 1903 | n/a |         self.assertIsNotNone(cfg.converters['list']) | 
|---|
| 1904 | n/a |         self.assertEqual(len(cfg.converters), 4) | 
|---|
| 1905 | n/a |         with self.assertRaises(ValueError): | 
|---|
| 1906 | n/a |             cfg.converters[''] = lambda v: v | 
|---|
| 1907 | n/a |         with self.assertRaises(ValueError): | 
|---|
| 1908 | n/a |             cfg.converters[None] = lambda v: v | 
|---|
| 1909 | n/a |         cfg.read_string(""" | 
|---|
| 1910 | n/a |         [s] | 
|---|
| 1911 | n/a |         str = string | 
|---|
| 1912 | n/a |         int = 1 | 
|---|
| 1913 | n/a |         float = 0.5 | 
|---|
| 1914 | n/a |         list = a b c d e f g | 
|---|
| 1915 | n/a |         bool = yes | 
|---|
| 1916 | n/a |         """) | 
|---|
| 1917 | n/a |         s = cfg['s'] | 
|---|
| 1918 | n/a |         self.assertEqual(s['str'], 'string') | 
|---|
| 1919 | n/a |         self.assertEqual(s['int'], '1') | 
|---|
| 1920 | n/a |         self.assertEqual(s['float'], '0.5') | 
|---|
| 1921 | n/a |         self.assertEqual(s['list'], 'a b c d e f g') | 
|---|
| 1922 | n/a |         self.assertEqual(s['bool'], 'yes') | 
|---|
| 1923 | n/a |         self.assertEqual(cfg.get('s', 'str'), 'string') | 
|---|
| 1924 | n/a |         self.assertEqual(cfg.get('s', 'int'), '1') | 
|---|
| 1925 | n/a |         self.assertEqual(cfg.get('s', 'float'), '0.5') | 
|---|
| 1926 | n/a |         self.assertEqual(cfg.get('s', 'list'), 'a b c d e f g') | 
|---|
| 1927 | n/a |         self.assertEqual(cfg.get('s', 'bool'), 'yes') | 
|---|
| 1928 | n/a |         self.assertEqual(cfg.get('s', 'str'), 'string') | 
|---|
| 1929 | n/a |         self.assertEqual(cfg.getint('s', 'int'), 1) | 
|---|
| 1930 | n/a |         self.assertEqual(cfg.getfloat('s', 'float'), 0.5) | 
|---|
| 1931 | n/a |         self.assertEqual(cfg.getlist('s', 'list'), ['a', 'b', 'c', 'd', | 
|---|
| 1932 | n/a |                                                     'e', 'f', 'g']) | 
|---|
| 1933 | n/a |         self.assertEqual(cfg.getboolean('s', 'bool'), True) | 
|---|
| 1934 | n/a |         self.assertEqual(s.get('str'), 'string') | 
|---|
| 1935 | n/a |         self.assertEqual(s.getint('int'), 1) | 
|---|
| 1936 | n/a |         self.assertEqual(s.getfloat('float'), 0.5) | 
|---|
| 1937 | n/a |         self.assertEqual(s.getlist('list'), ['a', 'b', 'c', 'd', | 
|---|
| 1938 | n/a |                                              'e', 'f', 'g']) | 
|---|
| 1939 | n/a |         self.assertEqual(s.getboolean('bool'), True) | 
|---|
| 1940 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1941 | n/a |             cfg.getdecimal('s', 'float') | 
|---|
| 1942 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1943 | n/a |             s.getdecimal('float') | 
|---|
| 1944 | n/a |         import decimal | 
|---|
| 1945 | n/a |         cfg.converters['decimal'] = decimal.Decimal | 
|---|
| 1946 | n/a |         self.assertIn('decimal', cfg.converters) | 
|---|
| 1947 | n/a |         self.assertIsNotNone(cfg.converters['decimal']) | 
|---|
| 1948 | n/a |         self.assertEqual(len(cfg.converters), 5) | 
|---|
| 1949 | n/a |         dec0_5 = decimal.Decimal('0.5') | 
|---|
| 1950 | n/a |         self.assertEqual(cfg.getdecimal('s', 'float'), dec0_5) | 
|---|
| 1951 | n/a |         self.assertEqual(s.getdecimal('float'), dec0_5) | 
|---|
| 1952 | n/a |         del cfg.converters['decimal'] | 
|---|
| 1953 | n/a |         self.assertNotIn('decimal', cfg.converters) | 
|---|
| 1954 | n/a |         self.assertEqual(len(cfg.converters), 4) | 
|---|
| 1955 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1956 | n/a |             cfg.getdecimal('s', 'float') | 
|---|
| 1957 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 1958 | n/a |             s.getdecimal('float') | 
|---|
| 1959 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 1960 | n/a |             del cfg.converters['decimal'] | 
|---|
| 1961 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 1962 | n/a |             del cfg.converters[''] | 
|---|
| 1963 | n/a |         with self.assertRaises(KeyError): | 
|---|
| 1964 | n/a |             del cfg.converters[None] | 
|---|
| 1965 | n/a |  | 
|---|
| 1966 | n/a |  | 
|---|
| 1967 | n/a | class BlatantOverrideConvertersTestCase(unittest.TestCase): | 
|---|
| 1968 | n/a |     """What if somebody overrode a getboolean()? We want to make sure that in | 
|---|
| 1969 | n/a |     this case the automatic converters do not kick in.""" | 
|---|
| 1970 | n/a |  | 
|---|
| 1971 | n/a |     config = """ | 
|---|
| 1972 | n/a |         [one] | 
|---|
| 1973 | n/a |         one = false | 
|---|
| 1974 | n/a |         two = false | 
|---|
| 1975 | n/a |         three = long story short | 
|---|
| 1976 | n/a |  | 
|---|
| 1977 | n/a |         [two] | 
|---|
| 1978 | n/a |         one = false | 
|---|
| 1979 | n/a |         two = false | 
|---|
| 1980 | n/a |         three = four | 
|---|
| 1981 | n/a |     """ | 
|---|
| 1982 | n/a |  | 
|---|
| 1983 | n/a |     def test_converters_at_init(self): | 
|---|
| 1984 | n/a |         cfg = configparser.ConfigParser(converters={'len': len}) | 
|---|
| 1985 | n/a |         cfg.read_string(self.config) | 
|---|
| 1986 | n/a |         self._test_len(cfg) | 
|---|
| 1987 | n/a |         self.assertIsNotNone(cfg.converters['len']) | 
|---|
| 1988 | n/a |  | 
|---|
| 1989 | n/a |     def test_inheritance(self): | 
|---|
| 1990 | n/a |         class StrangeConfigParser(configparser.ConfigParser): | 
|---|
| 1991 | n/a |             gettysburg = 'a historic borough in south central Pennsylvania' | 
|---|
| 1992 | n/a |  | 
|---|
| 1993 | n/a |             def getboolean(self, section, option, *, raw=False, vars=None, | 
|---|
| 1994 | n/a |                         fallback=configparser._UNSET): | 
|---|
| 1995 | n/a |                 if section == option: | 
|---|
| 1996 | n/a |                     return True | 
|---|
| 1997 | n/a |                 return super().getboolean(section, option, raw=raw, vars=vars, | 
|---|
| 1998 | n/a |                                           fallback=fallback) | 
|---|
| 1999 | n/a |             def getlen(self, section, option, *, raw=False, vars=None, | 
|---|
| 2000 | n/a |                        fallback=configparser._UNSET): | 
|---|
| 2001 | n/a |                 return self._get_conv(section, option, len, raw=raw, vars=vars, | 
|---|
| 2002 | n/a |                                       fallback=fallback) | 
|---|
| 2003 | n/a |  | 
|---|
| 2004 | n/a |         cfg = StrangeConfigParser() | 
|---|
| 2005 | n/a |         cfg.read_string(self.config) | 
|---|
| 2006 | n/a |         self._test_len(cfg) | 
|---|
| 2007 | n/a |         self.assertIsNone(cfg.converters['len']) | 
|---|
| 2008 | n/a |         self.assertTrue(cfg.getboolean('one', 'one')) | 
|---|
| 2009 | n/a |         self.assertTrue(cfg.getboolean('two', 'two')) | 
|---|
| 2010 | n/a |         self.assertFalse(cfg.getboolean('one', 'two')) | 
|---|
| 2011 | n/a |         self.assertFalse(cfg.getboolean('two', 'one')) | 
|---|
| 2012 | n/a |         cfg.converters['boolean'] = cfg._convert_to_boolean | 
|---|
| 2013 | n/a |         self.assertFalse(cfg.getboolean('one', 'one')) | 
|---|
| 2014 | n/a |         self.assertFalse(cfg.getboolean('two', 'two')) | 
|---|
| 2015 | n/a |         self.assertFalse(cfg.getboolean('one', 'two')) | 
|---|
| 2016 | n/a |         self.assertFalse(cfg.getboolean('two', 'one')) | 
|---|
| 2017 | n/a |  | 
|---|
| 2018 | n/a |     def _test_len(self, cfg): | 
|---|
| 2019 | n/a |         self.assertEqual(len(cfg.converters), 4) | 
|---|
| 2020 | n/a |         self.assertIn('boolean', cfg.converters) | 
|---|
| 2021 | n/a |         self.assertIn('len', cfg.converters) | 
|---|
| 2022 | n/a |         self.assertNotIn('tysburg', cfg.converters) | 
|---|
| 2023 | n/a |         self.assertIsNone(cfg.converters['int']) | 
|---|
| 2024 | n/a |         self.assertIsNone(cfg.converters['float']) | 
|---|
| 2025 | n/a |         self.assertIsNone(cfg.converters['boolean']) | 
|---|
| 2026 | n/a |         self.assertEqual(cfg.getlen('one', 'one'), 5) | 
|---|
| 2027 | n/a |         self.assertEqual(cfg.getlen('one', 'two'), 5) | 
|---|
| 2028 | n/a |         self.assertEqual(cfg.getlen('one', 'three'), 16) | 
|---|
| 2029 | n/a |         self.assertEqual(cfg.getlen('two', 'one'), 5) | 
|---|
| 2030 | n/a |         self.assertEqual(cfg.getlen('two', 'two'), 5) | 
|---|
| 2031 | n/a |         self.assertEqual(cfg.getlen('two', 'three'), 4) | 
|---|
| 2032 | n/a |         self.assertEqual(cfg.getlen('two', 'four', fallback=0), 0) | 
|---|
| 2033 | n/a |         with self.assertRaises(configparser.NoOptionError): | 
|---|
| 2034 | n/a |             cfg.getlen('two', 'four') | 
|---|
| 2035 | n/a |         self.assertEqual(cfg['one'].getlen('one'), 5) | 
|---|
| 2036 | n/a |         self.assertEqual(cfg['one'].getlen('two'), 5) | 
|---|
| 2037 | n/a |         self.assertEqual(cfg['one'].getlen('three'), 16) | 
|---|
| 2038 | n/a |         self.assertEqual(cfg['two'].getlen('one'), 5) | 
|---|
| 2039 | n/a |         self.assertEqual(cfg['two'].getlen('two'), 5) | 
|---|
| 2040 | n/a |         self.assertEqual(cfg['two'].getlen('three'), 4) | 
|---|
| 2041 | n/a |         self.assertEqual(cfg['two'].getlen('four', 0), 0) | 
|---|
| 2042 | n/a |         self.assertEqual(cfg['two'].getlen('four'), None) | 
|---|
| 2043 | n/a |  | 
|---|
| 2044 | n/a |     def test_instance_assignment(self): | 
|---|
| 2045 | n/a |         cfg = configparser.ConfigParser() | 
|---|
| 2046 | n/a |         cfg.getboolean = lambda section, option: True | 
|---|
| 2047 | n/a |         cfg.getlen = lambda section, option: len(cfg[section][option]) | 
|---|
| 2048 | n/a |         cfg.read_string(self.config) | 
|---|
| 2049 | n/a |         self.assertEqual(len(cfg.converters), 3) | 
|---|
| 2050 | n/a |         self.assertIn('boolean', cfg.converters) | 
|---|
| 2051 | n/a |         self.assertNotIn('len', cfg.converters) | 
|---|
| 2052 | n/a |         self.assertIsNone(cfg.converters['int']) | 
|---|
| 2053 | n/a |         self.assertIsNone(cfg.converters['float']) | 
|---|
| 2054 | n/a |         self.assertIsNone(cfg.converters['boolean']) | 
|---|
| 2055 | n/a |         self.assertTrue(cfg.getboolean('one', 'one')) | 
|---|
| 2056 | n/a |         self.assertTrue(cfg.getboolean('two', 'two')) | 
|---|
| 2057 | n/a |         self.assertTrue(cfg.getboolean('one', 'two')) | 
|---|
| 2058 | n/a |         self.assertTrue(cfg.getboolean('two', 'one')) | 
|---|
| 2059 | n/a |         cfg.converters['boolean'] = cfg._convert_to_boolean | 
|---|
| 2060 | n/a |         self.assertFalse(cfg.getboolean('one', 'one')) | 
|---|
| 2061 | n/a |         self.assertFalse(cfg.getboolean('two', 'two')) | 
|---|
| 2062 | n/a |         self.assertFalse(cfg.getboolean('one', 'two')) | 
|---|
| 2063 | n/a |         self.assertFalse(cfg.getboolean('two', 'one')) | 
|---|
| 2064 | n/a |         self.assertEqual(cfg.getlen('one', 'one'), 5) | 
|---|
| 2065 | n/a |         self.assertEqual(cfg.getlen('one', 'two'), 5) | 
|---|
| 2066 | n/a |         self.assertEqual(cfg.getlen('one', 'three'), 16) | 
|---|
| 2067 | n/a |         self.assertEqual(cfg.getlen('two', 'one'), 5) | 
|---|
| 2068 | n/a |         self.assertEqual(cfg.getlen('two', 'two'), 5) | 
|---|
| 2069 | n/a |         self.assertEqual(cfg.getlen('two', 'three'), 4) | 
|---|
| 2070 | n/a |         # If a getter impl is assigned straight to the instance, it won't | 
|---|
| 2071 | n/a |         # be available on the section proxies. | 
|---|
| 2072 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 2073 | n/a |             self.assertEqual(cfg['one'].getlen('one'), 5) | 
|---|
| 2074 | n/a |         with self.assertRaises(AttributeError): | 
|---|
| 2075 | n/a |             self.assertEqual(cfg['two'].getlen('one'), 5) | 
|---|
| 2076 | n/a |  | 
|---|
| 2077 | n/a |  | 
|---|
| 2078 | n/a | class MiscTestCase(unittest.TestCase): | 
|---|
| 2079 | n/a |     def test__all__(self): | 
|---|
| 2080 | n/a |         blacklist = {"Error"} | 
|---|
| 2081 | n/a |         support.check__all__(self, configparser, blacklist=blacklist) | 
|---|
| 2082 | n/a |  | 
|---|
| 2083 | n/a |  | 
|---|
| 2084 | n/a | if __name__ == '__main__': | 
|---|
| 2085 | n/a |     unittest.main() | 
|---|