diff --git a/Lib/configparser.py b/Lib/configparser.py index 3c452afe8ade485..2d6b1f121d5aeea 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -1222,7 +1222,7 @@ def _unify_values(self, section, vars): def _convert_to_boolean(self, value): """Return a boolean value translating from other types if necessary. """ - if value.lower() not in self.BOOLEAN_STATES: + if value is None or value.lower() not in self.BOOLEAN_STATES: raise ValueError('Not a boolean: %s' % value) return self.BOOLEAN_STATES[value.lower()] diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index 4783943f71a1092..e4034c0ed3b93d8 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -1338,6 +1338,14 @@ def test_other_errors(self): class ConfigParserTestCaseNoValue(ConfigParserTestCase): allow_no_value = True + def test_getboolean_with_no_value(self): + cf = self.fromstring("[section]\noption\n") + + with self.assertRaisesRegex(ValueError, "Not a boolean: None"): + cf.getboolean("section", "option") + with self.assertRaisesRegex(ValueError, "Not a boolean: None"): + cf["section"].getboolean("option") + class NoValueAndExtendedInterpolation(CfgParserTestCaseClass): interpolation = configparser.ExtendedInterpolation() diff --git a/Misc/NEWS.d/next/Library/2026-08-09-22-50-19.gh-issue-155436.gyB8_I.rst b/Misc/NEWS.d/next/Library/2026-08-09-22-50-19.gh-issue-155436.gyB8_I.rst new file mode 100644 index 000000000000000..9fffec26eb8950a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-09-22-50-19.gh-issue-155436.gyB8_I.rst @@ -0,0 +1,3 @@ +:class:`configparser.ConfigParser` now raises :exc:`ValueError` instead of +:exc:`AttributeError` when :meth:`~configparser.ConfigParser.getboolean` is +called on an option without a value while ``allow_no_value=True``.