Index: Lib/ConfigParser.py =================================================================== --- Lib/ConfigParser.py.orig +++ Lib/ConfigParser.py @@ -399,11 +399,10 @@ class RawConfigParser: fp.write("[%s]\n" % section) for (key, value) in self._sections[section].items(): if key != "__name__": - if value is None: - fp.write("%s\n" % (key)) - else: - fp.write("%s = %s\n" % - (key, str(value).replace('\n', '\n\t'))) + if (value is not None) or (self._optcre == self.OPTCRE): + key = " = ".join((key, str(value).replace('\n', '\n\t'))) + fp.write("%s\n" % (key)) + fp.write("\n") def remove_option(self, section, option): Index: Lib/test/test_cfgparser.py =================================================================== --- Lib/test/test_cfgparser.py.orig +++ Lib/test/test_cfgparser.py @@ -493,6 +493,33 @@ class SafeConfigParserTestCaseNoValue(Sa allow_no_value = True +class Issue7005TestCase(unittest.TestCase): + """Test output when None is set() as a value and allow_no_value == False. + + http://bugs.python.org/issue7005 + + """ + + expected_output = "[section]\noption = None\n\n" + + def prepare(self, config_class): + # This is the default, but that's the point. + cp = config_class(allow_no_value=False) + cp.add_section("section") + cp.set("section", "option", None) + sio = StringIO.StringIO() + cp.write(sio) + return sio.getvalue() + + def test_none_as_value_stringified(self): + output = self.prepare(ConfigParser.ConfigParser) + self.assertEqual(output, self.expected_output) + + def test_none_as_value_stringified_raw(self): + output = self.prepare(ConfigParser.RawConfigParser) + self.assertEqual(output, self.expected_output) + + class SortedTestCase(RawConfigParserTestCase): def newconfig(self, defaults=None): self.cf = self.config_class(defaults=defaults, dict_type=SortedDict) @@ -524,6 +551,7 @@ def test_main(): RawConfigParserTestCase, SafeConfigParserTestCase, SortedTestCase, + Issue7005TestCase, SafeConfigParserTestCaseNoValue, )