From ae6d8d728e12e8efd704ba529de1db2eacfb494f Mon Sep 17 00:00:00 2001 From: Paul Tremberth Date: Mon, 30 Jan 2017 16:33:08 +0100 Subject: [PATCH] Support 'True' and 'False' strings as boolean settings values --- scrapy/settings/__init__.py | 16 +++++++++++++--- tests/test_settings/__init__.py | 12 ++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/scrapy/settings/__init__.py b/scrapy/settings/__init__.py index 7b7808959..28446a372 100644 --- a/scrapy/settings/__init__.py +++ b/scrapy/settings/__init__.py @@ -114,8 +114,8 @@ class BaseSettings(MutableMapping): """ Get a setting value as a boolean. - ``1``, ``'1'``, and ``True`` return ``True``, while ``0``, ``'0'``, - ``False`` and ``None`` return ``False``. + ``1``, ``'1'``, `True`` and ``'True'`` return ``True``, + while ``0``, ``'0'``, ``False``, ``'False'`` and ``None`` return ``False``. For example, settings populated through environment variables set to ``'0'`` will return ``False`` when using this method. @@ -126,7 +126,17 @@ class BaseSettings(MutableMapping): :param default: the value to return if no setting is found :type default: any """ - return bool(int(self.get(name, default))) + got = self.get(name, default) + try: + return bool(int(got)) + except ValueError: + if got in ("True", "true"): + return True + if got in ("False", "false"): + return False + raise ValueError("Supported values for boolean settings " + "are 0/1, True/False, '0'/'1', " + "'True'/'False' and 'true'/'false'") def getint(self, name, default=0): """ diff --git a/tests/test_settings/__init__.py b/tests/test_settings/__init__.py index 4acf22cba..863684075 100644 --- a/tests/test_settings/__init__.py +++ b/tests/test_settings/__init__.py @@ -211,9 +211,15 @@ class BaseSettingsTest(unittest.TestCase): 'TEST_ENABLED1': '1', 'TEST_ENABLED2': True, 'TEST_ENABLED3': 1, + 'TEST_ENABLED4': 'True', + 'TEST_ENABLED5': 'true', + 'TEST_ENABLED_WRONG': 'on', 'TEST_DISABLED1': '0', 'TEST_DISABLED2': False, 'TEST_DISABLED3': 0, + 'TEST_DISABLED4': 'False', + 'TEST_DISABLED5': 'false', + 'TEST_DISABLED_WRONG': 'off', 'TEST_INT1': 123, 'TEST_INT2': '123', 'TEST_FLOAT1': 123.45, @@ -231,11 +237,15 @@ class BaseSettingsTest(unittest.TestCase): self.assertTrue(settings.getbool('TEST_ENABLED1')) self.assertTrue(settings.getbool('TEST_ENABLED2')) self.assertTrue(settings.getbool('TEST_ENABLED3')) + self.assertTrue(settings.getbool('TEST_ENABLED4')) + self.assertTrue(settings.getbool('TEST_ENABLED5')) self.assertFalse(settings.getbool('TEST_ENABLEDx')) self.assertTrue(settings.getbool('TEST_ENABLEDx', True)) self.assertFalse(settings.getbool('TEST_DISABLED1')) self.assertFalse(settings.getbool('TEST_DISABLED2')) self.assertFalse(settings.getbool('TEST_DISABLED3')) + self.assertFalse(settings.getbool('TEST_DISABLED4')) + self.assertFalse(settings.getbool('TEST_DISABLED5')) self.assertEqual(settings.getint('TEST_INT1'), 123) self.assertEqual(settings.getint('TEST_INT2'), 123) self.assertEqual(settings.getint('TEST_INTx'), 0) @@ -258,6 +268,8 @@ class BaseSettingsTest(unittest.TestCase): self.assertEqual(settings.getdict('TEST_DICT3'), {}) self.assertEqual(settings.getdict('TEST_DICT3', {'key1': 5}), {'key1': 5}) self.assertRaises(ValueError, settings.getdict, 'TEST_LIST1') + self.assertRaises(ValueError, settings.getbool, 'TEST_ENABLED_WRONG') + self.assertRaises(ValueError, settings.getbool, 'TEST_DISABLED_WRONG') def test_getpriority(self): settings = BaseSettings({'key': 'value'}, priority=99)