summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_configparser.py
diff options
context:
space:
mode:
authorŁukasz Langa <lukasz@langa.pl>2014-09-15 09:08:41 (GMT)
committerŁukasz Langa <lukasz@langa.pl>2014-09-15 09:08:41 (GMT)
commitdfdd2f7ef852d3440459d3eefa83a5d6bd5edb2c (patch)
treee0ea5977a56c7c16d9e6ecc831114cf83627ac83 /Lib/test/test_configparser.py
parent34cea14f746481b2d55c64e7b18bd20f176f88e2 (diff)
downloadcpython-dfdd2f7ef852d3440459d3eefa83a5d6bd5edb2c.zip
cpython-dfdd2f7ef852d3440459d3eefa83a5d6bd5edb2c.tar.gz
cpython-dfdd2f7ef852d3440459d3eefa83a5d6bd5edb2c.tar.bz2
Closes #18159: ConfigParser getters not available on SectionProxy
Diffstat (limited to 'Lib/test/test_configparser.py')
-rw-r--r--Lib/test/test_configparser.py223
1 files changed, 223 insertions, 0 deletions
diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py
index b439501..a7c6127 100644
--- a/Lib/test/test_configparser.py
+++ b/Lib/test/test_configparser.py
@@ -1584,6 +1584,34 @@ class CoverageOneHundredTestCase(unittest.TestCase):
""")
self.assertEqual(repr(parser['section']), '<Section: section>')
+ def test_inconsistent_converters_state(self):
+ parser = configparser.ConfigParser()
+ import decimal
+ parser.converters['decimal'] = decimal.Decimal
+ parser.read_string("""
+ [s1]
+ one = 1
+ [s2]
+ two = 2
+ """)
+ self.assertIn('decimal', parser.converters)
+ self.assertEqual(parser.getdecimal('s1', 'one'), 1)
+ self.assertEqual(parser.getdecimal('s2', 'two'), 2)
+ self.assertEqual(parser['s1'].getdecimal('one'), 1)
+ self.assertEqual(parser['s2'].getdecimal('two'), 2)
+ del parser.getdecimal
+ with self.assertRaises(AttributeError):
+ parser.getdecimal('s1', 'one')
+ self.assertIn('decimal', parser.converters)
+ del parser.converters['decimal']
+ self.assertNotIn('decimal', parser.converters)
+ with self.assertRaises(AttributeError):
+ parser.getdecimal('s1', 'one')
+ with self.assertRaises(AttributeError):
+ parser['s1'].getdecimal('one')
+ with self.assertRaises(AttributeError):
+ parser['s2'].getdecimal('two')
+
class ExceptionPicklingTestCase(unittest.TestCase):
"""Tests for issue #13760: ConfigParser exceptions are not picklable."""
@@ -1763,6 +1791,7 @@ class InlineCommentStrippingTestCase(unittest.TestCase):
self.assertEqual(s['k2'], 'v2')
self.assertEqual(s['k3'], 'v3;#//still v3# and still v3')
+
class ExceptionContextTestCase(unittest.TestCase):
""" Test that implementation details doesn't leak
through raising exceptions. """
@@ -1816,5 +1845,199 @@ class ExceptionContextTestCase(unittest.TestCase):
config.remove_option('Section1', 'an_int')
self.assertIs(cm.exception.__suppress_context__, True)
+
+class ConvertersTestCase(BasicTestCase, unittest.TestCase):
+ """Introduced in 3.5, issue #18159."""
+
+ config_class = configparser.ConfigParser
+
+ def newconfig(self, defaults=None):
+ instance = super().newconfig(defaults=defaults)
+ instance.converters['list'] = lambda v: [e.strip() for e in v.split()
+ if e.strip()]
+ return instance
+
+ def test_converters(self):
+ cfg = self.newconfig()
+ self.assertIn('boolean', cfg.converters)
+ self.assertIn('list', cfg.converters)
+ self.assertIsNone(cfg.converters['int'])
+ self.assertIsNone(cfg.converters['float'])
+ self.assertIsNone(cfg.converters['boolean'])
+ self.assertIsNotNone(cfg.converters['list'])
+ self.assertEqual(len(cfg.converters), 4)
+ with self.assertRaises(ValueError):
+ cfg.converters[''] = lambda v: v
+ with self.assertRaises(ValueError):
+ cfg.converters[None] = lambda v: v
+ cfg.read_string("""
+ [s]
+ str = string
+ int = 1
+ float = 0.5
+ list = a b c d e f g
+ bool = yes
+ """)
+ s = cfg['s']
+ self.assertEqual(s['str'], 'string')
+ self.assertEqual(s['int'], '1')
+ self.assertEqual(s['float'], '0.5')
+ self.assertEqual(s['list'], 'a b c d e f g')
+ self.assertEqual(s['bool'], 'yes')
+ self.assertEqual(cfg.get('s', 'str'), 'string')
+ self.assertEqual(cfg.get('s', 'int'), '1')
+ self.assertEqual(cfg.get('s', 'float'), '0.5')
+ self.assertEqual(cfg.get('s', 'list'), 'a b c d e f g')
+ self.assertEqual(cfg.get('s', 'bool'), 'yes')
+ self.assertEqual(cfg.get('s', 'str'), 'string')
+ self.assertEqual(cfg.getint('s', 'int'), 1)
+ self.assertEqual(cfg.getfloat('s', 'float'), 0.5)
+ self.assertEqual(cfg.getlist('s', 'list'), ['a', 'b', 'c', 'd',
+ 'e', 'f', 'g'])
+ self.assertEqual(cfg.getboolean('s', 'bool'), True)
+ self.assertEqual(s.get('str'), 'string')
+ self.assertEqual(s.getint('int'), 1)
+ self.assertEqual(s.getfloat('float'), 0.5)
+ self.assertEqual(s.getlist('list'), ['a', 'b', 'c', 'd',
+ 'e', 'f', 'g'])
+ self.assertEqual(s.getboolean('bool'), True)
+ with self.assertRaises(AttributeError):
+ cfg.getdecimal('s', 'float')
+ with self.assertRaises(AttributeError):
+ s.getdecimal('float')
+ import decimal
+ cfg.converters['decimal'] = decimal.Decimal
+ self.assertIn('decimal', cfg.converters)
+ self.assertIsNotNone(cfg.converters['decimal'])
+ self.assertEqual(len(cfg.converters), 5)
+ dec0_5 = decimal.Decimal('0.5')
+ self.assertEqual(cfg.getdecimal('s', 'float'), dec0_5)
+ self.assertEqual(s.getdecimal('float'), dec0_5)
+ del cfg.converters['decimal']
+ self.assertNotIn('decimal', cfg.converters)
+ self.assertEqual(len(cfg.converters), 4)
+ with self.assertRaises(AttributeError):
+ cfg.getdecimal('s', 'float')
+ with self.assertRaises(AttributeError):
+ s.getdecimal('float')
+ with self.assertRaises(KeyError):
+ del cfg.converters['decimal']
+ with self.assertRaises(KeyError):
+ del cfg.converters['']
+ with self.assertRaises(KeyError):
+ del cfg.converters[None]
+
+
+class BlatantOverrideConvertersTestCase(unittest.TestCase):
+ """What if somebody overrode a getboolean()? We want to make sure that in
+ this case the automatic converters do not kick in."""
+
+ config = """
+ [one]
+ one = false
+ two = false
+ three = long story short
+
+ [two]
+ one = false
+ two = false
+ three = four
+ """
+
+ def test_converters_at_init(self):
+ cfg = configparser.ConfigParser(converters={'len': len})
+ cfg.read_string(self.config)
+ self._test_len(cfg)
+ self.assertIsNotNone(cfg.converters['len'])
+
+ def test_inheritance(self):
+ class StrangeConfigParser(configparser.ConfigParser):
+ gettysburg = 'a historic borough in south central Pennsylvania'
+
+ def getboolean(self, section, option, *, raw=False, vars=None,
+ fallback=configparser._UNSET):
+ if section == option:
+ return True
+ return super().getboolean(section, option, raw=raw, vars=vars,
+ fallback=fallback)
+ def getlen(self, section, option, *, raw=False, vars=None,
+ fallback=configparser._UNSET):
+ return self._get_conv(section, option, len, raw=raw, vars=vars,
+ fallback=fallback)
+
+ cfg = StrangeConfigParser()
+ cfg.read_string(self.config)
+ self._test_len(cfg)
+ self.assertIsNone(cfg.converters['len'])
+ self.assertTrue(cfg.getboolean('one', 'one'))
+ self.assertTrue(cfg.getboolean('two', 'two'))
+ self.assertFalse(cfg.getboolean('one', 'two'))
+ self.assertFalse(cfg.getboolean('two', 'one'))
+ cfg.converters['boolean'] = cfg._convert_to_boolean
+ self.assertFalse(cfg.getboolean('one', 'one'))
+ self.assertFalse(cfg.getboolean('two', 'two'))
+ self.assertFalse(cfg.getboolean('one', 'two'))
+ self.assertFalse(cfg.getboolean('two', 'one'))
+
+ def _test_len(self, cfg):
+ self.assertEqual(len(cfg.converters), 4)
+ self.assertIn('boolean', cfg.converters)
+ self.assertIn('len', cfg.converters)
+ self.assertNotIn('tysburg', cfg.converters)
+ self.assertIsNone(cfg.converters['int'])
+ self.assertIsNone(cfg.converters['float'])
+ self.assertIsNone(cfg.converters['boolean'])
+ self.assertEqual(cfg.getlen('one', 'one'), 5)
+ self.assertEqual(cfg.getlen('one', 'two'), 5)
+ self.assertEqual(cfg.getlen('one', 'three'), 16)
+ self.assertEqual(cfg.getlen('two', 'one'), 5)
+ self.assertEqual(cfg.getlen('two', 'two'), 5)
+ self.assertEqual(cfg.getlen('two', 'three'), 4)
+ self.assertEqual(cfg.getlen('two', 'four', fallback=0), 0)
+ with self.assertRaises(configparser.NoOptionError):
+ cfg.getlen('two', 'four')
+ self.assertEqual(cfg['one'].getlen('one'), 5)
+ self.assertEqual(cfg['one'].getlen('two'), 5)
+ self.assertEqual(cfg['one'].getlen('three'), 16)
+ self.assertEqual(cfg['two'].getlen('one'), 5)
+ self.assertEqual(cfg['two'].getlen('two'), 5)
+ self.assertEqual(cfg['two'].getlen('three'), 4)
+ self.assertEqual(cfg['two'].getlen('four', 0), 0)
+ self.assertEqual(cfg['two'].getlen('four'), None)
+
+ def test_instance_assignment(self):
+ cfg = configparser.ConfigParser()
+ cfg.getboolean = lambda section, option: True
+ cfg.getlen = lambda section, option: len(cfg[section][option])
+ cfg.read_string(self.config)
+ self.assertEqual(len(cfg.converters), 3)
+ self.assertIn('boolean', cfg.converters)
+ self.assertNotIn('len', cfg.converters)
+ self.assertIsNone(cfg.converters['int'])
+ self.assertIsNone(cfg.converters['float'])
+ self.assertIsNone(cfg.converters['boolean'])
+ self.assertTrue(cfg.getboolean('one', 'one'))
+ self.assertTrue(cfg.getboolean('two', 'two'))
+ self.assertTrue(cfg.getboolean('one', 'two'))
+ self.assertTrue(cfg.getboolean('two', 'one'))
+ cfg.converters['boolean'] = cfg._convert_to_boolean
+ self.assertFalse(cfg.getboolean('one', 'one'))
+ self.assertFalse(cfg.getboolean('two', 'two'))
+ self.assertFalse(cfg.getboolean('one', 'two'))
+ self.assertFalse(cfg.getboolean('two', 'one'))
+ self.assertEqual(cfg.getlen('one', 'one'), 5)
+ self.assertEqual(cfg.getlen('one', 'two'), 5)
+ self.assertEqual(cfg.getlen('one', 'three'), 16)
+ self.assertEqual(cfg.getlen('two', 'one'), 5)
+ self.assertEqual(cfg.getlen('two', 'two'), 5)
+ self.assertEqual(cfg.getlen('two', 'three'), 4)
+ # If a getter impl is assigned straight to the instance, it won't
+ # be available on the section proxies.
+ with self.assertRaises(AttributeError):
+ self.assertEqual(cfg['one'].getlen('one'), 5)
+ with self.assertRaises(AttributeError):
+ self.assertEqual(cfg['two'].getlen('one'), 5)
+
+
if __name__ == '__main__':
unittest.main()